xref: /reactos/dll/cpl/sysdm/userprofile.c (revision cc439606)
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 
14 
15 typedef struct _PROFILEDATA
16 {
17     BOOL bMyProfile;
18     PWSTR pszFullName;
19 } PROFILEDATA, *PPROFILEDATA;
20 
21 
22 static VOID
23 SetListViewColumns(HWND hwndListView)
24 {
25     LV_COLUMN column;
26     RECT rect;
27     TCHAR szStr[32];
28 
29     GetClientRect(hwndListView, &rect);
30 
31     SendMessage(hwndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
32 
33     memset(&column, 0x00, sizeof(column));
34     column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
35     column.fmt = LVCFMT_LEFT;
36     column.cx = (INT)((rect.right - rect.left) * 0.40);
37     column.iSubItem = 0;
38     LoadString(hApplet, IDS_USERPROFILE_NAME, szStr, ARRAYSIZE(szStr));
39     column.pszText = szStr;
40     (void)ListView_InsertColumn(hwndListView, 0, &column);
41 
42     column.fmt = LVCFMT_RIGHT;
43     column.cx = (INT)((rect.right - rect.left) * 0.15);
44     column.iSubItem = 1;
45     LoadString(hApplet, IDS_USERPROFILE_SIZE, szStr, ARRAYSIZE(szStr));
46     column.pszText = szStr;
47     (void)ListView_InsertColumn(hwndListView, 1, &column);
48 
49     column.fmt = LVCFMT_LEFT;
50     column.cx = (INT)((rect.right - rect.left) * 0.15);
51     column.iSubItem = 2;
52     LoadString(hApplet, IDS_USERPROFILE_TYPE, szStr, ARRAYSIZE(szStr));
53     column.pszText = szStr;
54     (void)ListView_InsertColumn(hwndListView, 2, &column);
55 
56     column.fmt = LVCFMT_LEFT;
57     column.cx = (INT)((rect.right - rect.left) * 0.15);
58     column.iSubItem = 3;
59     LoadString(hApplet, IDS_USERPROFILE_STATUS, szStr, ARRAYSIZE(szStr));
60     column.pszText = szStr;
61     (void)ListView_InsertColumn(hwndListView, 3, &column);
62 
63     column.fmt = LVCFMT_LEFT;
64     column.cx = (INT)((rect.right - rect.left) * 0.15) - GetSystemMetrics(SM_CYHSCROLL);
65     column.iSubItem = 4;
66     LoadString(hApplet, IDS_USERPROFILE_MODIFIED, szStr, ARRAYSIZE(szStr));
67     column.pszText = szStr;
68     (void)ListView_InsertColumn(hwndListView, 4, &column);
69 }
70 
71 
72 static VOID
73 AddUserProfile(
74     _In_ HWND hwndListView,
75     _In_ LPTSTR lpProfileSid,
76     _In_ PSID pMySid)
77 {
78     PPROFILEDATA pProfileData = NULL;
79     PWSTR pszAccountName = NULL;
80     PWSTR pszDomainName = NULL;
81     SID_NAME_USE Use;
82     DWORD dwAccountNameSize, dwDomainNameSize;
83     DWORD dwProfileData;
84     PWSTR ptr;
85     PSID pSid = NULL;
86     LV_ITEM lvi;
87 
88     if (!ConvertStringSidToSid(lpProfileSid,
89                                &pSid))
90         return;
91 
92     dwAccountNameSize = 0;
93     dwDomainNameSize = 0;
94     LookupAccountSidW(NULL,
95                       pSid,
96                       NULL,
97                       &dwAccountNameSize,
98                       NULL,
99                       &dwDomainNameSize,
100                       &Use);
101 
102     pszDomainName = HeapAlloc(GetProcessHeap(),
103                               0,
104                               dwDomainNameSize * sizeof(WCHAR));
105     if (pszDomainName == NULL)
106         goto done;
107 
108     pszAccountName = HeapAlloc(GetProcessHeap(),
109                                0,
110                                dwAccountNameSize * sizeof(WCHAR));
111     if (pszAccountName == NULL)
112         goto done;
113 
114     if (!LookupAccountSidW(NULL,
115                            pSid,
116                            pszAccountName,
117                            &dwAccountNameSize,
118                            pszDomainName,
119                            &dwDomainNameSize,
120                            &Use))
121         goto done;
122 
123     /* Show only the user accounts */
124     if (Use != SidTypeUser)
125         goto done;
126 
127     dwProfileData = sizeof(PROFILEDATA) +
128                     ((wcslen(pszDomainName) + wcslen(pszAccountName) + 2) * sizeof(WCHAR));
129     pProfileData = HeapAlloc(GetProcessHeap(),
130                              0,
131                              dwProfileData);
132     if (pProfileData == NULL)
133         goto done;
134 
135     pProfileData->bMyProfile = EqualSid(pMySid, pSid);
136 
137     ptr = (PWSTR)((ULONG_PTR)pProfileData + sizeof(PROFILEDATA));
138     pProfileData->pszFullName = ptr;
139 
140     wsprintf(pProfileData->pszFullName, L"%s\\%s", pszDomainName, pszAccountName);
141 
142     memset(&lvi, 0x00, sizeof(lvi));
143     lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
144     lvi.pszText = pProfileData->pszFullName;
145     lvi.state = 0;
146     lvi.lParam = (LPARAM)pProfileData;
147     ListView_InsertItem(hwndListView, &lvi);
148 
149 done:
150     if (pszDomainName != NULL)
151         HeapFree(GetProcessHeap(), 0, pszDomainName);
152 
153     if (pszAccountName != NULL)
154         HeapFree(GetProcessHeap(), 0, pszAccountName);
155 
156     if (pSid != NULL)
157         LocalFree(pSid);
158 }
159 
160 
161 static VOID
162 AddUserProfiles(HWND hwndListView)
163 {
164     HKEY hKeyUserProfiles = INVALID_HANDLE_VALUE;
165     DWORD dwIndex;
166     WCHAR szProfileSid[64];
167     DWORD dwSidLength;
168     FILETIME ftLastWrite;
169     DWORD dwSize;
170     HANDLE hToken = NULL;
171     PTOKEN_USER pTokenUser = NULL;
172 
173     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
174         return;
175 
176     GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
177     if (dwSize == 0)
178         goto done;
179 
180     pTokenUser = HeapAlloc(GetProcessHeap(), 0, dwSize);
181     if (pTokenUser == NULL)
182         goto done;
183 
184     if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
185         goto done;
186 
187     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
188                       L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
189                       0,
190                       KEY_READ,
191                       &hKeyUserProfiles))
192         goto done;
193 
194     for (dwIndex = 0; ; dwIndex++)
195     {
196         dwSidLength = ARRAYSIZE(szProfileSid);
197         if (RegEnumKeyExW(hKeyUserProfiles,
198                           dwIndex,
199                           szProfileSid,
200                           &dwSidLength,
201                           NULL,
202                           NULL,
203                           NULL,
204                           &ftLastWrite))
205             break;
206 
207         AddUserProfile(hwndListView, szProfileSid, pTokenUser->User.Sid);
208     }
209 
210     if (ListView_GetItemCount(hwndListView) != 0)
211         ListView_SetItemState(hwndListView, 0, LVIS_SELECTED, LVIS_SELECTED);
212 
213 done:
214     if (hKeyUserProfiles != INVALID_HANDLE_VALUE)
215         RegCloseKey(hKeyUserProfiles);
216 
217     if (pTokenUser != NULL)
218         HeapFree(GetProcessHeap(), 0, pTokenUser);
219 
220     if (hToken != NULL)
221         CloseHandle(hToken);
222 }
223 
224 
225 static VOID
226 OnInitUserProfileDialog(HWND hwndDlg)
227 {
228     /* Initialize the list view control */
229     SetListViewColumns(GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST));
230 
231     AddUserProfiles(GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST));
232 
233     /* Disable the "Delete" and "Copy To" buttons if the user is not an admin */
234     if (!IsUserAnAdmin())
235     {
236          EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), FALSE);
237          EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), FALSE);
238     }
239 }
240 
241 
242 static
243 VOID
244 OnDestroy(
245     _In_ HWND hwndDlg)
246 {
247     HWND hwndList;
248     INT nItems, i;
249     LVITEM Item;
250 
251     hwndList = GetDlgItem(hwndDlg, IDC_USERPROFILE_LIST);
252 
253     nItems = ListView_GetItemCount(hwndList);
254     for (i = 0; i < nItems; i++)
255     {
256         Item.iItem = i;
257         Item.iSubItem = 0;
258         if (ListView_GetItem(hwndList, &Item))
259         {
260             if (Item.lParam != 0)
261                 HeapFree(GetProcessHeap(), 0, (PVOID)Item.lParam);
262         }
263     }
264 }
265 
266 
267 static
268 VOID
269 OnNotify(
270     _In_ HWND hwndDlg,
271     _In_ NMHDR *nmhdr)
272 {
273     if (nmhdr->idFrom == IDC_USERACCOUNT_LINK && nmhdr->code == NM_CLICK)
274     {
275         ShellExecuteW(hwndDlg, NULL, L"usrmgr.cpl", NULL, NULL, 0);
276     }
277     else if (nmhdr->idFrom == IDC_USERPROFILE_LIST && nmhdr->code == LVN_ITEMCHANGED)
278     {
279         if (ListView_GetSelectedCount(nmhdr->hwndFrom) == 0)
280         {
281             EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), FALSE);
282             EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), FALSE);
283             EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), FALSE);
284         }
285         else
286         {
287             LVITEM Item;
288             INT iSelected;
289             BOOL bMyProfile = FALSE;
290 
291             iSelected = ListView_GetNextItem(nmhdr->hwndFrom, -1, LVNI_SELECTED);
292             if (iSelected != -1)
293             {
294                 Item.iItem = iSelected;
295                 Item.iSubItem = 0;
296                 if (ListView_GetItem(nmhdr->hwndFrom, &Item))
297                 {
298                     if (Item.lParam != 0)
299                     {
300                         bMyProfile = ((PPROFILEDATA)Item.lParam)->bMyProfile;
301                     }
302                 }
303             }
304 
305             EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_CHANGE), TRUE);
306             if (IsUserAnAdmin() && !bMyProfile)
307             {
308                 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_DELETE), TRUE);
309                 EnableWindow(GetDlgItem(hwndDlg, IDC_USERPROFILE_COPY), TRUE);
310             }
311         }
312     }
313 }
314 
315 
316 /* Property page dialog callback */
317 INT_PTR CALLBACK
318 UserProfileDlgProc(HWND hwndDlg,
319                    UINT uMsg,
320                    WPARAM wParam,
321                    LPARAM lParam)
322 {
323     switch (uMsg)
324     {
325         case WM_INITDIALOG:
326             OnInitUserProfileDialog(hwndDlg);
327             break;
328 
329         case WM_DESTROY:
330             OnDestroy(hwndDlg);
331             break;
332 
333         case WM_COMMAND:
334             switch (LOWORD(wParam))
335             {
336                 case IDOK:
337                 case IDCANCEL:
338                     EndDialog(hwndDlg,
339                               LOWORD(wParam));
340                     return TRUE;
341 
342                 case IDC_USERPROFILE_DELETE:
343                     break;
344             }
345             break;
346 
347         case WM_NOTIFY:
348             OnNotify(hwndDlg, (NMHDR *)lParam);
349             break;
350     }
351 
352     return FALSE;
353 }
354