Skip to content

Commit 9a396ca

Browse files
committed
fix wine path fetching
1 parent aadf6ad commit 9a396ca

File tree

1 file changed

+111
-11
lines changed

1 file changed

+111
-11
lines changed

src/platform/windows.cpp

Lines changed: 111 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
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

Comments
 (0)