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