diff options
Diffstat (limited to 'src/corelib/io/qfilesystemengine_win.cpp')
-rw-r--r-- | src/corelib/io/qfilesystemengine_win.cpp | 57 |
1 files changed, 46 insertions, 11 deletions
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 80f5448d40..d724429f6b 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -160,6 +160,31 @@ typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACC static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0; static TRUSTEE_W currentUserTrusteeW; static TRUSTEE_W worldTrusteeW; +static PSID currentUserSID = 0; +static PSID worldSID = 0; + +/* + Deletes the allocated SIDs during global static cleanup +*/ +class SidCleanup +{ +public: + ~SidCleanup(); +}; + +SidCleanup::~SidCleanup() +{ + qFree(currentUserSID); + currentUserSID = 0; + + // worldSID was allocated with AllocateAndInitializeSid so it needs to be freed with FreeSid + if (worldSID) { + ::FreeSid(worldSID); + worldSID = 0; + } +} + +Q_GLOBAL_STATIC(SidCleanup, initSidCleanup) typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD); static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0; @@ -199,25 +224,35 @@ static void resolveLibs() // Create TRUSTEE for current user HANDLE hnd = ::GetCurrentProcess(); HANDLE token = 0; + initSidCleanup(); if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) { - TOKEN_USER tu; - DWORD retsize; - if (::GetTokenInformation(token, TokenUser, &tu, sizeof(tu), &retsize)) - ptrBuildTrusteeWithSidW(¤tUserTrusteeW, tu.User.Sid); + DWORD retsize = 0; + // GetTokenInformation requires a buffer big enough for the TOKEN_USER struct and + // the SID struct. Since the SID struct can have variable number of subauthorities + // tacked at the end, its size is variable. Obtain the required size by first + // doing a dummy GetTokenInformation call. + ::GetTokenInformation(token, TokenUser, 0, 0, &retsize); + if (retsize) { + void *tokenBuffer = qMalloc(retsize); + if (::GetTokenInformation(token, TokenUser, tokenBuffer, retsize, &retsize)) { + PSID tokenSid = reinterpret_cast<PTOKEN_USER>(tokenBuffer)->User.Sid; + DWORD sidLen = ::GetLengthSid(tokenSid); + currentUserSID = reinterpret_cast<PSID>(qMalloc(sidLen)); + if (::CopySid(sidLen, currentUserSID, tokenSid)) + ptrBuildTrusteeWithSidW(¤tUserTrusteeW, currentUserSID); + } + qFree(tokenBuffer); + } ::CloseHandle(token); } typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*); PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid"); - typedef PVOID (WINAPI *PtrFreeSid)(PSID); - PtrFreeSid ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid"); - if (ptrAllocateAndInitializeSid && ptrFreeSid) { + if (ptrAllocateAndInitializeSid) { // Create TRUSTEE for Everyone (World) SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY }; - PSID pWorld = 0; - if (ptrAllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pWorld)) - ptrBuildTrusteeWithSidW(&worldTrusteeW, pWorld); - ptrFreeSid(pWorld); + if (ptrAllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &worldSID)) + ptrBuildTrusteeWithSidW(&worldTrusteeW, worldSID); } } HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv"); |