mirror of
https://github.com/reactos/reactos.git
synced 2025-06-01 07:28:19 +00:00
[APITESTS]: Add a test for userenv.dll API Load/UnloadUserProfile.
CORE-12541 svn path=/trunk/; revision=73458
This commit is contained in:
parent
17b4930a9d
commit
a54d1167e4
4 changed files with 240 additions and 0 deletions
|
@ -30,6 +30,7 @@ add_subdirectory(spoolss)
|
|||
add_subdirectory(psapi)
|
||||
add_subdirectory(user32)
|
||||
add_subdirectory(user32_dynamic)
|
||||
add_subdirectory(userenv)
|
||||
if(NOT ARCH STREQUAL "amd64" AND NOT CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
add_subdirectory(win32kdll)
|
||||
add_subdirectory(win32nt)
|
||||
|
|
10
rostests/apitests/userenv/CMakeLists.txt
Normal file
10
rostests/apitests/userenv/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
LoadUserProfile.c
|
||||
testlist.c)
|
||||
|
||||
add_executable(userenv_apitest ${SOURCE})
|
||||
target_link_libraries(userenv_apitest wine ${PSEH_LIB})
|
||||
set_module_type(userenv_apitest win32cui)
|
||||
add_importlibs(userenv_apitest userenv advapi32 msvcrt kernel32)
|
||||
add_cd_file(TARGET userenv_apitest DESTINATION reactos/bin FOR all)
|
217
rostests/apitests/userenv/LoadUserProfile.c
Normal file
217
rostests/apitests/userenv/LoadUserProfile.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
12
rostests/apitests/userenv/testlist.c
Normal file
12
rostests/apitests/userenv/testlist.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
#define __ROS_LONG64__
|
||||
|
||||
#define STANDALONE
|
||||
#include <apitest.h>
|
||||
|
||||
extern void func_LoadUserProfile(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "LoadUserProfile", func_LoadUserProfile },
|
||||
{ 0, 0 }
|
||||
};
|
Loading…
Reference in a new issue