[SYSDM] Check the profile directory and hive file and display the last write date...
[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 BOOL bMyProfile;
20 DWORD dwState;
21 PWSTR pszFullName;
22 } PROFILEDATA, *PPROFILEDATA;
23
24
25 static
26 BOOL
27 OnProfileTypeInit(
28 HWND hwndDlg,
29 PPROFILEDATA pProfileData)
30 {
31 PWSTR pszRawBuffer = NULL, pszCookedBuffer = NULL;
32 INT nLength;
33
34 nLength = LoadStringW(hApplet, IDS_USERPROFILE_TYPE_TEXT, (PWSTR)&pszRawBuffer, 0);
35 pszRawBuffer = NULL;
36 if (nLength == 0)
37 return FALSE;
38
39 pszRawBuffer = HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(WCHAR));
40 if (pszRawBuffer == NULL)
41 return FALSE;
42
43 LoadStringW(hApplet, IDS_USERPROFILE_TYPE_TEXT, pszRawBuffer, nLength + 1);
44
45 pszCookedBuffer = HeapAlloc(GetProcessHeap(), 0, (nLength + wcslen(pProfileData->pszFullName) + 1) * sizeof(WCHAR));
46 if (pszCookedBuffer == NULL)
47 goto done;
48
49 swprintf(pszCookedBuffer, pszRawBuffer, pProfileData->pszFullName);
50
51 /* Set the full text */
52 SetDlgItemText(hwndDlg, IDC_USERPROFILE_TYPE_TEXT, pszCookedBuffer);
53
54 /* FIXME: Right now, we support local user profiles only! */
55 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_TYPE_ROAMING), FALSE);
56 Button_SetCheck(GetDlgItem(hwndDlg, IDC_USERPROFILE_TYPE_LOCAL), BST_CHECKED);
57 EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
58
59 done:
60 if (pszCookedBuffer != NULL)
61 HeapFree(GetProcessHeap(), 0, pszCookedBuffer);
62
63 if (pszRawBuffer != NULL)
64 HeapFree(GetProcessHeap(), 0, pszRawBuffer);
65
66 return TRUE;
67 }
68
69
70 static
71 INT_PTR
72 CALLBACK
73 UserProfileTypeDlgProc(
74 _In_ HWND hwndDlg,
75 _In_ UINT uMsg,
76 _In_ WPARAM wParam,
77 _In_ LPARAM lParam)
78 {
79 switch (uMsg)
80 {
81 case WM_INITDIALOG:
82 OnProfileTypeInit(hwndDlg, (PPROFILEDATA)lParam);
83 return TRUE;
84
85 case WM_DESTROY:
86 break;
87
88 case WM_COMMAND:
89 switch (LOWORD(wParam))
90 {
91 case IDOK:
92 case IDCANCEL:
93 EndDialog(hwndDlg,
94 LOWORD(wParam));
95 return TRUE;
96 }
97 break;
98 }
99
100 return FALSE;
101 }
102
103
104 static
105 BOOL
106 ChangeUserProfileType(
107 _In_ HWND hwndDlg)
108 {
109 HWND hwndListView;
110 LVITEM Item;
111 INT iSelected;
112
113 DPRINT("ChangeUserProfileType(%p)\n", hwndDlg);
114
115 hwndListView = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST);
116 if (hwndListView == NULL)
117 return FALSE;
118
119 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED);
120 if (iSelected == -1)
121 return FALSE;
122
123 ZeroMemory(&Item, sizeof(LVITEM));
124 Item.mask = LVIF_PARAM;
125 Item.iItem = iSelected;
126 Item.iSubItem = 0;
127 if (!ListView_GetItem(hwndListView, &Item))
128 return FALSE;
129
130 if (Item.lParam == 0)
131 return FALSE;
132
133 if (DialogBoxParam(hApplet,
134 MAKEINTRESOURCE(IDD_USERPROFILE_TYPE),
135 hwndDlg,
136 UserProfileTypeDlgProc,
137 (LPARAM)Item.lParam) == IDOK)
138 {
139 /* FIXME: Update the profile list view */
140 return TRUE;
141 }
142
143 return FALSE;
144 }
145
146
147 static
148 BOOL
149 DeleteUserProfile(
150 _In_ HWND hwndDlg)
151 {
152 WCHAR szTitle[64], szRawText[128], szCookedText[256];
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 Item.iSubItem = 0;
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->bMyProfile)
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 Item.iSubItem = 0;
255 if (!ListView_GetItem(hwndListView, &Item))
256 return FALSE;
257
258 if (Item.lParam == 0)
259 return FALSE;
260
261 if (DialogBoxParam(hApplet,
262 MAKEINTRESOURCE(IDD_USERPROFILE_COPY),
263 hwndDlg,
264 CopyUserProfileDlgProc,
265 (LPARAM)Item.lParam) == IDOK)
266 {
267 /* FIXME: Update the profile list view */
268 return TRUE;
269 }
270
271 return FALSE;
272 }
273
274
275 static VOID
276 SetListViewColumns(
277 _In_ HWND hwndListView)
278 {
279 LV_COLUMN column;
280 RECT rect;
281 TCHAR szStr[32];
282
283 GetClientRect(hwndListView, &rect);
284
285 SendMessage(hwndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
286
287 memset(&column, 0x00, sizeof(column));
288 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
289 column.fmt = LVCFMT_LEFT;
290 column.cx = (INT)((rect.right - rect.left) * 0.40);
291 column.iSubItem = 0;
292 LoadString(hApplet, IDS_USERPROFILE_NAME, szStr, ARRAYSIZE(szStr));
293 column.pszText = szStr;
294 (void)ListView_InsertColumn(hwndListView, 0, &column);
295
296 column.fmt = LVCFMT_RIGHT;
297 column.cx = (INT)((rect.right - rect.left) * 0.15);
298 column.iSubItem = 1;
299 LoadString(hApplet, IDS_USERPROFILE_SIZE, szStr, ARRAYSIZE(szStr));
300 column.pszText = szStr;
301 (void)ListView_InsertColumn(hwndListView, 1, &column);
302
303 column.fmt = LVCFMT_LEFT;
304 column.cx = (INT)((rect.right - rect.left) * 0.15);
305 column.iSubItem = 2;
306 LoadString(hApplet, IDS_USERPROFILE_TYPE, szStr, ARRAYSIZE(szStr));
307 column.pszText = szStr;
308 (void)ListView_InsertColumn(hwndListView, 2, &column);
309
310 column.fmt = LVCFMT_LEFT;
311 column.cx = (INT)((rect.right - rect.left) * 0.15);
312 column.iSubItem = 3;
313 LoadString(hApplet, IDS_USERPROFILE_STATUS, szStr, ARRAYSIZE(szStr));
314 column.pszText = szStr;
315 (void)ListView_InsertColumn(hwndListView, 3, &column);
316
317 column.fmt = LVCFMT_LEFT;
318 column.cx = (INT)((rect.right - rect.left) * 0.15) - GetSystemMetrics(SM_CYHSCROLL);
319 column.iSubItem = 4;
320 LoadString(hApplet, IDS_USERPROFILE_MODIFIED, szStr, ARRAYSIZE(szStr));
321 column.pszText = szStr;
322 (void)ListView_InsertColumn(hwndListView, 4, &column);
323 }
324
325
326 static
327 BOOL
328 GetProfileName(
329 _In_ PSID pProfileSid,
330 _In_ DWORD dwNameBufferSize,
331 _Out_ PWSTR pszNameBuffer)
332 {
333 WCHAR szAccountName[128], szDomainName[128];
334 DWORD dwAccountNameSize, dwDomainNameSize;
335 SID_NAME_USE Use;
336
337 dwAccountNameSize = ARRAYSIZE(szAccountName);
338 dwDomainNameSize = ARRAYSIZE(szDomainName);
339 if (!LookupAccountSidW(NULL,
340 pProfileSid,
341 szAccountName,
342 &dwAccountNameSize,
343 szDomainName,
344 &dwDomainNameSize,
345 &Use))
346 {
347 /* Unknown account */
348 LoadStringW(hApplet, IDS_USERPROFILE_ACCOUNT_UNKNOWN, pszNameBuffer, dwNameBufferSize);
349 }
350 else
351 {
352 /* Show only the user accounts */
353 if (Use != SidTypeUser)
354 return FALSE;
355
356 if (szAccountName[0] == UNICODE_NULL)
357 {
358 /* Deleted account */
359 LoadStringW(hApplet, IDS_USERPROFILE_ACCOUNT_DELETED, pszNameBuffer, dwNameBufferSize);
360 }
361 else
362 {
363 /* Normal account */
364 wsprintf(pszNameBuffer, L"%s\\%s", szDomainName, szAccountName);
365 }
366 }
367
368 return TRUE;
369 }
370
371
372 static VOID
373 AddUserProfile(
374 _In_ HWND hwndListView,
375 _In_ PWSTR pszProfileSid,
376 _In_ PSID pProfileSid,
377 _In_ BOOL bMyProfile,
378 _In_ HKEY hProfileKey)
379 {
380 WCHAR szTempProfilePath[MAX_PATH], szProfilePath[MAX_PATH];
381 WCHAR szNameBuffer[256];
382 PPROFILEDATA pProfileData = NULL;
383 DWORD dwProfileData, dwSize, dwType, dwState = 0;
384 DWORD dwProfilePathLength;
385 PWSTR ptr;
386 INT nId, iItem;
387 LV_ITEM lvi;
388 WIN32_FIND_DATA FindData;
389 HANDLE hFile;
390 SYSTEMTIME SystemTime;
391 DWORD dwError;
392
393 /* Get the profile path */
394 dwSize = MAX_PATH * sizeof(WCHAR);
395 dwError = RegQueryValueExW(hProfileKey,
396 L"ProfileImagePath",
397 NULL,
398 &dwType,
399 (LPBYTE)szTempProfilePath,
400 &dwSize);
401 if (dwError != ERROR_SUCCESS)
402 return;
403
404 /* Expand it */
405 ExpandEnvironmentStringsW(szTempProfilePath,
406 szProfilePath,
407 MAX_PATH);
408
409 /* Check if the profile path exists */
410 hFile = FindFirstFileW(szProfilePath, &FindData);
411 if (hFile == INVALID_HANDLE_VALUE)
412 return;
413
414 FindClose(hFile);
415
416 /* Get the length of the profile path */
417 dwProfilePathLength = wcslen(szProfilePath);
418
419 /* Check for the ntuser.dat file */
420 wcscat(szProfilePath, L"\\ntuser.dat");
421 hFile = FindFirstFileW(szProfilePath, &FindData);
422 if (hFile == INVALID_HANDLE_VALUE)
423 return;
424
425 FindClose(hFile);
426 szProfilePath[dwProfilePathLength] = UNICODE_NULL;
427
428 /* Get the profile name */
429 if (!GetProfileName(pProfileSid, ARRAYSIZE(szNameBuffer), szNameBuffer))
430 return;
431
432 /* Get the profile state value */
433 dwSize = sizeof(dwState);
434 if (RegQueryValueExW(hProfileKey,
435 L"State",
436 NULL,
437 &dwType,
438 (LPBYTE)&dwState,
439 &dwSize) != ERROR_SUCCESS)
440 {
441 dwState = 0;
442 }
443
444 /* Create and fill the profile data entry */
445 dwProfileData = sizeof(PROFILEDATA) +
446 ((wcslen(szNameBuffer) + 1) * sizeof(WCHAR));
447 pProfileData = HeapAlloc(GetProcessHeap(),
448 HEAP_ZERO_MEMORY,
449 dwProfileData);
450 if (pProfileData == NULL)
451 return;
452
453 pProfileData->bMyProfile = bMyProfile;
454 pProfileData->dwState = dwState;
455
456 ptr = (PWSTR)((ULONG_PTR)pProfileData + sizeof(PROFILEDATA));
457 pProfileData->pszFullName = ptr;
458
459 wcscpy(pProfileData->pszFullName, szNameBuffer);
460
461 /* Add the profile and set its name */
462 memset(&lvi, 0x00, sizeof(lvi));
463 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
464 lvi.pszText = pProfileData->pszFullName;
465 lvi.state = 0;
466 lvi.lParam = (LPARAM)pProfileData;
467 iItem = ListView_InsertItem(hwndListView, &lvi);
468
469 /* FIXME: Set the profile size */
470
471 /* Set the profile type */
472 if (dwState & 0x0001) // PROFILE_MANDATORY
473 nId = IDS_USERPROFILE_MANDATORY;
474 else if (dwState & 0x0010) // PROFILE_UPDATE_CENTRAL
475 nId = IDS_USERPROFILE_ROAMING;
476 else
477 nId = IDS_USERPROFILE_LOCAL;
478
479 LoadStringW(hApplet, nId, szNameBuffer, ARRAYSIZE(szNameBuffer));
480
481 ListView_SetItemText(hwndListView, iItem, 2, szNameBuffer);
482
483 /* FIXME: Set the profile status */
484
485 /* Set the profile modified time */
486 FileTimeToSystemTime(&FindData.ftLastWriteTime,
487 &SystemTime);
488
489 GetDateFormatW(LOCALE_USER_DEFAULT,
490 DATE_SHORTDATE,
491 &SystemTime,
492 NULL,
493 szNameBuffer,
494 ARRAYSIZE(szNameBuffer));
495
496 ListView_SetItemText(hwndListView, iItem, 4, szNameBuffer);
497 }
498
499
500 static VOID
501 UpdateButtonState(
502 _In_ HWND hwndDlg,
503 _In_ HWND hwndListView)
504 {
505 LVITEM Item;
506 INT iSelected;
507 BOOL bMyProfile;
508
509 iSelected = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED);
510 if (iSelected != -1)
511 {
512 Item.mask = LVIF_PARAM;
513 Item.iItem = iSelected;
514 Item.iSubItem = 0;
515 if (ListView_GetItem(hwndListView, &Item))
516 {
517 if (Item.lParam != 0)
518 {
519 bMyProfile = ((PPROFILEDATA)Item.lParam)->bMyProfile;
520 if (!bMyProfile)
521 {
522 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), TRUE);
523 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), TRUE);
524 }
525 }
526 }
527 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), TRUE);
528 }
529 else
530 {
531 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), FALSE);
532 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), FALSE);
533 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), FALSE);
534 }
535 }
536
537
538 static VOID
539 AddUserProfiles(
540 _In_ HWND hwndDlg,
541 _In_ HWND hwndListView,
542 _In_ BOOL bAdmin)
543 {
544 HKEY hKeyUserProfiles = INVALID_HANDLE_VALUE;
545 HKEY hProfileKey;
546 DWORD dwIndex;
547 WCHAR szProfileSid[64];
548 DWORD dwSidLength;
549 FILETIME ftLastWrite;
550 DWORD dwSize;
551 HANDLE hToken = NULL;
552 PTOKEN_USER pTokenUser = NULL;
553 PSID pProfileSid;
554 PWSTR pszProfileSid;
555
556 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
557 return;
558
559 GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
560 if (dwSize == 0)
561 goto done;
562
563 pTokenUser = HeapAlloc(GetProcessHeap(), 0, dwSize);
564 if (pTokenUser == NULL)
565 goto done;
566
567 if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
568 goto done;
569
570 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
571 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
572 0,
573 KEY_READ,
574 &hKeyUserProfiles))
575 goto done;
576
577 if (bAdmin)
578 {
579 for (dwIndex = 0; ; dwIndex++)
580 {
581 dwSidLength = ARRAYSIZE(szProfileSid);
582 if (RegEnumKeyExW(hKeyUserProfiles,
583 dwIndex,
584 szProfileSid,
585 &dwSidLength,
586 NULL,
587 NULL,
588 NULL,
589 &ftLastWrite))
590 break;
591
592 if (RegOpenKeyExW(hKeyUserProfiles,
593 szProfileSid,
594 0,
595 KEY_READ,
596 &hProfileKey) == ERROR_SUCCESS)
597 {
598 if (ConvertStringSidToSid(szProfileSid, &pProfileSid))
599 {
600 AddUserProfile(hwndListView,
601 pszProfileSid,
602 pProfileSid,
603 EqualSid(pProfileSid, pTokenUser->User.Sid),
604 hProfileKey);
605 LocalFree(pProfileSid);
606 }
607
608 RegCloseKey(hProfileKey);
609 }
610 }
611 }
612 else
613 {
614 if (ConvertSidToStringSidW(pTokenUser->User.Sid, &pszProfileSid))
615 {
616 if (RegOpenKeyExW(hKeyUserProfiles,
617 pszProfileSid,
618 0,
619 KEY_READ,
620 &hProfileKey) == ERROR_SUCCESS)
621 {
622 AddUserProfile(hwndListView,
623 pszProfileSid,
624 pTokenUser->User.Sid,
625 TRUE,
626 hProfileKey);
627 RegCloseKey(hProfileKey);
628 }
629
630 LocalFree(pszProfileSid);
631 }
632 }
633
634 if (ListView_GetItemCount(hwndListView) != 0)
635 ListView_SetItemState(hwndListView, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
636
637 UpdateButtonState(hwndDlg, hwndListView);
638
639 done:
640 if (hKeyUserProfiles != INVALID_HANDLE_VALUE)
641 RegCloseKey(hKeyUserProfiles);
642
643 if (pTokenUser != NULL)
644 HeapFree(GetProcessHeap(), 0, pTokenUser);
645
646 if (hToken != NULL)
647 CloseHandle(hToken);
648 }
649
650
651 static VOID
652 OnInitUserProfileDialog(HWND hwndDlg)
653 {
654 BOOL bAdmin;
655
656 bAdmin = IsUserAdmin();
657
658 /* Initialize the list view control */
659 SetListViewColumns(GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST));
660
661 /* Hide the delete and copy buttons for non-admins */
662 ShowWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), bAdmin ? SW_SHOW : SW_HIDE);
663 ShowWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), bAdmin ? SW_SHOW : SW_HIDE);
664
665 /* Add the profiles to the list view */
666 AddUserProfiles(hwndDlg, GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST), bAdmin);
667 }
668
669
670 static
671 VOID
672 OnDestroy(
673 _In_ HWND hwndDlg)
674 {
675 HWND hwndList;
676 INT nItems, i;
677 LVITEM Item;
678
679 hwndList = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST);
680
681 nItems = ListView_GetItemCount(hwndList);
682 for (i = 0; i < nItems; i++)
683 {
684 Item.iItem = i;
685 Item.iSubItem = 0;
686 if (ListView_GetItem(hwndList, &Item))
687 {
688 if (Item.lParam != 0)
689 HeapFree(GetProcessHeap(), 0, (PVOID)Item.lParam);
690 }
691 }
692 }
693
694
695 static
696 VOID
697 OnNotify(
698 _In_ HWND hwndDlg,
699 _In_ NMHDR *nmhdr)
700 {
701 if (nmhdr->idFrom == IDC_USERACCOUNT_LINK && nmhdr->code == NM_CLICK)
702 {
703 ShellExecuteW(hwndDlg, NULL, L"usrmgr.cpl", NULL, NULL, 0);
704 }
705 else if (nmhdr->idFrom == IDC_USERPROFILE_LIST && nmhdr->code == LVN_ITEMCHANGED)
706 {
707 UpdateButtonState(hwndDlg, nmhdr->hwndFrom);
708 }
709 }
710
711
712 /* Property page dialog callback */
713 INT_PTR CALLBACK
714 UserProfileDlgProc(HWND hwndDlg,
715 UINT uMsg,
716 WPARAM wParam,
717 LPARAM lParam)
718 {
719 switch (uMsg)
720 {
721 case WM_INITDIALOG:
722 OnInitUserProfileDialog(hwndDlg);
723 return TRUE;
724
725 case WM_DESTROY:
726 OnDestroy(hwndDlg);
727 break;
728
729 case WM_COMMAND:
730 switch (LOWORD(wParam))
731 {
732 case IDOK:
733 case IDCANCEL:
734 EndDialog(hwndDlg,
735 LOWORD(wParam));
736 return TRUE;
737
738 case IDC_USERPROFILE_CHANGE:
739 ChangeUserProfileType(hwndDlg);
740 break;
741
742 case IDC_USERPROFILE_DELETE:
743 DeleteUserProfile(hwndDlg);
744 break;
745
746 case IDC_USERPROFILE_COPY:
747 CopyUserProfile(hwndDlg);
748 break;
749 }
750 break;
751
752 case WM_NOTIFY:
753 OnNotify(hwndDlg, (NMHDR *)lParam);
754 break;
755 }
756
757 return FALSE;
758 }