reactos/modules/rostests/apitests/userenv/LoadUserProfile.c

218 lines
6.8 KiB
C

/*
* PROJECT: ReactOS api tests
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
* PURPOSE: Tests for Load/UnloadUserProfile
* PROGRAMMERS: Hermes Belusca-Maito
*/
#include <apitest.h>
// #include <windef.h>
// #include <winbase.h>
#include <sddl.h>
#include <userenv.h>
#include <strsafe.h>
#undef SE_RESTORE_NAME
#undef SE_BACKUP_NAME
#define SE_RESTORE_NAME L"SeRestorePrivilege"
#define SE_BACKUP_NAME L"SeBackupPrivilege"
/*
* Taken from dll/win32/shell32/dialogs/dialogs.cpp ;
* See also base/applications/shutdown/shutdown.c .
*/
static BOOL
EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
{
BOOL Success;
HANDLE hToken;
TOKEN_PRIVILEGES tp;
Success = OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&hToken);
if (!Success) return Success;
Success = LookupPrivilegeValueW(NULL,
lpszPrivilegeName,
&tp.Privileges[0].Luid);
if (!Success) goto Quit;
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
Quit:
CloseHandle(hToken);
return Success;
}
/*
* Taken from dll/win32/userenv/sid.c .
* We cannot directly use the USERENV.DLL export, because: 1) it is exported
* by ordinal (#142), and: 2) it is simply not exported at all in Vista+
* (and ordinal #142 is assigned there to LoadUserProfileA).
*/
PSID
WINAPI
GetUserSid(IN HANDLE hToken)
{
BOOL Success;
PSID pSid;
ULONG Length;
PTOKEN_USER UserBuffer;
PTOKEN_USER TempBuffer;
Length = 256;
UserBuffer = LocalAlloc(LPTR, Length);
if (UserBuffer == NULL)
return NULL;
Success = GetTokenInformation(hToken,
TokenUser,
(PVOID)UserBuffer,
Length,
&Length);
if (!Success && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
{
TempBuffer = LocalReAlloc(UserBuffer, Length, LMEM_MOVEABLE);
if (TempBuffer == NULL)
{
LocalFree(UserBuffer);
return NULL;
}
UserBuffer = TempBuffer;
Success = GetTokenInformation(hToken,
TokenUser,
(PVOID)UserBuffer,
Length,
&Length);
}
if (!Success)
{
LocalFree(UserBuffer);
return NULL;
}
Length = GetLengthSid(UserBuffer->User.Sid);
pSid = LocalAlloc(LPTR, Length);
if (pSid == NULL)
{
LocalFree(UserBuffer);
return NULL;
}
Success = CopySid(Length, pSid, UserBuffer->User.Sid);
LocalFree(UserBuffer);
if (!Success)
{
LocalFree(pSid);
return NULL;
}
return pSid;
}
START_TEST(LoadUserProfile)
{
BOOL Success;
HANDLE hToken = NULL;
PSID pUserSid = NULL;
USHORT i;
PROFILEINFOW ProfileInfo[2] = { {0}, {0} };
Success = OpenThreadToken(GetCurrentThread(),
TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
TRUE,
&hToken);
if (!Success && (GetLastError() == ERROR_NO_TOKEN))
{
trace("OpenThreadToken failed with error %lu, falling back to OpenProcessToken\n", GetLastError());
Success = OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
&hToken);
}
if (!Success || (hToken == NULL))
{
skip("Open[Thread|Process]Token failed with error %lu\n", GetLastError());
return;
}
pUserSid = GetUserSid(hToken);
ok(pUserSid != NULL, "GetUserSid failed with error %lu\n", GetLastError());
if (pUserSid)
{
LPWSTR pSidStr = NULL;
Success = ConvertSidToStringSidW(pUserSid, &pSidStr);
ok(Success, "ConvertSidToStringSidW failed with error %lu\n", GetLastError());
if (Success)
{
trace("User SID is '%ls'\n", pSidStr);
LocalFree(pSidStr);
}
LocalFree(pUserSid);
pUserSid = NULL;
}
else
{
trace("No SID available!\n");
}
/* Check whether ProfileInfo.lpUserName is really needed */
ZeroMemory(&ProfileInfo[0], sizeof(ProfileInfo[0]));
ProfileInfo[0].dwSize = sizeof(ProfileInfo[0]);
ProfileInfo[0].dwFlags = PI_NOUI;
ProfileInfo[0].lpUserName = NULL;
Success = LoadUserProfileW(hToken, &ProfileInfo[0]);
ok(!Success, "LoadUserProfile succeeded with error %lu, expected failing\n", GetLastError());
ok(ProfileInfo[0].hProfile == NULL, "ProfileInfo[0].hProfile != NULL, expected NULL\n");
/* Unload the user profile if we erroneously succeeded, just in case... */
if (Success)
{
trace("LoadUserProfileW(ProfileInfo[0]) unexpectedly succeeded, unload the user profile just in case...\n");
UnloadUserProfile(hToken, ProfileInfo[0].hProfile);
}
/* TODO: Check which privileges we do need */
/* Enable both the SE_RESTORE_NAME and SE_BACKUP_NAME privileges */
Success = EnablePrivilege(SE_RESTORE_NAME, TRUE);
ok(Success, "EnablePrivilege(SE_RESTORE_NAME) failed with error %lu\n", GetLastError());
Success = EnablePrivilege(SE_BACKUP_NAME, TRUE);
ok(Success, "EnablePrivilege(SE_BACKUP_NAME) failed with error %lu\n", GetLastError());
/* Check whether we can load multiple times the same user profile */
for (i = 0; i < ARRAYSIZE(ProfileInfo); ++i)
{
ZeroMemory(&ProfileInfo[i], sizeof(ProfileInfo[i]));
ProfileInfo[i].dwSize = sizeof(ProfileInfo[i]);
ProfileInfo[i].dwFlags = PI_NOUI;
ProfileInfo[i].lpUserName = L"toto"; // Dummy name; normally this should be the user name...
Success = LoadUserProfileW(hToken, &ProfileInfo[i]);
ok(Success, "LoadUserProfileW(ProfileInfo[%d]) failed with error %lu\n", i, GetLastError());
ok(ProfileInfo[i].hProfile != NULL, "ProfileInfo[%d].hProfile == NULL\n", i);
trace("ProfileInfo[%d].hProfile = 0x%p\n", i, ProfileInfo[i].hProfile);
}
i = ARRAYSIZE(ProfileInfo);
while (i-- > 0)
{
trace("UnloadUserProfile(ProfileInfo[%d].hProfile)\n", i);
Success = UnloadUserProfile(hToken, ProfileInfo[i].hProfile);
ok(Success, "UnloadUserProfile(ProfileInfo[%d].hProfile) failed with error %lu\n", i, GetLastError());
}
/* Disable the privileges */
EnablePrivilege(SE_BACKUP_NAME, FALSE);
EnablePrivilege(SE_RESTORE_NAME, FALSE);
/* Final cleanup */
CloseHandle(hToken);
}