Hello,
This is my first time posting to this mailing list. (This email is a bit long... sorry!) I am a developer writing Win32 code using Wine on Debian Linux. I tried to use the Win32 API function GetTempPath2W(), but my Wine version does not support it. I checked out the Wine source code and found GetTempPathW() here: dlls/kernelbase/file.c ... but did not find GetTempPath2W().
First, if this function is already in the pipeline (another feature branch, etc.), please let me know... and ignore the rest of this email! :-)
From GetTempPathW() docs: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gette... "Note: Apps should call GetTempPath2 instead of GetTempPath."
From GetTempPath2W() docs: "When calling this function from a process running as SYSTEM it will return the path C:\Windows\SystemTemp"
The implementation looks rather straightforward except this part: "process running as SYSTEM". How to detect this? I found a good blog post from (the legend) Raymond Chen: https://devblogs.microsoft.com/oldnewthing/20210106-00/?p=104669
Sample code looks like this: << #include <wil/token_helpers.h>
bool DoesTokenRepresentSid(HANDLE token, WELL_KNOWN_SID_TYPE type) { // maps to GetTokenInformation(token, TokenUser, ...); auto user = wil::get_token_information<TOKEN_USER>(token); return !!IsWellKnownSid(user->User.Sid, type); }
bool IsCurrentProcessRunningAsSystem() { return DoesTokenRepresentSid(GetCurrentProcessToken(), WinLocalSystemSid); }
bool IsCurrentThreadRunningAsSystem() { return DoesTokenRepresentSid(GetCurrentThreadEffectiveToken(), WinLocalSystemSid); }
Reading the WIL source code on GitHub, I understand the required Win32 calls. In short, I plan to re-write the above same code using pure Win32 code (remove the WIL requirement).
My questions:
1. Do you agree with Raymond Chen's technique for Wine source code? (Or: Is there a better way to do it for Wine source code?) 2. Should my SYSTEM account test use IsCurrentProcessRunningAsSystem() or IsCurrentThreadRunningAsSystem()? If I read the official docs literally, I think "process" not "thread". Please advise. 3. Reading the WIL code: TOKEN_INFORMATION_CLASS TokenUser appears to require this pattern: 1. Call GetTokenInformation() to get required buffer size 2. malloc buffer 3. Call GetTokenInformation() again with buffer 4. Check: WinLocalSystemSid == ((TOKEN_USER *) buffer)->User.Sid 5. free buffer 1. Is there a way to avoid the above steps? malloc+free seems like overkill to decide if the current user is SYSTEM! 2. Do I misunderstand the WIL code? Reading the Wine code for: GetTokenInformation() -> NtQueryInformationToken(): TOKEN_USER appears to be fixed size. Why does WIL think TOKEN_USER is not fixed size? I am confused! :-)
Kind regards, Kevin Connor ARPE Tokyo, Japan
On 16/03/2023 17:18, Kevin Connor Arpe wrote:
Hello,
This is my first time posting to this mailing list. (This email is a bit long... sorry!) I am a developer writing Win32 code using Wine on Debian Linux. I tried to use the Win32 API function GetTempPath2W(), but my Wine version does not support it. I checked out the Wine source code and found GetTempPathW() here: dlls/kernelbase/file.c ... but did not find GetTempPath2W().
First, if this function is already in the pipeline (another feature branch, etc.), please let me know... and ignore the rest of this email! :-)
From GetTempPathW() docs: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gette... "Note: Apps should call GetTempPath2 instead of GetTempPath."
From GetTempPath2W() docs: "When calling this function from a process running as SYSTEM it will return the path C:\Windows\SystemTemp"
The implementation looks rather straightforward except this part: "process running as SYSTEM". How to detect this? I found a good blog post from (the legend) Raymond Chen: https://devblogs.microsoft.com/oldnewthing/20210106-00/?p=104669
Sample code looks like this: << #include <wil/token_helpers.h>
bool DoesTokenRepresentSid(HANDLE token, WELL_KNOWN_SID_TYPE type) { // maps to GetTokenInformation(token, TokenUser, ...); auto user = wil::get_token_information<TOKEN_USER>(token); return !!IsWellKnownSid(user->User.Sid, type); }
bool IsCurrentProcessRunningAsSystem() { return DoesTokenRepresentSid(GetCurrentProcessToken(), WinLocalSystemSid); }
bool IsCurrentThreadRunningAsSystem() { return DoesTokenRepresentSid(GetCurrentThreadEffectiveToken(), WinLocalSystemSid); }
Reading the WIL source code on GitHub, I understand the required Win32 calls. In short, I plan to re-write the above same code using pure Win32 code (remove the WIL requirement).
My questions:
- Do you agree with Raymond Chen's technique for Wine source code? (Or: Is there a better way to do it for Wine source code?)
- Should my SYSTEM account test use IsCurrentProcessRunningAsSystem() or IsCurrentThreadRunningAsSystem()? If I read the official docs literally, I think "process" not "thread". Please advise.
- Reading the WIL code: TOKEN_INFORMATION_CLASS TokenUser appears to require this pattern: 1. Call GetTokenInformation() to get required buffer size 2. malloc buffer 3. Call GetTokenInformation() again with buffer 4. Check: WinLocalSystemSid == ((TOKEN_USER *) buffer)->User.Sid 5. free buffer
- Is there a way to avoid the above steps? malloc+free seems like overkill to decide if the current user is SYSTEM!
- Do I misunderstand the WIL code? Reading the Wine code for: GetTokenInformation() -> NtQueryInformationToken(): TOKEN_USER appears to be fixed size. Why does WIL think TOKEN_USER is not fixed size? I am confused! :-)
Kind regards, Kevin Connor ARPE Tokyo, Japan
Why not something like:
TOKEN_USER user_token; DWORD len;
if (!GetTokenInformation(GetCurrentProcessToken(), TokenUser, &user_token, sizeof(user_token), &len)) return FALSE;
return IsWellKnownSid(user_token.User.Sid, WinLocalSystemSid);
I'm not familiar with the APIs, nor do I know if Wine implements them properly, but there shouldn't be any need for malloc/free.
Am Donnerstag, 16. März 2023, 18:52:33 EAT schrieb Gabriel Ivăncescu:
From GetTempPath2W() docs: "When calling this function from a process
running as SYSTEM it will return the path C:\Windows\SystemTemp"
Do we even care for the purpose of GetTempPath2? Wine doesn't really do multiple users (it all lives in the context of your own Linux user), and it handles different privilege levels only as much as necessary. In that sense a real SYSTEM user doesn't exist, and depending on your point of view everything runs as SYSTEM or nothing runs as SYSTEM.
On 3/16/23 10:18, Kevin Connor Arpe wrote:
My questions:
1. Do you agree with Raymond Chen's technique for Wine source code? (Or: Is there a better way to do it for Wine source code?)
I'm not even sure I would bother with that quirk—simply forwarding to GetTempPath() would be simpler and probably good enough.
2. Should my SYSTEM account test use IsCurrentProcessRunningAsSystem() or IsCurrentThreadRunningAsSystem()? If I read the official docs literally, I think "process" not "thread". Please advise.
Generally speaking, that's the sort of thing you'd have to write tests for.
3. Reading the WIL code: TOKEN_INFORMATION_CLASS TokenUser appears to require this pattern: 1. Call GetTokenInformation() to get required buffer size 2. malloc buffer 3. Call GetTokenInformation() again with buffer 4. Check: WinLocalSystemSid == ((TOKEN_USER *) buffer)->User.Sid 5. free buffer 1. Is there a way to avoid the above steps? malloc+free seems like overkill to decide if the current user is SYSTEM! 2. Do I misunderstand the WIL code? Reading the Wine code for: GetTokenInformation() -> NtQueryInformationToken():
TOKEN_USER appears to be fixed size. Why does WIL think TOKEN_USER is not fixed size? I am confused! :-)
TOKEN_USER contains a pointer. I believe that GetTokenInformation() returns a pointer to data placed immediately after the TOKEN_USER structure. Since a SID is not a fixed-size structure, it's necessary to allocate dynamically.
Kind regards, Kevin Connor ARPE Tokyo, Japan