diff --git a/UnitTests/Win.cpp b/UnitTests/Win.cpp index 5cd90ff7..b470c316 100644 --- a/UnitTests/Win.cpp +++ b/UnitTests/Win.cpp @@ -31,6 +31,12 @@ namespace UnitTests } } + TEST_METHOD(CreateWellKnownSid) + { + std::unique_ptr sid; + Assert::IsTrue(::CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, sid)); + } + TEST_METHOD(library) { winstd::library lib_shell32(LoadLibraryEx(_T("shell32.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE)); diff --git a/include/WinStd/Win.h b/include/WinStd/Win.h index 86003238..543c96be 100644 --- a/include/WinStd/Win.h +++ b/include/WinStd/Win.h @@ -1240,6 +1240,33 @@ static _Success_(return != 0) BOOL LookupAccountSidW(_In_opt_z_ LPCWSTR lpSystem return FALSE; } +/// +/// Creates a SID for predefined aliases. +/// +/// \sa [CreateWellKnownSid function](https://learn.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-createwellknownsid) +/// +static _Success_(return != FALSE) BOOL CreateWellKnownSid(_In_ WELL_KNOWN_SID_TYPE WellKnownSidType, _In_opt_ PSID DomainSid, _Inout_ std::unique_ptr &Sid) +{ + BYTE szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(BYTE)]; + DWORD dwSize = sizeof(szStackBuffer); + + // Try with stack buffer first. + if (CreateWellKnownSid(WellKnownSidType, DomainSid, szStackBuffer, &dwSize)) { + // Copy from stack. + Sid.reset((SID*)new BYTE[dwSize]); + memcpy(Sid.get(), szStackBuffer, dwSize); + return TRUE; + } + for (;;) { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return FALSE; + // Allocate on heap and retry. + Sid.reset((SID*)new BYTE[dwSize]); + if (CreateWellKnownSid(WellKnownSidType, DomainSid, Sid.get(), &dwSize)) + return TRUE; + } +} + /// /// Retrieves a specified type of information about an access token. The calling process must have appropriate access rights to obtain the information. ///