1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Tests for Load/UnloadUserProfile 5 * PROGRAMMERS: Hermes Belusca-Maito 6 */ 7 8 #include <apitest.h> 9 // #include <windef.h> 10 // #include <winbase.h> 11 #include <sddl.h> 12 #include <userenv.h> 13 #include <strsafe.h> 14 15 #undef SE_RESTORE_NAME 16 #undef SE_BACKUP_NAME 17 #define SE_RESTORE_NAME L"SeRestorePrivilege" 18 #define SE_BACKUP_NAME L"SeBackupPrivilege" 19 20 /* 21 * Taken from dll/win32/shell32/dialogs/dialogs.cpp ; 22 * See also base/applications/shutdown/shutdown.c . 23 */ 24 static BOOL 25 EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege) 26 { 27 BOOL Success; 28 HANDLE hToken; 29 TOKEN_PRIVILEGES tp; 30 31 Success = OpenProcessToken(GetCurrentProcess(), 32 TOKEN_ADJUST_PRIVILEGES, 33 &hToken); 34 if (!Success) return Success; 35 36 Success = LookupPrivilegeValueW(NULL, 37 lpszPrivilegeName, 38 &tp.Privileges[0].Luid); 39 if (!Success) goto Quit; 40 41 tp.PrivilegeCount = 1; 42 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0); 43 44 Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL); 45 46 Quit: 47 CloseHandle(hToken); 48 return Success; 49 } 50 51 /* 52 * Taken from dll/win32/userenv/sid.c . 53 * We cannot directly use the USERENV.DLL export, because: 1) it is exported 54 * by ordinal (#142), and: 2) it is simply not exported at all in Vista+ 55 * (and ordinal #142 is assigned there to LoadUserProfileA). 56 */ 57 PSID 58 WINAPI 59 GetUserSid(IN HANDLE hToken) 60 { 61 BOOL Success; 62 PSID pSid; 63 ULONG Length; 64 PTOKEN_USER UserBuffer; 65 PTOKEN_USER TempBuffer; 66 67 Length = 256; 68 UserBuffer = LocalAlloc(LPTR, Length); 69 if (UserBuffer == NULL) 70 return NULL; 71 72 Success = GetTokenInformation(hToken, 73 TokenUser, 74 (PVOID)UserBuffer, 75 Length, 76 &Length); 77 if (!Success && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) 78 { 79 TempBuffer = LocalReAlloc(UserBuffer, Length, LMEM_MOVEABLE); 80 if (TempBuffer == NULL) 81 { 82 LocalFree(UserBuffer); 83 return NULL; 84 } 85 86 UserBuffer = TempBuffer; 87 Success = GetTokenInformation(hToken, 88 TokenUser, 89 (PVOID)UserBuffer, 90 Length, 91 &Length); 92 } 93 94 if (!Success) 95 { 96 LocalFree(UserBuffer); 97 return NULL; 98 } 99 100 Length = GetLengthSid(UserBuffer->User.Sid); 101 102 pSid = LocalAlloc(LPTR, Length); 103 if (pSid == NULL) 104 { 105 LocalFree(UserBuffer); 106 return NULL; 107 } 108 109 Success = CopySid(Length, pSid, UserBuffer->User.Sid); 110 111 LocalFree(UserBuffer); 112 113 if (!Success) 114 { 115 LocalFree(pSid); 116 return NULL; 117 } 118 119 return pSid; 120 } 121 122 START_TEST(LoadUserProfile) 123 { 124 BOOL Success; 125 HANDLE hToken = NULL; 126 PSID pUserSid = NULL; 127 USHORT i; 128 PROFILEINFOW ProfileInfo[2] = { {0}, {0} }; 129 130 Success = OpenThreadToken(GetCurrentThread(), 131 TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, 132 TRUE, 133 &hToken); 134 if (!Success && (GetLastError() == ERROR_NO_TOKEN)) 135 { 136 trace("OpenThreadToken failed with error %lu, falling back to OpenProcessToken\n", GetLastError()); 137 Success = OpenProcessToken(GetCurrentProcess(), 138 TOKEN_QUERY | TOKEN_IMPERSONATE | TOKEN_DUPLICATE, 139 &hToken); 140 } 141 if (!Success || (hToken == NULL)) 142 { 143 skip("Open[Thread|Process]Token failed with error %lu\n", GetLastError()); 144 return; 145 } 146 147 pUserSid = GetUserSid(hToken); 148 ok(pUserSid != NULL, "GetUserSid failed with error %lu\n", GetLastError()); 149 if (pUserSid) 150 { 151 LPWSTR pSidStr = NULL; 152 Success = ConvertSidToStringSidW(pUserSid, &pSidStr); 153 ok(Success, "ConvertSidToStringSidW failed with error %lu\n", GetLastError()); 154 if (Success) 155 { 156 trace("User SID is '%ls'\n", pSidStr); 157 LocalFree(pSidStr); 158 } 159 LocalFree(pUserSid); 160 pUserSid = NULL; 161 } 162 else 163 { 164 trace("No SID available!\n"); 165 } 166 167 /* Check whether ProfileInfo.lpUserName is really needed */ 168 ZeroMemory(&ProfileInfo[0], sizeof(ProfileInfo[0])); 169 ProfileInfo[0].dwSize = sizeof(ProfileInfo[0]); 170 ProfileInfo[0].dwFlags = PI_NOUI; 171 ProfileInfo[0].lpUserName = NULL; 172 Success = LoadUserProfileW(hToken, &ProfileInfo[0]); 173 ok(!Success, "LoadUserProfile succeeded with error %lu, expected failing\n", GetLastError()); 174 ok(ProfileInfo[0].hProfile == NULL, "ProfileInfo[0].hProfile != NULL, expected NULL\n"); 175 /* Unload the user profile if we erroneously succeeded, just in case... */ 176 if (Success) 177 { 178 trace("LoadUserProfileW(ProfileInfo[0]) unexpectedly succeeded, unload the user profile just in case...\n"); 179 UnloadUserProfile(hToken, ProfileInfo[0].hProfile); 180 } 181 182 /* TODO: Check which privileges we do need */ 183 184 /* Enable both the SE_RESTORE_NAME and SE_BACKUP_NAME privileges */ 185 Success = EnablePrivilege(SE_RESTORE_NAME, TRUE); 186 ok(Success, "EnablePrivilege(SE_RESTORE_NAME) failed with error %lu\n", GetLastError()); 187 Success = EnablePrivilege(SE_BACKUP_NAME, TRUE); 188 ok(Success, "EnablePrivilege(SE_BACKUP_NAME) failed with error %lu\n", GetLastError()); 189 190 /* Check whether we can load multiple times the same user profile */ 191 for (i = 0; i < ARRAYSIZE(ProfileInfo); ++i) 192 { 193 ZeroMemory(&ProfileInfo[i], sizeof(ProfileInfo[i])); 194 ProfileInfo[i].dwSize = sizeof(ProfileInfo[i]); 195 ProfileInfo[i].dwFlags = PI_NOUI; 196 ProfileInfo[i].lpUserName = L"toto"; // Dummy name; normally this should be the user name... 197 Success = LoadUserProfileW(hToken, &ProfileInfo[i]); 198 ok(Success, "LoadUserProfileW(ProfileInfo[%d]) failed with error %lu\n", i, GetLastError()); 199 ok(ProfileInfo[i].hProfile != NULL, "ProfileInfo[%d].hProfile == NULL\n", i); 200 trace("ProfileInfo[%d].hProfile = 0x%p\n", i, ProfileInfo[i].hProfile); 201 } 202 203 i = ARRAYSIZE(ProfileInfo); 204 while (i-- > 0) 205 { 206 trace("UnloadUserProfile(ProfileInfo[%d].hProfile)\n", i); 207 Success = UnloadUserProfile(hToken, ProfileInfo[i].hProfile); 208 ok(Success, "UnloadUserProfile(ProfileInfo[%d].hProfile) failed with error %lu\n", i, GetLastError()); 209 } 210 211 /* Disable the privileges */ 212 EnablePrivilege(SE_BACKUP_NAME, FALSE); 213 EnablePrivilege(SE_RESTORE_NAME, FALSE); 214 215 /* Final cleanup */ 216 CloseHandle(hToken); 217 } 218