Author: hbelusca
Date: Thu Dec 15 18:44:47 2016
New Revision: 73458
URL:
http://svn.reactos.org/svn/reactos?rev=73458&view=rev
Log:
[APITESTS]: Add a test for userenv.dll API Load/UnloadUserProfile.
CORE-12541
Added:
trunk/rostests/apitests/userenv/
trunk/rostests/apitests/userenv/CMakeLists.txt (with props)
trunk/rostests/apitests/userenv/LoadUserProfile.c (with props)
trunk/rostests/apitests/userenv/testlist.c (with props)
Modified:
trunk/rostests/apitests/CMakeLists.txt
Modified: trunk/rostests/apitests/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/CMakeLists.txt?r…
==============================================================================
--- trunk/rostests/apitests/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/rostests/apitests/CMakeLists.txt [iso-8859-1] Thu Dec 15 18:44:47 2016
@@ -30,6 +30,7 @@
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)
Added: trunk/rostests/apitests/userenv/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/userenv/CMakeLis…
==============================================================================
--- trunk/rostests/apitests/userenv/CMakeLists.txt (added)
+++ trunk/rostests/apitests/userenv/CMakeLists.txt [iso-8859-1] Thu Dec 15 18:44:47 2016
@@ -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)
Propchange: trunk/rostests/apitests/userenv/CMakeLists.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/apitests/userenv/LoadUserProfile.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/userenv/LoadUser…
==============================================================================
--- trunk/rostests/apitests/userenv/LoadUserProfile.c (added)
+++ trunk/rostests/apitests/userenv/LoadUserProfile.c [iso-8859-1] Thu Dec 15 18:44:47
2016
@@ -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);
+}
Propchange: trunk/rostests/apitests/userenv/LoadUserProfile.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/apitests/userenv/testlist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/userenv/testlist…
==============================================================================
--- trunk/rostests/apitests/userenv/testlist.c (added)
+++ trunk/rostests/apitests/userenv/testlist.c [iso-8859-1] Thu Dec 15 18:44:47 2016
@@ -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 }
+};
Propchange: trunk/rostests/apitests/userenv/testlist.c
------------------------------------------------------------------------------
svn:eol-style = native