[CRT] Remove useless #undef abort from process.h
[reactos.git] / dll / cpl / sysdm / userprofile.c
1 /*
2 * PROJECT: ReactOS System Control Panel Applet
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/cpl/sysdm/userprofile.c
5 * PURPOSE: Computer settings for networking
6 * COPYRIGHT: Copyright Thomas Weidenmueller <w3seek@reactos.org>
7 * Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
8 *
9 */
10
11 #include "precomp.h"
12 #include <sddl.h>
13 #include <winnls.h>
14
15 #include <debug.h>
16
17 typedef struct _PROFILEDATA
18 {
19 DWORD dwRefCount;
20 DWORD dwState;
21 BOOL bUnknownProfile;
22 PWSTR pszFullName;
23 PWSTR pszProfilePath;
24 } PROFILEDATA, *PPROFILEDATA;
25
26
27 static
28 BOOL
29 OnProfileTypeInit(
30 _In_ HWND hwndDlg,
31 _In_ PPROFILEDATA pProfileData)
32 {
33 PWSTR pszRawBuffer = NULL, pszCookedBuffer = NULL;
34 INT nLength;
35
36 nLength = LoadStringW(hApplet, IDS_USERPROFILE_TYPE_TEXT, (PWSTR)&pszRawBuffer, 0);
37 pszRawBuffer = NULL;
38 if (nLength == 0)
39 return FALSE;
40
41 pszRawBuffer = HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(WCHAR));
42 if (pszRawBuffer == NULL)
43 return FALSE;
44
45 LoadStringW(hApplet, IDS_USERPROFILE_TYPE_TEXT, pszRawBuffer, nLength + 1);
46
47 pszCookedBuffer = HeapAlloc(GetProcessHeap(), 0, (nLength + wcslen(pProfileData->pszFullName) + 1) * sizeof(WCHAR));
48 if (pszCookedBuffer == NULL)
49 goto done;
50
51 swprintf(pszCookedBuffer, pszRawBuffer, pProfileData->pszFullName);
52
53 /* Set the full text */
54 SetDlgItemText(hwndDlg, IDC_USERPROFILE_TYPE_TEXT, pszCookedBuffer);
55
56 /* FIXME: Right now, we support local user profiles only! */
57 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_TYPE_ROAMING), FALSE);
58 Button_SetCheck(GetDlgItem(hwndDlg, IDC_USERPROFILE_TYPE_LOCAL), BST_CHECKED);
59 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
60
61 done:
62 if (pszCookedBuffer != NULL)
63 HeapFree(GetProcessHeap(), 0, pszCookedBuffer);
64
65 if (pszRawBuffer != NULL)
66 HeapFree(GetProcessHeap(), 0, pszRawBuffer);
67
68 return TRUE;
69 }
70
71
72 static
73 INT_PTR
74 CALLBACK
75 UserProfileTypeDlgProc(
76 _In_ HWND hwndDlg,
77 _In_ UINT uMsg,
78 _In_ WPARAM wParam,
79 _In_ LPARAM lParam)
80 {
81 switch (uMsg)
82 {
83 case WM_INITDIALOG:
84 OnProfileTypeInit(hwndDlg, (PPROFILEDATA)lParam);
85 return TRUE;
86
87 case WM_DESTROY:
88 break;
89
90 case WM_COMMAND:
91 switch (LOWORD(wParam))
92 {
93 case IDOK:
94 case IDCANCEL:
95 EndDialog(hwndDlg,
96 LOWORD(wParam));
97 return TRUE;
98 }
99 break;
100 }
101
102 return FALSE;
103 }
104
105
106 static
107 BOOL
108 ChangeUserProfileType(
109 _In_ HWND hwndDlg)
110 {
111 HWND hwndListView;
112 LVITEM Item;
113 INT iSelected;
114
115 DPRINT("ChangeUserProfileType(%p)\n", hwndDlg);
116
117 hwndListView = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST);
118 if (hwndListView == NULL)
119 return FALSE;
120
121 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED);
122 if (iSelected == -1)
123 return FALSE;
124
125 ZeroMemory(&Item, sizeof(LVITEM));
126 Item.mask = LVIF_PARAM;
127 Item.iItem = iSelected;
128 if (!ListView_GetItem(hwndListView, &Item))
129 return FALSE;
130
131 if (Item.lParam == 0)
132 return FALSE;
133
134 if (DialogBoxParam(hApplet,
135 MAKEINTRESOURCE(IDD_USERPROFILE_TYPE),
136 hwndDlg,
137 UserProfileTypeDlgProc,
138 (LPARAM)Item.lParam) == IDOK)
139 {
140 /* FIXME: Update the profile list view */
141 return TRUE;
142 }
143
144 return FALSE;
145 }
146
147
148 static
149 BOOL
150 DeleteUserProfile(
151 _In_ HWND hwndDlg)
152 {
153 WCHAR szTitle[64], szRawText[128], szCookedText[256];
154 HWND hwndListView;
155 LVITEM Item;
156 INT iSelected;
157 PPROFILEDATA pProfileData;
158
159 DPRINT("DeleteUserProfile()\n");
160
161 hwndListView = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST);
162 if (hwndListView == NULL)
163 return FALSE;
164
165 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED);
166 if (iSelected == -1)
167 return FALSE;
168
169 ZeroMemory(&Item, sizeof(LVITEM));
170 Item.mask = LVIF_PARAM;
171 Item.iItem = iSelected;
172 if (!ListView_GetItem(hwndListView, &Item))
173 return FALSE;
174
175 if (Item.lParam == 0)
176 return FALSE;
177
178 pProfileData = (PPROFILEDATA)Item.lParam;
179 if (pProfileData->dwRefCount != 0)
180 return FALSE;
181
182 LoadStringW(hApplet, IDS_USERPROFILE_CONFIRM_DELETE_TITLE, szTitle, ARRAYSIZE(szTitle));
183 LoadStringW(hApplet, IDS_USERPROFILE_CONFIRM_DELETE, szRawText, ARRAYSIZE(szRawText));
184 swprintf(szCookedText, szRawText, pProfileData->pszFullName);
185
186 if (MessageBoxW(hwndDlg,
187 szCookedText,
188 szTitle,
189 MB_ICONQUESTION | MB_YESNO) == IDYES)
190 {
191 /* FIXME: Delete the profile here! */
192 return TRUE;
193 }
194
195 return FALSE;
196 }
197
198
199 static
200 INT_PTR
201 CALLBACK
202 CopyUserProfileDlgProc(
203 _In_ HWND hwndDlg,
204 _In_ UINT uMsg,
205 _In_ WPARAM wParam,
206 _In_ LPARAM lParam)
207 {
208 switch (uMsg)
209 {
210 case WM_INITDIALOG:
211 return TRUE;
212
213 case WM_DESTROY:
214 break;
215
216 case WM_COMMAND:
217 switch (LOWORD(wParam))
218 {
219 case IDOK:
220 case IDCANCEL:
221 EndDialog(hwndDlg,
222 LOWORD(wParam));
223 return TRUE;
224 }
225 break;
226 }
227
228 return FALSE;
229 }
230
231
232 static
233 BOOL
234 CopyUserProfile(
235 _In_ HWND hwndDlg)
236 {
237 HWND hwndListView;
238 LVITEM Item;
239 INT iSelected;
240
241 DPRINT("CopyUserProfile()\n");
242
243 hwndListView = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST);
244 if (hwndListView == NULL)
245 return FALSE;
246
247 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED);
248 if (iSelected == -1)
249 return FALSE;
250
251 ZeroMemory(&Item, sizeof(LVITEM));
252 Item.mask = LVIF_PARAM;
253 Item.iItem = iSelected;
254 if (!ListView_GetItem(hwndListView, &Item))
255 return FALSE;
256
257 if (Item.lParam == 0)
258 return FALSE;
259
260 if (DialogBoxParam(hApplet,
261 MAKEINTRESOURCE(IDD_USERPROFILE_COPY),
262 hwndDlg,
263 CopyUserProfileDlgProc,
264 (LPARAM)Item.lParam) == IDOK)
265 {
266 /* FIXME: Update the profile list view */
267 return TRUE;
268 }
269
270 return FALSE;
271 }
272
273
274 static VOID
275 SetListViewColumns(
276 _In_ HWND hwndListView)
277 {
278 LV_COLUMN column;
279 RECT rect;
280 TCHAR szStr[32];
281
282 GetClientRect(hwndListView, &rect);
283
284 SendMessage(hwndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
285
286 memset(&column, 0x00, sizeof(column));
287 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
288 column.fmt = LVCFMT_LEFT;
289 column.cx = (INT)((rect.right - rect.left) * 0.40);
290 column.iSubItem = 0;
291 LoadString(hApplet, IDS_USERPROFILE_NAME, szStr, ARRAYSIZE(szStr));
292 column.pszText = szStr;
293 (void)ListView_InsertColumn(hwndListView, 0, &column);
294
295 column.fmt = LVCFMT_RIGHT;
296 column.cx = (INT)((rect.right - rect.left) * 0.15);
297 column.iSubItem = 1;
298 LoadString(hApplet, IDS_USERPROFILE_SIZE, szStr, ARRAYSIZE(szStr));
299 column.pszText = szStr;
300 (void)ListView_InsertColumn(hwndListView, 1, &column);
301
302 column.fmt = LVCFMT_LEFT;
303 column.cx = (INT)((rect.right - rect.left) * 0.15);
304 column.iSubItem = 2;
305 LoadString(hApplet, IDS_USERPROFILE_TYPE, szStr, ARRAYSIZE(szStr));
306 column.pszText = szStr;
307 (void)ListView_InsertColumn(hwndListView, 2, &column);
308
309 column.fmt = LVCFMT_LEFT;
310 column.cx = (INT)((rect.right - rect.left) * 0.15);
311 column.iSubItem = 3;
312 LoadString(hApplet, IDS_USERPROFILE_STATUS, szStr, ARRAYSIZE(szStr));
313 column.pszText = szStr;
314 (void)ListView_InsertColumn(hwndListView, 3, &column);
315
316 column.fmt = LVCFMT_LEFT;
317 column.cx = (INT)((rect.right - rect.left) * 0.15) - GetSystemMetrics(SM_CYHSCROLL);
318 column.iSubItem = 4;
319 LoadString(hApplet, IDS_USERPROFILE_MODIFIED, szStr, ARRAYSIZE(szStr));
320 column.pszText = szStr;
321 (void)ListView_InsertColumn(hwndListView, 4, &column);
322 }
323
324
325 static
326 BOOL
327 GetProfileSize(
328 _In_ PWSTR pszProfilePath,
329 _Inout_ PULONGLONG pullProfileSize)
330 {
331 HANDLE hFile = INVALID_HANDLE_VALUE;
332 WIN32_FIND_DATA FindData;
333 DWORD dwProfilePathLength;
334 ULARGE_INTEGER Size;
335 BOOL bResult = TRUE;
336
337 dwProfilePathLength = wcslen(pszProfilePath);
338
339 wcscat(pszProfilePath, L"\\*.*");
340
341 hFile = FindFirstFileW(pszProfilePath, &FindData);
342 if (hFile == INVALID_HANDLE_VALUE)
343 {
344 if ((GetLastError() != ERROR_FILE_NOT_FOUND) &&
345 (GetLastError() != ERROR_PATH_NOT_FOUND))
346 bResult = FALSE;
347
348 goto done;
349 }
350
351 do
352 {
353 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
354 {
355 if ((_wcsicmp(FindData.cFileName, L".") == 0) ||
356 (_wcsicmp(FindData.cFileName, L"..") == 0))
357 continue;
358
359 pszProfilePath[dwProfilePathLength + 1] = UNICODE_NULL;
360 wcscat(pszProfilePath, FindData.cFileName);
361
362 if (!GetProfileSize(pszProfilePath, pullProfileSize))
363 {
364 bResult = FALSE;
365 goto done;
366 }
367 }
368 else
369 {
370 Size.u.LowPart = FindData.nFileSizeLow;
371 Size.u.HighPart = FindData.nFileSizeHigh;
372 *pullProfileSize += Size.QuadPart;
373 }
374 }
375 while (FindNextFile(hFile, &FindData));
376
377 done:
378 pszProfilePath[dwProfilePathLength] = UNICODE_NULL;
379
380 if (hFile != INVALID_HANDLE_VALUE)
381 FindClose(hFile);
382
383 return bResult;
384 }
385
386
387 static
388 BOOL
389 GetProfileName(
390 _In_ PSID pProfileSid,
391 _In_ DWORD dwNameBufferSize,
392 _Out_ PWSTR pszNameBuffer,
393 _Out_ PBOOL pbUnknownProfile)
394 {
395 WCHAR szAccountName[128], szDomainName[128];
396 DWORD dwAccountNameSize, dwDomainNameSize;
397 SID_NAME_USE Use;
398
399 dwAccountNameSize = ARRAYSIZE(szAccountName);
400 dwDomainNameSize = ARRAYSIZE(szDomainName);
401 if (!LookupAccountSidW(NULL,
402 pProfileSid,
403 szAccountName,
404 &dwAccountNameSize,
405 szDomainName,
406 &dwDomainNameSize,
407 &Use))
408 {
409 /* Unknown account */
410 LoadStringW(hApplet, IDS_USERPROFILE_ACCOUNT_UNKNOWN, pszNameBuffer, dwNameBufferSize);
411 *pbUnknownProfile = TRUE;
412 }
413 else
414 {
415 /* Show only the user accounts */
416 if (Use != SidTypeUser)
417 return FALSE;
418
419 if (szAccountName[0] == UNICODE_NULL)
420 {
421 /* Deleted account */
422 LoadStringW(hApplet, IDS_USERPROFILE_ACCOUNT_DELETED, pszNameBuffer, dwNameBufferSize);
423 }
424 else
425 {
426 /* Normal account */
427 wsprintf(pszNameBuffer, L"%s\\%s", szDomainName, szAccountName);
428 }
429 *pbUnknownProfile = FALSE;
430 }
431
432 return TRUE;
433 }
434
435
436 static VOID
437 AddUserProfile(
438 _In_ HWND hwndListView,
439 _In_ PSID pProfileSid,
440 _In_ HKEY hProfileKey)
441 {
442 WCHAR szTempProfilePath[MAX_PATH], szProfilePath[MAX_PATH];
443 WCHAR szNameBuffer[256];
444 PPROFILEDATA pProfileData = NULL;
445 DWORD dwProfileData, dwSize, dwType, dwState = 0, dwRefCount = 0;
446 DWORD dwProfilePathLength;
447 PWSTR ptr;
448 INT nId, iItem;
449 LV_ITEM lvi;
450 WIN32_FIND_DATA FindData;
451 HANDLE hFile;
452 SYSTEMTIME SystemTime;
453 ULONGLONG ullProfileSize;
454 BOOL bUnknownProfile;
455 DWORD dwError;
456
457 /* Get the profile path */
458 dwSize = MAX_PATH * sizeof(WCHAR);
459 dwError = RegQueryValueExW(hProfileKey,
460 L"ProfileImagePath",
461 NULL,
462 &dwType,
463 (LPBYTE)szTempProfilePath,
464 &dwSize);
465 if (dwError != ERROR_SUCCESS)
466 return;
467
468 /* Expand it */
469 ExpandEnvironmentStringsW(szTempProfilePath,
470 szProfilePath,
471 MAX_PATH);
472
473 /* Check if the profile path exists */
474 hFile = FindFirstFileW(szProfilePath, &FindData);
475 if (hFile == INVALID_HANDLE_VALUE)
476 return;
477
478 FindClose(hFile);
479
480 /* Get the length of the profile path */
481 dwProfilePathLength = wcslen(szProfilePath);
482
483 /* Check for the ntuser.dat file */
484 wcscat(szProfilePath, L"\\ntuser.dat");
485 hFile = FindFirstFileW(szProfilePath, &FindData);
486 if (hFile == INVALID_HANDLE_VALUE)
487 return;
488
489 FindClose(hFile);
490 szProfilePath[dwProfilePathLength] = UNICODE_NULL;
491
492 /* Get the profile size */
493 ullProfileSize = 0ULL;
494 GetProfileSize(szProfilePath, &ullProfileSize);
495
496 /* Get the profile name */
497 if (!GetProfileName(pProfileSid,
498 ARRAYSIZE(szNameBuffer),
499 szNameBuffer,
500 &bUnknownProfile))
501 return;
502
503 /* Get the profile state value */
504 dwSize = sizeof(dwState);
505 if (RegQueryValueExW(hProfileKey,
506 L"State",
507 NULL,
508 &dwType,
509 (LPBYTE)&dwState,
510 &dwSize) != ERROR_SUCCESS)
511 {
512 dwState = 0;
513 }
514
515 /* Get the profile reference counter */
516 dwSize = sizeof(dwRefCount);
517 if (RegQueryValueExW(hProfileKey,
518 L"RefCount",
519 NULL,
520 &dwType,
521 (LPBYTE)&dwRefCount,
522 &dwSize) != ERROR_SUCCESS)
523 {
524 dwRefCount = 0;
525 }
526
527 /* Create and fill the profile data entry */
528 dwProfileData = sizeof(PROFILEDATA) +
529 ((wcslen(szNameBuffer) + 1) * sizeof(WCHAR)) +
530 ((wcslen(szProfilePath) + 1) * sizeof(WCHAR));
531 pProfileData = HeapAlloc(GetProcessHeap(),
532 HEAP_ZERO_MEMORY,
533 dwProfileData);
534 if (pProfileData == NULL)
535 return;
536
537 pProfileData->dwRefCount = dwRefCount;
538 pProfileData->dwState = dwState;
539 pProfileData->bUnknownProfile = bUnknownProfile;
540
541 ptr = (PWSTR)((ULONG_PTR)pProfileData + sizeof(PROFILEDATA));
542 pProfileData->pszFullName = ptr;
543
544 wcscpy(pProfileData->pszFullName, szNameBuffer);
545
546 ptr = (PWSTR)((ULONG_PTR)ptr + ((wcslen(pProfileData->pszFullName) + 1) * sizeof(WCHAR)));
547 pProfileData->pszProfilePath = ptr;
548 wcscpy(pProfileData->pszProfilePath, szProfilePath);
549
550 /* Add the profile and set its name */
551 memset(&lvi, 0x00, sizeof(lvi));
552 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
553 lvi.pszText = pProfileData->pszFullName;
554 lvi.state = 0;
555 lvi.lParam = (LPARAM)pProfileData;
556 iItem = ListView_InsertItem(hwndListView, &lvi);
557
558 /* Set the profile size */
559 StrFormatByteSizeW(ullProfileSize, szNameBuffer, ARRAYSIZE(szNameBuffer) - 1);
560 ListView_SetItemText(hwndListView, iItem, 1, szNameBuffer);
561
562 /* Set the profile type */
563 if (dwState & 0x0010) // PROFILE_UPDATE_CENTRAL
564 nId = IDS_USERPROFILE_ROAMING;
565 else
566 nId = IDS_USERPROFILE_LOCAL;
567
568 LoadStringW(hApplet, nId, szNameBuffer, ARRAYSIZE(szNameBuffer));
569
570 ListView_SetItemText(hwndListView, iItem, 2, szNameBuffer);
571
572 /* FIXME: Set the profile status */
573 if (dwState & 0x0001) // PROFILE_MANDATORY
574 nId = IDS_USERPROFILE_MANDATORY;
575 else if (dwState & 0x0010) // PROFILE_UPDATE_CENTRAL
576 nId = IDS_USERPROFILE_ROAMING;
577 else
578 nId = IDS_USERPROFILE_LOCAL;
579
580 LoadStringW(hApplet, nId, szNameBuffer, ARRAYSIZE(szNameBuffer));
581
582 ListView_SetItemText(hwndListView, iItem, 3, szNameBuffer);
583
584 /* Set the profile modified time */
585 FileTimeToSystemTime(&FindData.ftLastWriteTime,
586 &SystemTime);
587
588 GetDateFormatW(LOCALE_USER_DEFAULT,
589 DATE_SHORTDATE,
590 &SystemTime,
591 NULL,
592 szNameBuffer,
593 ARRAYSIZE(szNameBuffer));
594
595 ListView_SetItemText(hwndListView, iItem, 4, szNameBuffer);
596 }
597
598
599 static VOID
600 UpdateButtonState(
601 _In_ HWND hwndDlg,
602 _In_ HWND hwndListView)
603 {
604 LVITEM Item;
605 INT iSelected;
606 BOOL bChange = FALSE;
607 BOOL bCopy = FALSE;
608 BOOL bDelete = FALSE;
609 PPROFILEDATA pProfileData;
610
611 if (ListView_GetSelectedCount(hwndListView) != 0)
612 {
613 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED);
614 if (iSelected != -1)
615 {
616 ZeroMemory(&Item, sizeof(LVITEM));
617 Item.mask = LVIF_PARAM;
618 Item.iItem = iSelected;
619 if (ListView_GetItem(hwndListView, &Item))
620 {
621 if (Item.lParam != 0)
622 {
623 pProfileData = (PPROFILEDATA)Item.lParam;
624
625 if (pProfileData->bUnknownProfile)
626 {
627 bDelete = TRUE;
628 bCopy = FALSE;
629 }
630 else
631 {
632 bDelete = (pProfileData->dwRefCount == 0);
633 bCopy = (pProfileData->dwRefCount == 0);
634 }
635 }
636 }
637
638 bChange = TRUE;
639 }
640 }
641
642 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), bChange);
643 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), bDelete);
644 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), bCopy);
645 }
646
647
648 static VOID
649 AddUserProfiles(
650 _In_ HWND hwndDlg,
651 _In_ HWND hwndListView,
652 _In_ BOOL bAdmin)
653 {
654 HKEY hKeyUserProfiles = INVALID_HANDLE_VALUE;
655 HKEY hProfileKey;
656 DWORD dwIndex;
657 WCHAR szProfileSid[64];
658 DWORD dwSidLength;
659 FILETIME ftLastWrite;
660 DWORD dwSize;
661 HANDLE hToken = NULL;
662 PTOKEN_USER pTokenUser = NULL;
663 PSID pProfileSid;
664 PWSTR pszProfileSid;
665
666 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
667 return;
668
669 if (GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize) ||
670 GetLastError() != ERROR_INSUFFICIENT_BUFFER)
671 {
672 goto done;
673 }
674
675 pTokenUser = HeapAlloc(GetProcessHeap(), 0, dwSize);
676 if (pTokenUser == NULL)
677 goto done;
678
679 if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
680 goto done;
681
682 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
683 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
684 0,
685 KEY_READ,
686 &hKeyUserProfiles))
687 goto done;
688
689 if (bAdmin)
690 {
691 for (dwIndex = 0; ; dwIndex++)
692 {
693 dwSidLength = ARRAYSIZE(szProfileSid);
694 if (RegEnumKeyExW(hKeyUserProfiles,
695 dwIndex,
696 szProfileSid,
697 &dwSidLength,
698 NULL,
699 NULL,
700 NULL,
701 &ftLastWrite))
702 break;
703
704 if (RegOpenKeyExW(hKeyUserProfiles,
705 szProfileSid,
706 0,
707 KEY_READ,
708 &hProfileKey) == ERROR_SUCCESS)
709 {
710 if (ConvertStringSidToSid(szProfileSid, &pProfileSid))
711 {
712 AddUserProfile(hwndListView,
713 pProfileSid,
714 hProfileKey);
715 LocalFree(pProfileSid);
716 }
717
718 RegCloseKey(hProfileKey);
719 }
720 }
721 }
722 else
723 {
724 if (ConvertSidToStringSidW(pTokenUser->User.Sid, &pszProfileSid))
725 {
726 if (RegOpenKeyExW(hKeyUserProfiles,
727 pszProfileSid,
728 0,
729 KEY_READ,
730 &hProfileKey) == ERROR_SUCCESS)
731 {
732 AddUserProfile(hwndListView,
733 pTokenUser->User.Sid,
734 hProfileKey);
735 RegCloseKey(hProfileKey);
736 }
737
738 LocalFree(pszProfileSid);
739 }
740 }
741
742 if (ListView_GetItemCount(hwndListView) != 0)
743 ListView_SetItemState(hwndListView, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
744
745 UpdateButtonState(hwndDlg, hwndListView);
746
747 done:
748 if (hKeyUserProfiles != INVALID_HANDLE_VALUE)
749 RegCloseKey(hKeyUserProfiles);
750
751 if (pTokenUser != NULL)
752 HeapFree(GetProcessHeap(), 0, pTokenUser);
753
754 if (hToken != NULL)
755 CloseHandle(hToken);
756 }
757
758
759 static VOID
760 OnInitUserProfileDialog(HWND hwndDlg)
761 {
762 BOOL bAdmin;
763
764 bAdmin = IsUserAdmin();
765
766 /* Initialize the list view control */
767 SetListViewColumns(GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST));
768
769 /* Hide the delete and copy buttons for non-admins */
770 ShowWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), bAdmin ? SW_SHOW : SW_HIDE);
771 ShowWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), bAdmin ? SW_SHOW : SW_HIDE);
772
773 /* Add the profiles to the list view */
774 AddUserProfiles(hwndDlg, GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST), bAdmin);
775 }
776
777 static
778 VOID
779 OnNotify(
780 _In_ HWND hwndDlg,
781 _In_ NMHDR *nmhdr)
782 {
783 LPNMLISTVIEW pNMLV;
784
785 if (nmhdr->idFrom == IDC_USERACCOUNT_LINK && nmhdr->code == NM_CLICK)
786 {
787 ShellExecuteW(hwndDlg, NULL, L"usrmgr.cpl", NULL, NULL, 0);
788 }
789 else if (nmhdr->idFrom == IDC_USERPROFILE_LIST)
790 {
791 switch(nmhdr->code)
792 {
793 case LVN_ITEMCHANGED:
794 UpdateButtonState(hwndDlg, nmhdr->hwndFrom);
795 break;
796
797 case NM_DBLCLK:
798 ChangeUserProfileType(hwndDlg);
799 break;
800
801 case LVN_DELETEITEM:
802 pNMLV = (LPNMLISTVIEW)nmhdr;
803 if (pNMLV->lParam != 0)
804 HeapFree(GetProcessHeap(), 0, (LPVOID)pNMLV->lParam);
805 break;
806 }
807 }
808 }
809
810
811 /* Property page dialog callback */
812 INT_PTR CALLBACK
813 UserProfileDlgProc(HWND hwndDlg,
814 UINT uMsg,
815 WPARAM wParam,
816 LPARAM lParam)
817 {
818 switch (uMsg)
819 {
820 case WM_INITDIALOG:
821 OnInitUserProfileDialog(hwndDlg);
822 return TRUE;
823
824 case WM_COMMAND:
825 switch (LOWORD(wParam))
826 {
827 case IDOK:
828 case IDCANCEL:
829 EndDialog(hwndDlg,
830 LOWORD(wParam));
831 return TRUE;
832
833 case IDC_USERPROFILE_CHANGE:
834 ChangeUserProfileType(hwndDlg);
835 break;
836
837 case IDC_USERPROFILE_DELETE:
838 DeleteUserProfile(hwndDlg);
839 break;
840
841 case IDC_USERPROFILE_COPY:
842 CopyUserProfile(hwndDlg);
843 break;
844 }
845 break;
846
847 case WM_NOTIFY:
848 OnNotify(hwndDlg, (NMHDR *)lParam);
849 break;
850 }
851
852 return FALSE;
853 }