[USERENV]
[reactos.git] / reactos / dll / win32 / userenv / profile.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/userenv/profile.c
5 * PURPOSE: User profile code
6 * PROGRAMMERS: Eric Kohl
7 * Hervé Poussineau
8 */
9
10 #include "precomp.h"
11
12 #include <sddl.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* FUNCTIONS ***************************************************************/
18
19 BOOL
20 AppendSystemPostfix(LPWSTR lpName,
21 DWORD dwMaxLength)
22 {
23 WCHAR szSystemRoot[MAX_PATH];
24 LPWSTR lpszPostfix;
25 LPWSTR lpszPtr;
26
27 /* Build profile name postfix */
28 if (!ExpandEnvironmentStringsW(L"%SystemRoot%",
29 szSystemRoot,
30 ARRAYSIZE(szSystemRoot)))
31 {
32 DPRINT1("Error: %lu\n", GetLastError());
33 return FALSE;
34 }
35
36 _wcsupr(szSystemRoot);
37
38 /* Get name postfix */
39 szSystemRoot[2] = L'.';
40 lpszPostfix = &szSystemRoot[2];
41 lpszPtr = lpszPostfix;
42 while (*lpszPtr != (WCHAR)0)
43 {
44 if (*lpszPtr == L'\\')
45 *lpszPtr = L'_';
46 lpszPtr++;
47 }
48
49 if (wcslen(lpName) + wcslen(lpszPostfix) + 1 >= dwMaxLength)
50 {
51 DPRINT1("Error: buffer overflow\n");
52 SetLastError(ERROR_BUFFER_OVERFLOW);
53 return FALSE;
54 }
55
56 wcscat(lpName, lpszPostfix);
57
58 return TRUE;
59 }
60
61
62 static
63 BOOL
64 AcquireRemoveRestorePrivilege(IN BOOL bAcquire)
65 {
66 BOOL bRet = FALSE;
67 HANDLE Token;
68 TOKEN_PRIVILEGES TokenPriv;
69
70 DPRINT("AcquireRemoveRestorePrivilege(%d)\n", bAcquire);
71
72 if (OpenProcessToken(GetCurrentProcess(),
73 TOKEN_ADJUST_PRIVILEGES,
74 &Token))
75 {
76 TokenPriv.PrivilegeCount = 1;
77 TokenPriv.Privileges[0].Attributes = (bAcquire ? SE_PRIVILEGE_ENABLED : 0);
78
79 if (LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &TokenPriv.Privileges[0].Luid))
80 {
81 bRet = AdjustTokenPrivileges(Token, FALSE, &TokenPriv, 0, NULL, NULL);
82
83 if (!bRet)
84 {
85 DPRINT1("AdjustTokenPrivileges() failed with error %lu\n", GetLastError());
86 }
87 else if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
88 {
89 DPRINT1("AdjustTokenPrivileges() succeeded, but with not all privileges assigned\n");
90 bRet = FALSE;
91 }
92 }
93 else
94 {
95 DPRINT1("LookupPrivilegeValue() failed with error %lu\n", GetLastError());
96 }
97
98 CloseHandle(Token);
99 }
100 else
101 {
102 DPRINT1("OpenProcessToken() failed with error %lu\n", GetLastError());
103 }
104
105 return bRet;
106 }
107
108
109 BOOL
110 WINAPI
111 CreateUserProfileA(
112 _In_ PSID pSid,
113 _In_ LPCSTR lpUserName)
114 {
115 LPWSTR pUserNameW = NULL;
116 INT nLength;
117 BOOL bResult;
118
119 DPRINT("CreateUserProfileA(%p %s)\n", pSid, lpUserName);
120
121 /* Convert lpUserName to Unicode */
122 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, NULL, 0);
123 pUserNameW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
124 if (pUserNameW == NULL)
125 {
126 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
127 return FALSE;
128 }
129 MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, pUserNameW, nLength);
130
131 /* Call the Ex function */
132 bResult = CreateUserProfileExW(pSid,
133 pUserNameW,
134 NULL,
135 NULL,
136 0,
137 FALSE);
138
139 HeapFree(GetProcessHeap(), 0, pUserNameW);
140
141 return bResult;
142 }
143
144
145 BOOL
146 WINAPI
147 CreateUserProfileW(
148 _In_ PSID pSid,
149 _In_ LPCWSTR lpUserName)
150 {
151 DPRINT("CreateUserProfileW(%p %S)\n", pSid, lpUserName);
152
153 /* Call the Ex function */
154 return CreateUserProfileExW(pSid,
155 lpUserName,
156 NULL,
157 NULL,
158 0,
159 FALSE);
160 }
161
162
163 BOOL
164 WINAPI
165 CreateUserProfileExA(
166 _In_ PSID pSid,
167 _In_ LPCSTR lpUserName,
168 _In_opt_ LPCSTR lpUserHive,
169 _Out_opt_ LPSTR lpProfileDir,
170 _In_ DWORD dwDirSize,
171 _In_ BOOL bWin9xUpg)
172 {
173 LPWSTR pUserNameW = NULL;
174 LPWSTR pUserHiveW = NULL;
175 LPWSTR pProfileDirW = NULL;
176 INT nLength;
177 BOOL bResult = FALSE;
178
179 DPRINT("CreateUserProfileExA(%p %s %s %p %lu %d)\n",
180 pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, bWin9xUpg);
181
182 /* Check the parameters */
183 if (lpProfileDir != NULL && dwDirSize == 0)
184 {
185 SetLastError(ERROR_INVALID_PARAMETER);
186 return FALSE;
187 }
188
189 /* Convert lpUserName to Unicode */
190 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, NULL, 0);
191 pUserNameW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
192 if (pUserNameW == NULL)
193 {
194 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
195 goto done;
196 }
197 MultiByteToWideChar(CP_ACP, 0, lpUserName, -1, pUserNameW, nLength);
198
199 /* Convert lpUserHive to Unicode */
200 if (lpUserHive != NULL)
201 {
202 nLength = MultiByteToWideChar(CP_ACP, 0, lpUserHive, -1, NULL, 0);
203 pUserHiveW = HeapAlloc(GetProcessHeap(), 0, nLength * sizeof(WCHAR));
204 if (pUserHiveW == NULL)
205 {
206 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
207 goto done;
208 }
209 MultiByteToWideChar(CP_ACP, 0, lpUserHive, -1, pUserHiveW, nLength);
210 }
211
212 /* Allocate a Unicode buffer for lpProfileDir */
213 if (lpProfileDir != NULL)
214 {
215 pProfileDirW = HeapAlloc(GetProcessHeap(), 0, dwDirSize * sizeof(WCHAR));
216 if (pProfileDirW == NULL)
217 {
218 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
219 goto done;
220 }
221 }
222
223 /* Call the Unicode function */
224 bResult = CreateUserProfileExW(pSid,
225 (LPCWSTR)pUserNameW,
226 (LPCWSTR)pUserHiveW,
227 pProfileDirW,
228 dwDirSize,
229 bWin9xUpg);
230
231 /* Convert the profile path to ANSI */
232 if (bResult && lpProfileDir != NULL)
233 {
234 WideCharToMultiByte(CP_ACP, 0, pProfileDirW, -1, lpProfileDir, dwDirSize, NULL, NULL);
235 }
236
237 done:
238 /* Free the buffers */
239 if (pProfileDirW != NULL)
240 HeapFree(GetProcessHeap(), 0, pProfileDirW);
241
242 if (pUserHiveW != NULL)
243 HeapFree(GetProcessHeap(), 0, pUserHiveW);
244
245 if (pUserNameW != NULL)
246 HeapFree(GetProcessHeap(), 0, pUserNameW);
247
248 return bResult;
249 }
250
251
252 BOOL
253 WINAPI
254 CreateUserProfileExW(
255 _In_ PSID pSid,
256 _In_ LPCWSTR lpUserName,
257 _In_opt_ LPCWSTR lpUserHive,
258 _Out_opt_ LPWSTR lpProfileDir,
259 _In_ DWORD dwDirSize,
260 _In_ BOOL bWin9xUpg)
261 {
262 WCHAR szRawProfilesPath[MAX_PATH];
263 WCHAR szProfilesPath[MAX_PATH];
264 WCHAR szUserProfilePath[MAX_PATH];
265 WCHAR szDefaultUserPath[MAX_PATH];
266 WCHAR szUserProfileName[MAX_PATH];
267 WCHAR szBuffer[MAX_PATH];
268 LPWSTR SidString;
269 DWORD dwLength;
270 DWORD dwDisposition;
271 UINT i;
272 HKEY hKey;
273 BOOL bRet = TRUE;
274 LONG Error;
275
276 DPRINT("CreateUserProfileExW(%p %S %S %p %lu %d)\n",
277 pSid, lpUserName, lpUserHive, lpProfileDir, dwDirSize, bWin9xUpg);
278
279 /*
280 * TODO:
281 * - Add support for lpUserHive, lpProfileDir.
282 * - bWin9xUpg is obsolete. Don't waste your time implementing this.
283 */
284
285 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
286 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
287 0,
288 KEY_QUERY_VALUE,
289 &hKey);
290 if (Error != ERROR_SUCCESS)
291 {
292 DPRINT1("Error: %lu\n", Error);
293 SetLastError((DWORD)Error);
294 return FALSE;
295 }
296
297 /* Get profiles path */
298 dwLength = sizeof(szRawProfilesPath);
299 Error = RegQueryValueExW(hKey,
300 L"ProfilesDirectory",
301 NULL,
302 NULL,
303 (LPBYTE)szRawProfilesPath,
304 &dwLength);
305 if (Error != ERROR_SUCCESS)
306 {
307 DPRINT1("Error: %lu\n", Error);
308 RegCloseKey(hKey);
309 SetLastError((DWORD)Error);
310 return FALSE;
311 }
312
313 /* Expand it */
314 if (!ExpandEnvironmentStringsW(szRawProfilesPath,
315 szProfilesPath,
316 ARRAYSIZE(szProfilesPath)))
317 {
318 DPRINT1("Error: %lu\n", GetLastError());
319 RegCloseKey(hKey);
320 return FALSE;
321 }
322
323 /* create the profiles directory if it does not yet exist */
324 if (!CreateDirectoryW(szProfilesPath, NULL))
325 {
326 if (GetLastError() != ERROR_ALREADY_EXISTS)
327 {
328 DPRINT1("Error: %lu\n", GetLastError());
329 return FALSE;
330 }
331 }
332
333 /* Get default user path */
334 dwLength = sizeof(szBuffer);
335 Error = RegQueryValueExW(hKey,
336 L"DefaultUserProfile",
337 NULL,
338 NULL,
339 (LPBYTE)szBuffer,
340 &dwLength);
341 if (Error != ERROR_SUCCESS)
342 {
343 DPRINT1("Error: %lu\n", Error);
344 RegCloseKey(hKey);
345 SetLastError((DWORD)Error);
346 return FALSE;
347 }
348
349 RegCloseKey (hKey);
350
351 wcscpy(szUserProfileName, lpUserName);
352
353 wcscpy(szUserProfilePath, szProfilesPath);
354 wcscat(szUserProfilePath, L"\\");
355 wcscat(szUserProfilePath, szUserProfileName);
356
357 wcscpy(szDefaultUserPath, szProfilesPath);
358 wcscat(szDefaultUserPath, L"\\");
359 wcscat(szDefaultUserPath, szBuffer);
360
361 /* Create user profile directory */
362 if (!CreateDirectoryW(szUserProfilePath, NULL))
363 {
364 if (GetLastError() != ERROR_ALREADY_EXISTS)
365 {
366 DPRINT1("Error: %lu\n", GetLastError());
367 return FALSE;
368 }
369
370 for (i = 0; i < 1000; i++)
371 {
372 swprintf(szUserProfileName, L"%s.%03u", lpUserName, i);
373
374 wcscpy(szUserProfilePath, szProfilesPath);
375 wcscat(szUserProfilePath, L"\\");
376 wcscat(szUserProfilePath, szUserProfileName);
377
378 if (CreateDirectoryW(szUserProfilePath, NULL))
379 break;
380
381 if (GetLastError() != ERROR_ALREADY_EXISTS)
382 {
383 DPRINT1("Error: %lu\n", GetLastError());
384 return FALSE;
385 }
386 }
387 }
388
389 /* Copy default user directory */
390 if (!CopyDirectory(szUserProfilePath, szDefaultUserPath))
391 {
392 DPRINT1("Error: %lu\n", GetLastError());
393 return FALSE;
394 }
395
396 /* Add profile to profile list */
397 if (!ConvertSidToStringSidW(pSid,
398 &SidString))
399 {
400 DPRINT1("Error: %lu\n", GetLastError());
401 return FALSE;
402 }
403
404 wcscpy(szBuffer,
405 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
406 wcscat(szBuffer, SidString);
407
408 /* Create user profile key */
409 Error = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
410 szBuffer,
411 0,
412 NULL,
413 REG_OPTION_NON_VOLATILE,
414 KEY_ALL_ACCESS,
415 NULL,
416 &hKey,
417 &dwDisposition);
418 if (Error != ERROR_SUCCESS)
419 {
420 DPRINT1("Error: %lu\n", Error);
421 bRet = FALSE;
422 goto done;
423 }
424
425 /* Create non-expanded user profile path */
426 wcscpy(szBuffer, szRawProfilesPath);
427 wcscat(szBuffer, L"\\");
428 wcscat(szBuffer, szUserProfileName);
429
430 /* Set 'ProfileImagePath' value (non-expanded) */
431 Error = RegSetValueExW(hKey,
432 L"ProfileImagePath",
433 0,
434 REG_EXPAND_SZ,
435 (LPBYTE)szBuffer,
436 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
437 if (Error != ERROR_SUCCESS)
438 {
439 DPRINT1("Error: %lu\n", Error);
440 RegCloseKey(hKey);
441 bRet = FALSE;
442 goto done;
443 }
444
445 /* Set 'Sid' value */
446 Error = RegSetValueExW(hKey,
447 L"Sid",
448 0,
449 REG_BINARY,
450 pSid,
451 GetLengthSid(pSid));
452 if (Error != ERROR_SUCCESS)
453 {
454 DPRINT1("Error: %lu\n", Error);
455 RegCloseKey(hKey);
456 bRet = FALSE;
457 goto done;
458 }
459
460 RegCloseKey(hKey);
461
462 /* Create user hive name */
463 wcscpy(szBuffer, szUserProfilePath);
464 wcscat(szBuffer, L"\\ntuser.dat");
465
466 /* Acquire restore privilege */
467 if (!AcquireRemoveRestorePrivilege(TRUE))
468 {
469 Error = GetLastError();
470 DPRINT1("Error: %lu\n", Error);
471 bRet = FALSE;
472 goto done;
473 }
474
475 /* Create new user hive */
476 Error = RegLoadKeyW(HKEY_USERS,
477 SidString,
478 szBuffer);
479 AcquireRemoveRestorePrivilege(FALSE);
480 if (Error != ERROR_SUCCESS)
481 {
482 DPRINT1("Error: %lu\n", Error);
483 bRet = FALSE;
484 goto done;
485 }
486
487 /* Initialize user hive */
488 if (!CreateUserHive(SidString, szUserProfilePath))
489 {
490 Error = GetLastError();
491 DPRINT1("Error: %lu\n", Error);
492 bRet = FALSE;
493 }
494
495 /* Unload the hive */
496 AcquireRemoveRestorePrivilege(TRUE);
497 RegUnLoadKeyW(HKEY_USERS, SidString);
498 AcquireRemoveRestorePrivilege(FALSE);
499
500 done:
501 LocalFree((HLOCAL)SidString);
502 SetLastError((DWORD)Error);
503
504 DPRINT("CreateUserProfileExW() done\n");
505
506 return bRet;
507 }
508
509
510 BOOL
511 WINAPI
512 GetAllUsersProfileDirectoryA(
513 _Out_opt_ LPSTR lpProfileDir,
514 _Inout_ LPDWORD lpcchSize)
515 {
516 LPWSTR lpBuffer;
517 BOOL bResult;
518
519 lpBuffer = GlobalAlloc(GMEM_FIXED,
520 *lpcchSize * sizeof(WCHAR));
521 if (lpBuffer == NULL)
522 return FALSE;
523
524 bResult = GetAllUsersProfileDirectoryW(lpBuffer,
525 lpcchSize);
526 if (bResult)
527 {
528 WideCharToMultiByte(CP_ACP,
529 0,
530 lpBuffer,
531 -1,
532 lpProfileDir,
533 *lpcchSize,
534 NULL,
535 NULL);
536 }
537
538 GlobalFree(lpBuffer);
539
540 return bResult;
541 }
542
543
544 BOOL
545 WINAPI
546 GetAllUsersProfileDirectoryW(
547 _Out_opt_ LPWSTR lpProfileDir,
548 _Inout_ LPDWORD lpcchSize)
549 {
550 WCHAR szProfilePath[MAX_PATH];
551 WCHAR szBuffer[MAX_PATH];
552 DWORD dwLength;
553 HKEY hKey;
554 LONG Error;
555
556 if (!lpcchSize)
557 {
558 SetLastError(ERROR_INVALID_PARAMETER);
559 return FALSE;
560 }
561
562 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
563 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
564 0,
565 KEY_QUERY_VALUE,
566 &hKey);
567 if (Error != ERROR_SUCCESS)
568 {
569 DPRINT1("Error: %lu\n", Error);
570 SetLastError((DWORD)Error);
571 return FALSE;
572 }
573
574 /* Get profiles path */
575 dwLength = sizeof(szBuffer);
576 Error = RegQueryValueExW(hKey,
577 L"ProfilesDirectory",
578 NULL,
579 NULL,
580 (LPBYTE)szBuffer,
581 &dwLength);
582 if (Error != ERROR_SUCCESS)
583 {
584 DPRINT1("Error: %lu\n", Error);
585 RegCloseKey(hKey);
586 SetLastError((DWORD)Error);
587 return FALSE;
588 }
589
590 /* Expand it */
591 if (!ExpandEnvironmentStringsW(szBuffer,
592 szProfilePath,
593 MAX_PATH))
594 {
595 DPRINT1("Error: %lu\n", GetLastError());
596 RegCloseKey (hKey);
597 return FALSE;
598 }
599
600 /* Get 'AllUsersProfile' name */
601 dwLength = sizeof(szBuffer);
602 Error = RegQueryValueExW(hKey,
603 L"AllUsersProfile",
604 NULL,
605 NULL,
606 (LPBYTE)szBuffer,
607 &dwLength);
608 if (Error != ERROR_SUCCESS)
609 {
610 DPRINT1("Error: %lu\n", Error);
611 RegCloseKey(hKey);
612 SetLastError((DWORD)Error);
613 return FALSE;
614 }
615
616 RegCloseKey (hKey);
617
618 wcscat(szProfilePath, L"\\");
619 wcscat(szProfilePath, szBuffer);
620
621 dwLength = wcslen(szProfilePath) + 1;
622 if (lpProfileDir != NULL)
623 {
624 if (*lpcchSize < dwLength)
625 {
626 *lpcchSize = dwLength;
627 SetLastError(ERROR_INSUFFICIENT_BUFFER);
628 return FALSE;
629 }
630
631 wcscpy(lpProfileDir, szProfilePath);
632 }
633
634 *lpcchSize = dwLength;
635
636 return TRUE;
637 }
638
639
640 BOOL
641 WINAPI
642 GetDefaultUserProfileDirectoryA(
643 _Out_opt_ LPSTR lpProfileDir,
644 _Inout_ LPDWORD lpcchSize)
645 {
646 LPWSTR lpBuffer;
647 BOOL bResult;
648
649 lpBuffer = GlobalAlloc(GMEM_FIXED,
650 *lpcchSize * sizeof(WCHAR));
651 if (lpBuffer == NULL)
652 return FALSE;
653
654 bResult = GetDefaultUserProfileDirectoryW(lpBuffer,
655 lpcchSize);
656 if (bResult)
657 {
658 WideCharToMultiByte(CP_ACP,
659 0,
660 lpBuffer,
661 -1,
662 lpProfileDir,
663 *lpcchSize,
664 NULL,
665 NULL);
666 }
667
668 GlobalFree(lpBuffer);
669
670 return bResult;
671 }
672
673
674 BOOL
675 WINAPI
676 GetDefaultUserProfileDirectoryW(
677 _Out_opt_ LPWSTR lpProfileDir,
678 _Inout_ LPDWORD lpcchSize)
679 {
680 WCHAR szProfilePath[MAX_PATH];
681 WCHAR szBuffer[MAX_PATH];
682 DWORD dwLength;
683 HKEY hKey;
684 LONG Error;
685
686 if (!lpcchSize)
687 {
688 SetLastError(ERROR_INVALID_PARAMETER);
689 return FALSE;
690 }
691
692 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
693 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
694 0,
695 KEY_QUERY_VALUE,
696 &hKey);
697 if (Error != ERROR_SUCCESS)
698 {
699 DPRINT1("Error: %lu\n", Error);
700 SetLastError((DWORD)Error);
701 return FALSE;
702 }
703
704 /* Get profiles path */
705 dwLength = sizeof(szBuffer);
706 Error = RegQueryValueExW(hKey,
707 L"ProfilesDirectory",
708 NULL,
709 NULL,
710 (LPBYTE)szBuffer,
711 &dwLength);
712 if (Error != ERROR_SUCCESS)
713 {
714 DPRINT1("Error: %lu\n", Error);
715 RegCloseKey(hKey);
716 SetLastError((DWORD)Error);
717 return FALSE;
718 }
719
720 /* Expand it */
721 if (!ExpandEnvironmentStringsW(szBuffer,
722 szProfilePath,
723 MAX_PATH))
724 {
725 DPRINT1("Error: %lu\n", GetLastError());
726 RegCloseKey(hKey);
727 return FALSE;
728 }
729
730 /* Get 'DefaultUserProfile' name */
731 dwLength = sizeof(szBuffer);
732 Error = RegQueryValueExW(hKey,
733 L"DefaultUserProfile",
734 NULL,
735 NULL,
736 (LPBYTE)szBuffer,
737 &dwLength);
738 if (Error != ERROR_SUCCESS)
739 {
740 DPRINT1("Error: %lu\n", Error);
741 RegCloseKey(hKey);
742 SetLastError((DWORD)Error);
743 return FALSE;
744 }
745
746 RegCloseKey(hKey);
747
748 wcscat(szProfilePath, L"\\");
749 wcscat(szProfilePath, szBuffer);
750
751 dwLength = wcslen(szProfilePath) + 1;
752 if (lpProfileDir != NULL)
753 {
754 if (*lpcchSize < dwLength)
755 {
756 *lpcchSize = dwLength;
757 SetLastError(ERROR_INSUFFICIENT_BUFFER);
758 return FALSE;
759 }
760
761 wcscpy(lpProfileDir, szProfilePath);
762 }
763
764 *lpcchSize = dwLength;
765
766 return TRUE;
767 }
768
769
770 BOOL
771 WINAPI
772 GetProfilesDirectoryA(
773 _Out_ LPSTR lpProfileDir, // _Out_opt_
774 _Inout_ LPDWORD lpcchSize)
775 {
776 LPWSTR lpBuffer;
777 BOOL bResult;
778
779 if (!lpProfileDir || !lpcchSize)
780 {
781 SetLastError(ERROR_INVALID_PARAMETER);
782 return FALSE;
783 }
784
785 lpBuffer = GlobalAlloc(GMEM_FIXED,
786 *lpcchSize * sizeof(WCHAR));
787 if (lpBuffer == NULL)
788 return FALSE;
789
790 bResult = GetProfilesDirectoryW(lpBuffer,
791 lpcchSize);
792 if (bResult)
793 {
794 bResult = WideCharToMultiByte(CP_ACP,
795 0,
796 lpBuffer,
797 -1,
798 lpProfileDir,
799 *lpcchSize,
800 NULL,
801 NULL);
802 }
803
804 GlobalFree(lpBuffer);
805
806 return bResult;
807 }
808
809
810 BOOL
811 WINAPI
812 GetProfilesDirectoryW(
813 _Out_ LPWSTR lpProfilesDir, // _Out_opt_
814 _Inout_ LPDWORD lpcchSize)
815 {
816 WCHAR szProfilesPath[MAX_PATH];
817 WCHAR szBuffer[MAX_PATH];
818 DWORD dwLength;
819 HKEY hKey;
820 LONG Error;
821 BOOL bRet = FALSE;
822
823 if (!lpcchSize)
824 {
825 SetLastError(ERROR_INVALID_PARAMETER);
826 return FALSE;
827 }
828
829 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
830 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
831 0,
832 KEY_QUERY_VALUE,
833 &hKey);
834 if (Error != ERROR_SUCCESS)
835 {
836 DPRINT1("Error: %lu\n", Error);
837 SetLastError((DWORD)Error);
838 return FALSE;
839 }
840
841 /* Get profiles path */
842 dwLength = sizeof(szBuffer);
843 Error = RegQueryValueExW(hKey,
844 L"ProfilesDirectory",
845 NULL,
846 NULL,
847 (LPBYTE)szBuffer,
848 &dwLength);
849 if (Error != ERROR_SUCCESS)
850 {
851 DPRINT1("Error: %lu\n", Error);
852 RegCloseKey(hKey);
853 SetLastError((DWORD)Error);
854 return FALSE;
855 }
856
857 RegCloseKey(hKey);
858
859 /* Expand it */
860 if (!ExpandEnvironmentStringsW(szBuffer,
861 szProfilesPath,
862 ARRAYSIZE(szProfilesPath)))
863 {
864 DPRINT1("Error: %lu\n", GetLastError());
865 return FALSE;
866 }
867
868 dwLength = wcslen(szProfilesPath) + 1;
869 if (lpProfilesDir != NULL)
870 {
871 if (*lpcchSize < dwLength)
872 {
873 SetLastError(ERROR_INSUFFICIENT_BUFFER);
874 }
875 else
876 {
877 wcscpy(lpProfilesDir, szProfilesPath);
878 bRet = TRUE;
879 }
880 }
881 else
882 {
883 SetLastError(ERROR_INSUFFICIENT_BUFFER);
884 }
885
886 *lpcchSize = dwLength;
887
888 return bRet;
889 }
890
891
892 BOOL
893 WINAPI
894 GetUserProfileDirectoryA(
895 _In_ HANDLE hToken,
896 _Out_opt_ LPSTR lpProfileDir,
897 _Inout_ LPDWORD lpcchSize)
898 {
899 LPWSTR lpBuffer;
900 BOOL bResult;
901
902 if (!lpProfileDir || !lpcchSize)
903 {
904 SetLastError( ERROR_INVALID_PARAMETER );
905 return FALSE;
906 }
907
908 lpBuffer = GlobalAlloc(GMEM_FIXED,
909 *lpcchSize * sizeof(WCHAR));
910 if (lpBuffer == NULL)
911 return FALSE;
912
913 bResult = GetUserProfileDirectoryW(hToken,
914 lpBuffer,
915 lpcchSize);
916 if (bResult)
917 {
918 WideCharToMultiByte(CP_ACP,
919 0,
920 lpBuffer,
921 -1,
922 lpProfileDir,
923 *lpcchSize,
924 NULL,
925 NULL);
926 }
927
928 GlobalFree(lpBuffer);
929
930 return bResult;
931 }
932
933
934 BOOL
935 WINAPI
936 GetUserProfileDirectoryW(
937 _In_ HANDLE hToken,
938 _Out_opt_ LPWSTR lpProfileDir,
939 _Inout_ LPDWORD lpcchSize)
940 {
941 UNICODE_STRING SidString;
942 WCHAR szKeyName[MAX_PATH];
943 WCHAR szRawImagePath[MAX_PATH];
944 WCHAR szImagePath[MAX_PATH];
945 DWORD dwLength;
946 HKEY hKey;
947 LONG Error;
948
949 if (!hToken)
950 {
951 SetLastError(ERROR_INVALID_HANDLE);
952 return FALSE;
953 }
954
955 if (!lpcchSize)
956 {
957 SetLastError(ERROR_INVALID_PARAMETER);
958 return FALSE;
959 }
960
961 if (!GetUserSidStringFromToken(hToken,
962 &SidString))
963 {
964 DPRINT1("GetUserSidFromToken() failed\n");
965 return FALSE;
966 }
967
968 DPRINT("SidString: '%wZ'\n", &SidString);
969
970 wcscpy(szKeyName,
971 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\");
972 wcscat(szKeyName,
973 SidString.Buffer);
974
975 RtlFreeUnicodeString(&SidString);
976
977 DPRINT("KeyName: '%S'\n", szKeyName);
978
979 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
980 szKeyName,
981 0,
982 KEY_QUERY_VALUE,
983 &hKey);
984 if (Error != ERROR_SUCCESS)
985 {
986 DPRINT1("Error: %lu\n", Error);
987 SetLastError((DWORD)Error);
988 return FALSE;
989 }
990
991 dwLength = sizeof(szRawImagePath);
992 Error = RegQueryValueExW(hKey,
993 L"ProfileImagePath",
994 NULL,
995 NULL,
996 (LPBYTE)szRawImagePath,
997 &dwLength);
998 if (Error != ERROR_SUCCESS)
999 {
1000 DPRINT1("Error: %lu\n", Error);
1001 RegCloseKey(hKey);
1002 SetLastError((DWORD)Error);
1003 return FALSE;
1004 }
1005
1006 RegCloseKey(hKey);
1007
1008 DPRINT("RawImagePath: '%S'\n", szRawImagePath);
1009
1010 /* Expand it */
1011 if (!ExpandEnvironmentStringsW(szRawImagePath,
1012 szImagePath,
1013 ARRAYSIZE(szImagePath)))
1014 {
1015 DPRINT1 ("Error: %lu\n", GetLastError());
1016 return FALSE;
1017 }
1018
1019 DPRINT("ImagePath: '%S'\n", szImagePath);
1020
1021 dwLength = wcslen (szImagePath) + 1;
1022 if (*lpcchSize < dwLength)
1023 {
1024 *lpcchSize = dwLength;
1025 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1026 return FALSE;
1027 }
1028
1029 *lpcchSize = dwLength;
1030 wcscpy(lpProfileDir, szImagePath);
1031
1032 return TRUE;
1033 }
1034
1035
1036 static
1037 BOOL
1038 CheckForLoadedProfile(HANDLE hToken)
1039 {
1040 UNICODE_STRING SidString;
1041 HKEY hKey;
1042
1043 DPRINT("CheckForLoadedProfile() called\n");
1044
1045 if (!GetUserSidStringFromToken(hToken,
1046 &SidString))
1047 {
1048 DPRINT1("GetUserSidFromToken() failed\n");
1049 return FALSE;
1050 }
1051
1052 if (RegOpenKeyExW(HKEY_USERS,
1053 SidString.Buffer,
1054 0,
1055 MAXIMUM_ALLOWED,
1056 &hKey))
1057 {
1058 DPRINT("Profile not loaded\n");
1059 RtlFreeUnicodeString(&SidString);
1060 return FALSE;
1061 }
1062
1063 RegCloseKey(hKey);
1064
1065 RtlFreeUnicodeString(&SidString);
1066
1067 DPRINT("Profile already loaded\n");
1068
1069 return TRUE;
1070 }
1071
1072
1073 BOOL
1074 WINAPI
1075 LoadUserProfileA(
1076 _In_ HANDLE hToken,
1077 _Inout_ LPPROFILEINFOA lpProfileInfo)
1078 {
1079 BOOL bResult = FALSE;
1080 PROFILEINFOW ProfileInfoW = {0};
1081 int len;
1082
1083 DPRINT("LoadUserProfileA() called\n");
1084
1085 /* Check profile info */
1086 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOA)) ||
1087 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
1088 {
1089 SetLastError(ERROR_INVALID_PARAMETER);
1090 return FALSE;
1091 }
1092
1093 /* Convert the structure to UNICODE... */
1094 ProfileInfoW.dwSize = sizeof(ProfileInfoW);
1095 ProfileInfoW.dwFlags = lpProfileInfo->dwFlags;
1096
1097 if (lpProfileInfo->lpUserName)
1098 {
1099 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, NULL, 0);
1100 ProfileInfoW.lpUserName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1101 if (!ProfileInfoW.lpUserName)
1102 {
1103 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1104 goto cleanup;
1105 }
1106 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpUserName, -1, ProfileInfoW.lpUserName, len);
1107 }
1108
1109 if (lpProfileInfo->lpProfilePath)
1110 {
1111 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, NULL, 0);
1112 ProfileInfoW.lpProfilePath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1113 if (!ProfileInfoW.lpProfilePath)
1114 {
1115 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1116 goto cleanup;
1117 }
1118 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpProfilePath, -1, ProfileInfoW.lpProfilePath, len);
1119 }
1120
1121 if (lpProfileInfo->lpDefaultPath)
1122 {
1123 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, NULL, 0);
1124 ProfileInfoW.lpDefaultPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1125 if (!ProfileInfoW.lpDefaultPath)
1126 {
1127 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1128 goto cleanup;
1129 }
1130 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpDefaultPath, -1, ProfileInfoW.lpDefaultPath, len);
1131 }
1132
1133 if (lpProfileInfo->lpServerName)
1134 {
1135 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, NULL, 0);
1136 ProfileInfoW.lpServerName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1137 if (!ProfileInfoW.lpServerName)
1138 {
1139 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1140 goto cleanup;
1141 }
1142 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpServerName, -1, ProfileInfoW.lpServerName, len);
1143 }
1144
1145 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && lpProfileInfo->lpPolicyPath)
1146 {
1147 len = MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, NULL, 0);
1148 ProfileInfoW.lpPolicyPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1149 if (!ProfileInfoW.lpPolicyPath)
1150 {
1151 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1152 goto cleanup;
1153 }
1154 MultiByteToWideChar(CP_ACP, 0, lpProfileInfo->lpPolicyPath, -1, ProfileInfoW.lpPolicyPath, len);
1155 }
1156
1157 /* ... and call the UNICODE function */
1158 bResult = LoadUserProfileW(hToken, &ProfileInfoW);
1159
1160 /* Save the returned value */
1161 lpProfileInfo->hProfile = ProfileInfoW.hProfile;
1162
1163 cleanup:
1164 /* Memory cleanup */
1165 if (ProfileInfoW.lpUserName)
1166 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpUserName);
1167
1168 if (ProfileInfoW.lpProfilePath)
1169 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpProfilePath);
1170
1171 if (ProfileInfoW.lpDefaultPath)
1172 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpDefaultPath);
1173
1174 if (ProfileInfoW.lpServerName)
1175 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpServerName);
1176
1177 if ((ProfileInfoW.dwFlags & PI_APPLYPOLICY) != 0 && ProfileInfoW.lpPolicyPath)
1178 HeapFree(GetProcessHeap(), 0, ProfileInfoW.lpPolicyPath);
1179
1180 return bResult;
1181 }
1182
1183
1184 BOOL
1185 WINAPI
1186 LoadUserProfileW(
1187 _In_ HANDLE hToken,
1188 _Inout_ LPPROFILEINFOW lpProfileInfo)
1189 {
1190 WCHAR szUserHivePath[MAX_PATH];
1191 LPWSTR UserName = NULL, Domain = NULL;
1192 DWORD UserNameLength = 0, DomainLength = 0;
1193 PTOKEN_USER UserSid = NULL;
1194 SID_NAME_USE AccountType;
1195 UNICODE_STRING SidString = { 0, 0, NULL };
1196 LONG Error;
1197 BOOL ret = FALSE;
1198 DWORD dwLength = sizeof(szUserHivePath) / sizeof(szUserHivePath[0]);
1199
1200 DPRINT("LoadUserProfileW() called\n");
1201
1202 /* Check profile info */
1203 if (!lpProfileInfo || (lpProfileInfo->dwSize != sizeof(PROFILEINFOW)) ||
1204 (lpProfileInfo->lpUserName == NULL) || (lpProfileInfo->lpUserName[0] == 0))
1205 {
1206 SetLastError(ERROR_INVALID_PARAMETER);
1207 return FALSE;
1208 }
1209
1210 /* Don't load a profile twice */
1211 if (CheckForLoadedProfile(hToken))
1212 {
1213 DPRINT ("Profile already loaded\n");
1214 lpProfileInfo->hProfile = NULL;
1215 return TRUE;
1216 }
1217
1218 if (lpProfileInfo->lpProfilePath)
1219 {
1220 wcscpy(szUserHivePath, lpProfileInfo->lpProfilePath);
1221 }
1222 else
1223 {
1224 /* FIXME: check if MS Windows allows lpProfileInfo->lpProfilePath to be NULL */
1225 if (!GetProfilesDirectoryW(szUserHivePath, &dwLength))
1226 {
1227 DPRINT1("GetProfilesDirectoryW() failed (error %ld)\n", GetLastError());
1228 return FALSE;
1229 }
1230 }
1231
1232 /* Create user hive name */
1233 wcscat(szUserHivePath, L"\\");
1234 wcscat(szUserHivePath, lpProfileInfo->lpUserName);
1235 wcscat(szUserHivePath, L"\\ntuser.dat");
1236 DPRINT("szUserHivePath: %S\n", szUserHivePath);
1237
1238 /* Create user profile directory if needed */
1239 if (GetFileAttributesW(szUserHivePath) == INVALID_FILE_ATTRIBUTES)
1240 {
1241 /* Get user sid */
1242 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwLength) ||
1243 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1244 {
1245 DPRINT1 ("GetTokenInformation() failed\n");
1246 return FALSE;
1247 }
1248
1249 UserSid = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, dwLength);
1250 if (!UserSid)
1251 {
1252 DPRINT1("HeapAlloc() failed\n");
1253 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1254 goto cleanup;
1255 }
1256
1257 if (!GetTokenInformation(hToken, TokenUser, UserSid, dwLength, &dwLength))
1258 {
1259 DPRINT1("GetTokenInformation() failed\n");
1260 goto cleanup;
1261 }
1262
1263 /* Get user name */
1264 do
1265 {
1266 if (UserNameLength > 0)
1267 {
1268 HeapFree(GetProcessHeap(), 0, UserName);
1269 UserName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, UserNameLength * sizeof(WCHAR));
1270 if (!UserName)
1271 {
1272 DPRINT1("HeapAlloc() failed\n");
1273 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1274 goto cleanup;
1275 }
1276 }
1277 if (DomainLength > 0)
1278 {
1279 HeapFree(GetProcessHeap(), 0, Domain);
1280 Domain = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, DomainLength * sizeof(WCHAR));
1281 if (!Domain)
1282 {
1283 DPRINT1("HeapAlloc() failed\n");
1284 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1285 goto cleanup;
1286 }
1287 }
1288 ret = LookupAccountSidW(NULL,
1289 UserSid->User.Sid,
1290 UserName,
1291 &UserNameLength,
1292 Domain,
1293 &DomainLength,
1294 &AccountType);
1295 } while (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
1296
1297 if (!ret)
1298 {
1299 DPRINT1("LookupAccountSidW() failed\n");
1300 goto cleanup;
1301 }
1302
1303 /* Create profile */
1304 /* FIXME: ignore Domain? */
1305 DPRINT("UserName %S, Domain %S\n", UserName, Domain);
1306 ret = CreateUserProfileW(UserSid->User.Sid, UserName);
1307 if (!ret)
1308 {
1309 DPRINT1("CreateUserProfileW() failed\n");
1310 goto cleanup;
1311 }
1312 }
1313
1314 /* Get user SID string */
1315 ret = GetUserSidStringFromToken(hToken, &SidString);
1316 if (!ret)
1317 {
1318 DPRINT1("GetUserSidFromToken() failed\n");
1319 goto cleanup;
1320 }
1321 ret = FALSE;
1322
1323 /* Acquire restore privilege */
1324 if (!AcquireRemoveRestorePrivilege(TRUE))
1325 {
1326 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1327 goto cleanup;
1328 }
1329
1330 /* Load user registry hive */
1331 Error = RegLoadKeyW(HKEY_USERS,
1332 SidString.Buffer,
1333 szUserHivePath);
1334 AcquireRemoveRestorePrivilege(FALSE);
1335
1336 /* HACK: Do not fail if the profile has already been loaded! */
1337 if (Error == ERROR_SHARING_VIOLATION)
1338 Error = ERROR_SUCCESS;
1339
1340 if (Error != ERROR_SUCCESS)
1341 {
1342 DPRINT1("RegLoadKeyW() failed (Error %ld)\n", Error);
1343 SetLastError((DWORD)Error);
1344 goto cleanup;
1345 }
1346
1347 /* Open future HKEY_CURRENT_USER */
1348 Error = RegOpenKeyExW(HKEY_USERS,
1349 SidString.Buffer,
1350 0,
1351 MAXIMUM_ALLOWED,
1352 (PHKEY)&lpProfileInfo->hProfile);
1353 if (Error != ERROR_SUCCESS)
1354 {
1355 DPRINT1("RegOpenKeyExW() failed (Error %ld)\n", Error);
1356 SetLastError((DWORD)Error);
1357 goto cleanup;
1358 }
1359
1360 ret = TRUE;
1361
1362 cleanup:
1363 HeapFree(GetProcessHeap(), 0, UserSid);
1364 HeapFree(GetProcessHeap(), 0, UserName);
1365 HeapFree(GetProcessHeap(), 0, Domain);
1366 RtlFreeUnicodeString(&SidString);
1367
1368 DPRINT("LoadUserProfileW() done\n");
1369 return ret;
1370 }
1371
1372
1373 BOOL
1374 WINAPI
1375 UnloadUserProfile(
1376 _In_ HANDLE hToken,
1377 _In_ HANDLE hProfile)
1378 {
1379 UNICODE_STRING SidString;
1380 LONG Error;
1381
1382 DPRINT("UnloadUserProfile() called\n");
1383
1384 if (hProfile == NULL)
1385 {
1386 DPRINT1("Invalid profile handle\n");
1387 SetLastError(ERROR_INVALID_PARAMETER);
1388 return FALSE;
1389 }
1390
1391 RegCloseKey(hProfile);
1392
1393 if (!GetUserSidStringFromToken(hToken,
1394 &SidString))
1395 {
1396 DPRINT1("GetUserSidFromToken() failed\n");
1397 return FALSE;
1398 }
1399
1400 DPRINT("SidString: '%wZ'\n", &SidString);
1401
1402 /* Acquire restore privilege */
1403 if (!AcquireRemoveRestorePrivilege(TRUE))
1404 {
1405 DPRINT1("AcquireRemoveRestorePrivilege() failed (Error %ld)\n", GetLastError());
1406 RtlFreeUnicodeString(&SidString);
1407 return FALSE;
1408 }
1409
1410 /* HACK */
1411 {
1412 HKEY hUserKey;
1413
1414 Error = RegOpenKeyExW(HKEY_USERS,
1415 SidString.Buffer,
1416 0,
1417 KEY_WRITE,
1418 &hUserKey);
1419 if (Error == ERROR_SUCCESS)
1420 {
1421 RegDeleteKeyW(hUserKey,
1422 L"Volatile Environment");
1423
1424 RegCloseKey(hUserKey);
1425 }
1426 }
1427 /* End of HACK */
1428
1429 /* Unload the hive */
1430 Error = RegUnLoadKeyW(HKEY_USERS,
1431 SidString.Buffer);
1432
1433 /* Remove restore privilege */
1434 AcquireRemoveRestorePrivilege(FALSE);
1435
1436 if (Error != ERROR_SUCCESS)
1437 {
1438 DPRINT1("RegUnLoadKeyW() failed (Error %ld)\n", Error);
1439 RtlFreeUnicodeString(&SidString);
1440 SetLastError((DWORD)Error);
1441 return FALSE;
1442 }
1443
1444 RtlFreeUnicodeString(&SidString);
1445
1446 DPRINT("UnloadUserProfile() done\n");
1447
1448 return TRUE;
1449 }
1450
1451
1452 BOOL
1453 WINAPI
1454 DeleteProfileW(
1455 _In_ LPCWSTR lpSidString,
1456 _In_opt_ LPCWSTR lpProfilePath,
1457 _In_opt_ LPCWSTR lpComputerName)
1458 {
1459 DPRINT1("DeleteProfileW() not implemented!\n");
1460 return FALSE;
1461 }
1462
1463
1464 BOOL
1465 WINAPI
1466 DeleteProfileA(
1467 _In_ LPCSTR lpSidString,
1468 _In_opt_ LPCSTR lpProfilePath,
1469 _In_opt_ LPCSTR lpComputerName)
1470 {
1471 BOOL bResult;
1472 UNICODE_STRING SidString, ProfilePath, ComputerName;
1473
1474 DPRINT("DeleteProfileA() called\n");
1475
1476 /* Conversion to UNICODE */
1477 if (lpSidString)
1478 RtlCreateUnicodeStringFromAsciiz(&SidString,
1479 (LPSTR)lpSidString);
1480
1481 if (lpProfilePath)
1482 RtlCreateUnicodeStringFromAsciiz(&ProfilePath,
1483 (LPSTR)lpProfilePath);
1484
1485 if (lpComputerName)
1486 RtlCreateUnicodeStringFromAsciiz(&ComputerName,
1487 (LPSTR)lpComputerName);
1488
1489 /* Call the UNICODE function */
1490 bResult = DeleteProfileW(SidString.Buffer,
1491 ProfilePath.Buffer,
1492 ComputerName.Buffer);
1493
1494 /* Memory cleanup */
1495 if (lpSidString)
1496 RtlFreeUnicodeString(&SidString);
1497
1498 if (lpProfilePath)
1499 RtlFreeUnicodeString(&ProfilePath);
1500
1501 if (lpComputerName)
1502 RtlFreeUnicodeString(&ComputerName);
1503
1504 return bResult;
1505 }
1506
1507
1508 BOOL
1509 WINAPI
1510 GetProfileType(_Out_ PDWORD pdwFlags)
1511 {
1512 DPRINT1("GetProfileType() not implemented!\n");
1513 return FALSE;
1514 }
1515
1516 /* EOF */