11#include " windows.hpp"
22#include < array>
3+ #include < memory>
4+ #include < sddl.h>
35#include < WinSock2.h>
46#include < fmt/format.h>
57
@@ -16,21 +18,119 @@ namespace wine {
1618 return wine;
1719 }
1820
19- static std::string getTempPath () {
20- wchar_t const * envVars[] = {L" XDG_RUNTIME_DIR" , L" TMPDIR" , L" TMP" , L" TEMP" };
21+ // https://stackoverflow.com/a/28523686
22+ struct heap_delete {
23+ using pointer = LPVOID;
24+
25+ void operator ()(LPVOID p) const {
26+ ::HeapFree (::GetProcessHeap(), 0, p);
27+ }
28+ };
29+
30+ struct handle_delete {
31+ using pointer = HANDLE;
32+
33+ void operator ()(HANDLE p) const {
34+ ::CloseHandle (p);
35+ }
36+ };
37+
38+ using heap_unique_ptr = std::unique_ptr<LPVOID, heap_delete>;
39+ using handle_unique_ptr = std::unique_ptr<HANDLE, handle_delete>;
40+ using uid_t = uint32_t ;
41+
42+ static BOOL GetUserSID (HANDLE token, PSID* sid) {
43+ if (token == nullptr || token == INVALID_HANDLE_VALUE) {
44+ SetLastError (ERROR_INVALID_PARAMETER);
45+ return FALSE ;
46+ }
47+
48+ DWORD tokenInformationLength = 0 ;
49+ ::GetTokenInformation (token, TokenUser, nullptr , 0 , &tokenInformationLength);
50+ if (GetLastError () != ERROR_INSUFFICIENT_BUFFER) return FALSE ;
51+
52+ heap_unique_ptr data (::HeapAlloc (::GetProcessHeap (), HEAP_ZERO_MEMORY, tokenInformationLength));
53+ if (data.get () == nullptr ) return FALSE ;
54+
55+ BOOL getTokenInfo = ::GetTokenInformation (
56+ token, TokenUser,
57+ data.get (), tokenInformationLength,
58+ &tokenInformationLength
59+ );
60+ if (!getTokenInfo) return FALSE ;
61+
62+ PTOKEN_USER pTokenUser = static_cast <PTOKEN_USER>(data.get ());
63+ DWORD sidLength = ::GetLengthSid (pTokenUser->User .Sid );
64+ heap_unique_ptr sidPtr (::HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sidLength));
65+ PSID sidL = sidPtr.get ();
66+ if (sidL == nullptr ) return FALSE ;
67+
68+ BOOL copySid = ::CopySid (sidLength, sidL, pTokenUser->User .Sid );
69+ if (!copySid) return FALSE ;
70+ if (!IsValidSid (sidL)) return FALSE ;
71+
72+ *sid = sidL;
73+ sidPtr.release ();
74+ return TRUE ;
75+ }
76+
77+ static uid_t GetUID (HANDLE token) {
78+ PSID sid = nullptr ;
79+ BOOL getSID = GetUserSID (token, &sid);
80+ if (!getSID || !sid) {
81+ return -1 ;
82+ }
83+
84+ heap_unique_ptr sidPtr (sid);
85+ LPWSTR stringSid = nullptr ;
86+ BOOL convertSid = ::ConvertSidToStringSidW (sid, &stringSid);
87+ if (!convertSid) {
88+ return -1 ;
89+ }
90+
91+ uid_t ret = -1 ;
92+ LPCWSTR p = ::wcsrchr (stringSid, L' -' );
93+ if (p && ::iswdigit (p[1 ])) {
94+ ++p;
95+ ret = ::_wtoi (p);
96+ }
2197
98+ ::LocalFree (stringSid);
99+ return ret;
100+ }
101+
102+ static uid_t getuid () {
103+ HANDLE process = ::GetCurrentProcess ();
104+ handle_unique_ptr processPtr (process);
105+ HANDLE token = nullptr ;
106+ BOOL openToken = ::OpenProcessToken (
107+ process, TOKEN_READ | TOKEN_QUERY_SOURCE, &token
108+ );
109+ if (!openToken) {
110+ return -1 ;
111+ }
112+ handle_unique_ptr tokenPtr (token);
113+ uid_t ret = GetUID (token);
114+ return ret;
115+ }
116+
117+ static std::string getTempPath () {
22118 wchar_t buffer[MAX_PATH];
23- for (auto const & var : envVars) {
24- DWORD result = ::GetEnvironmentVariableW (var, buffer, MAX_PATH);
25- if (result > 0 && result < MAX_PATH) {
26- int len = WideCharToMultiByte (CP_UTF8, 0 , buffer, result, nullptr , 0 , nullptr , nullptr );
27- std::string path (len, ' \0 ' );
28- WideCharToMultiByte (CP_UTF8, 0 , buffer, result, path.data (), len, nullptr , nullptr );
29- return path;
30- }
119+ DWORD result = ::GetEnvironmentVariableW (L" XDG_RUNTIME_DIR" , buffer, MAX_PATH);
120+ if (result > 0 && result < MAX_PATH) {
121+ int len = WideCharToMultiByte (CP_UTF8, 0 , buffer, result, nullptr , 0 , nullptr , nullptr );
122+ std::string path (len, ' \0 ' );
123+ WideCharToMultiByte (CP_UTF8, 0 , buffer, result, path.data (), len, nullptr , nullptr );
124+ return path;
125+ }
126+
127+ // try to get userid
128+ auto uid = getuid ();
129+ if (uid != static_cast <uid_t >(-1 )) {
130+ return fmt::format (" /run/user/{}" , uid);
31131 }
32132
33- return " /tmp " ;
133+ return " /run/user/1000 " ; // common default
34134 }
35135
36136 static std::array<std::string, 4 > const & getCandidatePaths () {
0 commit comments