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>
16 typedef struct _PROFILEDATA
21 } PROFILEDATA
, *PPROFILEDATA
;
28 PPROFILEDATA pProfileData
)
30 PWSTR pszRawBuffer
= NULL
, pszCookedBuffer
= NULL
;
33 nLength
= LoadStringW(hApplet
, IDS_USERPROFILE_TYPE_TEXT
, (PWSTR
)&pszRawBuffer
, 0);
38 pszRawBuffer
= HeapAlloc(GetProcessHeap(), 0, (nLength
+ 1) * sizeof(WCHAR
));
39 if (pszRawBuffer
== NULL
)
42 LoadStringW(hApplet
, IDS_USERPROFILE_TYPE_TEXT
, pszRawBuffer
, nLength
+ 1);
44 pszCookedBuffer
= HeapAlloc(GetProcessHeap(), 0, (nLength
+ wcslen(pProfileData
->pszFullName
) + 1) * sizeof(WCHAR
));
45 if (pszCookedBuffer
== NULL
)
48 swprintf(pszCookedBuffer
, pszRawBuffer
, pProfileData
->pszFullName
);
50 /* Set the full text */
51 SetDlgItemText(hwndDlg
, IDC_USERPROFILE_TYPE_TEXT
, pszCookedBuffer
);
53 /* FIXME: Right now, we support local user profiles only! */
54 EnableWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_TYPE_ROAMING
), FALSE
);
55 Button_SetCheck(GetDlgItem(hwndDlg
, IDC_USERPROFILE_TYPE_LOCAL
), BST_CHECKED
);
56 EnableWindow(GetDlgItem(hwndDlg
, IDOK
), FALSE
);
59 if (pszCookedBuffer
!= NULL
)
60 HeapFree(GetProcessHeap(), 0, pszCookedBuffer
);
62 if (pszRawBuffer
!= NULL
)
63 HeapFree(GetProcessHeap(), 0, pszRawBuffer
);
72 UserProfileTypeDlgProc(
81 OnProfileTypeInit(hwndDlg
, (PPROFILEDATA
)lParam
);
88 switch (LOWORD(wParam
))
105 ChangeUserProfileType(
112 DPRINT("ChangeUserProfileType(%p)\n", hwndDlg
);
114 hwndListView
= GetDlgItem(hwndDlg
, IDC_USERPROFILE_LIST
);
115 if (hwndListView
== NULL
)
118 iSelected
= ListView_GetNextItem(hwndListView
, -1, LVNI_SELECTED
);
122 ZeroMemory(&Item
, sizeof(LVITEM
));
123 Item
.mask
= LVIF_PARAM
;
124 Item
.iItem
= iSelected
;
126 if (!ListView_GetItem(hwndListView
, &Item
))
129 if (Item
.lParam
== 0)
132 if (DialogBoxParam(hApplet
,
133 MAKEINTRESOURCE(IDD_USERPROFILE_TYPE
),
135 UserProfileTypeDlgProc
,
136 (LPARAM
)Item
.lParam
) == IDOK
)
138 /* FIXME: Update the profile list view */
151 WCHAR szTitle
[64], szRawText
[128], szCookedText
[256];
155 PPROFILEDATA pProfileData
;
157 DPRINT("DeleteUserProfile()\n");
159 hwndListView
= GetDlgItem(hwndDlg
, IDC_USERPROFILE_LIST
);
160 if (hwndListView
== NULL
)
163 iSelected
= ListView_GetNextItem(hwndListView
, -1, LVNI_SELECTED
);
167 ZeroMemory(&Item
, sizeof(LVITEM
));
168 Item
.mask
= LVIF_PARAM
;
169 Item
.iItem
= iSelected
;
171 if (!ListView_GetItem(hwndListView
, &Item
))
174 if (Item
.lParam
== 0)
177 pProfileData
= (PPROFILEDATA
)Item
.lParam
;
178 if (pProfileData
->bMyProfile
)
181 LoadStringW(hApplet
, IDS_USERPROFILE_CONFIRM_DELETE_TITLE
, szTitle
, ARRAYSIZE(szTitle
));
182 LoadStringW(hApplet
, IDS_USERPROFILE_CONFIRM_DELETE
, szRawText
, ARRAYSIZE(szRawText
));
183 swprintf(szCookedText
, szRawText
, pProfileData
->pszFullName
);
185 if (MessageBoxW(hwndDlg
,
188 MB_ICONQUESTION
| MB_YESNO
) == IDYES
)
190 /* FIXME: Delete the profile here! */
201 CopyUserProfileDlgProc(
216 switch (LOWORD(wParam
))
240 DPRINT("CopyUserProfile()\n");
242 hwndListView
= GetDlgItem(hwndDlg
, IDC_USERPROFILE_LIST
);
243 if (hwndListView
== NULL
)
246 iSelected
= ListView_GetNextItem(hwndListView
, -1, LVNI_SELECTED
);
250 ZeroMemory(&Item
, sizeof(LVITEM
));
251 Item
.mask
= LVIF_PARAM
;
252 Item
.iItem
= iSelected
;
254 if (!ListView_GetItem(hwndListView
, &Item
))
257 if (Item
.lParam
== 0)
260 if (DialogBoxParam(hApplet
,
261 MAKEINTRESOURCE(IDD_USERPROFILE_COPY
),
263 CopyUserProfileDlgProc
,
264 (LPARAM
)Item
.lParam
) == IDOK
)
266 /* FIXME: Update the profile list view */
276 _In_ HWND hwndListView
)
282 GetClientRect(hwndListView
, &rect
);
284 SendMessage(hwndListView
, LVM_SETEXTENDEDLISTVIEWSTYLE
, 0, LVS_EX_FULLROWSELECT
);
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);
291 LoadString(hApplet
, IDS_USERPROFILE_NAME
, szStr
, ARRAYSIZE(szStr
));
292 column
.pszText
= szStr
;
293 (void)ListView_InsertColumn(hwndListView
, 0, &column
);
295 column
.fmt
= LVCFMT_RIGHT
;
296 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.15);
298 LoadString(hApplet
, IDS_USERPROFILE_SIZE
, szStr
, ARRAYSIZE(szStr
));
299 column
.pszText
= szStr
;
300 (void)ListView_InsertColumn(hwndListView
, 1, &column
);
302 column
.fmt
= LVCFMT_LEFT
;
303 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.15);
305 LoadString(hApplet
, IDS_USERPROFILE_TYPE
, szStr
, ARRAYSIZE(szStr
));
306 column
.pszText
= szStr
;
307 (void)ListView_InsertColumn(hwndListView
, 2, &column
);
309 column
.fmt
= LVCFMT_LEFT
;
310 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.15);
312 LoadString(hApplet
, IDS_USERPROFILE_STATUS
, szStr
, ARRAYSIZE(szStr
));
313 column
.pszText
= szStr
;
314 (void)ListView_InsertColumn(hwndListView
, 3, &column
);
316 column
.fmt
= LVCFMT_LEFT
;
317 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.15) - GetSystemMetrics(SM_CYHSCROLL
);
319 LoadString(hApplet
, IDS_USERPROFILE_MODIFIED
, szStr
, ARRAYSIZE(szStr
));
320 column
.pszText
= szStr
;
321 (void)ListView_InsertColumn(hwndListView
, 4, &column
);
327 _In_ HWND hwndListView
,
328 _In_ PSID pProfileSid
,
330 _In_ HKEY hProfileKey
)
332 PPROFILEDATA pProfileData
= NULL
;
333 WCHAR szAccountName
[128], szDomainName
[128];
334 WCHAR szNameBuffer
[256];
336 DWORD dwAccountNameSize
, dwDomainNameSize
;
337 DWORD dwProfileData
, dwSize
, dwType
, dwState
= 0;
342 dwAccountNameSize
= ARRAYSIZE(szAccountName
);
343 dwDomainNameSize
= ARRAYSIZE(szDomainName
);
344 if (!LookupAccountSidW(NULL
,
352 /* Unknown account */
353 LoadStringW(hApplet
, IDS_USERPROFILE_ACCOUNT_UNKNOWN
, szNameBuffer
, ARRAYSIZE(szNameBuffer
));
357 /* Show only the user accounts */
358 if (Use
!= SidTypeUser
)
361 if (szAccountName
[0] == UNICODE_NULL
)
363 /* Deleted account */
364 LoadStringW(hApplet
, IDS_USERPROFILE_ACCOUNT_DELETED
, szNameBuffer
, ARRAYSIZE(szNameBuffer
));
369 wsprintf(szNameBuffer
, L
"%s\\%s", szDomainName
, szAccountName
);
373 /* Get the profile state value */
374 dwSize
= sizeof(dwState
);
375 if (RegQueryValueExW(hProfileKey
,
380 &dwSize
) != ERROR_SUCCESS
)
385 /* Create and fill the profile data entry */
386 dwProfileData
= sizeof(PROFILEDATA
) +
387 ((wcslen(szNameBuffer
) + 1) * sizeof(WCHAR
));
388 pProfileData
= HeapAlloc(GetProcessHeap(),
391 if (pProfileData
== NULL
)
394 pProfileData
->bMyProfile
= EqualSid(pMySid
, pProfileSid
);
395 pProfileData
->dwState
= dwState
;
397 ptr
= (PWSTR
)((ULONG_PTR
)pProfileData
+ sizeof(PROFILEDATA
));
398 pProfileData
->pszFullName
= ptr
;
400 wcscpy(pProfileData
->pszFullName
, szNameBuffer
);
402 /* Add the profile and set its name */
403 memset(&lvi
, 0x00, sizeof(lvi
));
404 lvi
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_PARAM
;
405 lvi
.pszText
= pProfileData
->pszFullName
;
407 lvi
.lParam
= (LPARAM
)pProfileData
;
408 iItem
= ListView_InsertItem(hwndListView
, &lvi
);
410 /* Set the profile type */
411 if (dwState
& 0x0001) // PROFILE_MANDATORY
412 nId
= IDS_USERPROFILE_MANDATORY
;
413 else if (dwState
& 0x0010) // PROFILE_UPDATE_CENTRAL
414 nId
= IDS_USERPROFILE_ROAMING
;
416 nId
= IDS_USERPROFILE_LOCAL
;
418 LoadStringW(hApplet
, nId
, szAccountName
, ARRAYSIZE(szAccountName
));
420 ListView_SetItemText(hwndListView
, iItem
, 2, szAccountName
);
427 _In_ HWND hwndListView
)
433 iSelected
= ListView_GetNextItem(hwndListView
, -1, LVNI_SELECTED
);
436 Item
.mask
= LVIF_PARAM
;
437 Item
.iItem
= iSelected
;
439 if (ListView_GetItem(hwndListView
, &Item
))
441 if (Item
.lParam
!= 0)
443 bMyProfile
= ((PPROFILEDATA
)Item
.lParam
)->bMyProfile
;
446 EnableWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_DELETE
), TRUE
);
447 EnableWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_COPY
), TRUE
);
451 EnableWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_CHANGE
), TRUE
);
455 EnableWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_CHANGE
), FALSE
);
456 EnableWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_DELETE
), FALSE
);
457 EnableWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_COPY
), FALSE
);
465 _In_ HWND hwndListView
,
468 HKEY hKeyUserProfiles
= INVALID_HANDLE_VALUE
;
471 WCHAR szProfileSid
[64];
473 FILETIME ftLastWrite
;
475 HANDLE hToken
= NULL
;
476 PTOKEN_USER pTokenUser
= NULL
;
480 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
483 GetTokenInformation(hToken
, TokenUser
, NULL
, 0, &dwSize
);
487 pTokenUser
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
488 if (pTokenUser
== NULL
)
491 if (!GetTokenInformation(hToken
, TokenUser
, pTokenUser
, dwSize
, &dwSize
))
494 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
495 L
"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
503 for (dwIndex
= 0; ; dwIndex
++)
505 dwSidLength
= ARRAYSIZE(szProfileSid
);
506 if (RegEnumKeyExW(hKeyUserProfiles
,
516 if (RegOpenKeyExW(hKeyUserProfiles
,
520 &hProfileKey
) == ERROR_SUCCESS
)
522 if (ConvertStringSidToSid(szProfileSid
, &pProfileSid
))
524 AddUserProfile(hwndListView
, pProfileSid
, pTokenUser
->User
.Sid
, hProfileKey
);
525 LocalFree(pProfileSid
);
528 RegCloseKey(hProfileKey
);
534 if (ConvertSidToStringSidW(pTokenUser
->User
.Sid
, &pszProfileSid
))
536 if (RegOpenKeyExW(hKeyUserProfiles
,
540 &hProfileKey
) == ERROR_SUCCESS
)
542 AddUserProfile(hwndListView
, pTokenUser
->User
.Sid
, pTokenUser
->User
.Sid
, hProfileKey
);
543 RegCloseKey(hProfileKey
);
546 LocalFree(pszProfileSid
);
550 if (ListView_GetItemCount(hwndListView
) != 0)
551 ListView_SetItemState(hwndListView
, 0, LVIS_SELECTED
| LVIS_FOCUSED
, LVIS_SELECTED
| LVIS_FOCUSED
);
553 UpdateButtonState(hwndDlg
, hwndListView
);
556 if (hKeyUserProfiles
!= INVALID_HANDLE_VALUE
)
557 RegCloseKey(hKeyUserProfiles
);
559 if (pTokenUser
!= NULL
)
560 HeapFree(GetProcessHeap(), 0, pTokenUser
);
568 OnInitUserProfileDialog(HWND hwndDlg
)
572 bAdmin
= IsUserAdmin();
574 /* Initialize the list view control */
575 SetListViewColumns(GetDlgItem(hwndDlg
, IDC_USERPROFILE_LIST
));
577 /* Hide the delete and copy buttons for non-admins */
578 ShowWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_DELETE
), bAdmin
? SW_SHOW
: SW_HIDE
);
579 ShowWindow(GetDlgItem(hwndDlg
, IDC_USERPROFILE_COPY
), bAdmin
? SW_SHOW
: SW_HIDE
);
581 /* Add the profiles to the list view */
582 AddUserProfiles(hwndDlg
, GetDlgItem(hwndDlg
, IDC_USERPROFILE_LIST
), bAdmin
);
595 hwndList
= GetDlgItem(hwndDlg
, IDC_USERPROFILE_LIST
);
597 nItems
= ListView_GetItemCount(hwndList
);
598 for (i
= 0; i
< nItems
; i
++)
602 if (ListView_GetItem(hwndList
, &Item
))
604 if (Item
.lParam
!= 0)
605 HeapFree(GetProcessHeap(), 0, (PVOID
)Item
.lParam
);
617 if (nmhdr
->idFrom
== IDC_USERACCOUNT_LINK
&& nmhdr
->code
== NM_CLICK
)
619 ShellExecuteW(hwndDlg
, NULL
, L
"usrmgr.cpl", NULL
, NULL
, 0);
621 else if (nmhdr
->idFrom
== IDC_USERPROFILE_LIST
&& nmhdr
->code
== LVN_ITEMCHANGED
)
623 UpdateButtonState(hwndDlg
, nmhdr
->hwndFrom
);
628 /* Property page dialog callback */
630 UserProfileDlgProc(HWND hwndDlg
,
638 OnInitUserProfileDialog(hwndDlg
);
646 switch (LOWORD(wParam
))
654 case IDC_USERPROFILE_CHANGE
:
655 ChangeUserProfileType(hwndDlg
);
658 case IDC_USERPROFILE_DELETE
:
659 DeleteUserProfile(hwndDlg
);
662 case IDC_USERPROFILE_COPY
:
663 CopyUserProfile(hwndDlg
);
669 OnNotify(hwndDlg
, (NMHDR
*)lParam
);