- User properties:
[reactos.git] / reactos / dll / cpl / usrmgr / userprops.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS User Manager Control Panel
4 * FILE: dll/cpl/usrmgr/userprops.c
5 * PURPOSE: User property sheet
6 *
7 * PROGRAMMERS: Eric Kohl
8 */
9
10 #include "usrmgr.h"
11
12 typedef struct _GENERAL_USER_DATA
13 {
14 DWORD dwFlags;
15 DWORD dwPasswordExpired;
16 TCHAR szUserName[1];
17 } GENERAL_USER_DATA, *PGENERAL_USER_DATA;
18
19 #define VALID_GENERAL_FLAGS (UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD | UF_ACCOUNTDISABLE | UF_LOCKOUT)
20
21
22
23 static VOID
24 GetProfileData(HWND hwndDlg, LPTSTR lpUserName)
25 {
26 PUSER_INFO_3 userInfo = NULL;
27 NET_API_STATUS status;
28 BOOL bLocal;
29 TCHAR szDrive[8];
30 INT i;
31 INT nSel;
32
33 status = NetUserGetInfo(NULL, lpUserName, 3, (LPBYTE*)&userInfo);
34 if (status != NERR_Success)
35 return;
36
37 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_PATH, userInfo->usri3_profile);
38 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_SCRIPT, userInfo->usri3_script_path);
39
40
41 bLocal = (userInfo->usri3_home_dir_drive == NULL) ||
42 (_tcslen(userInfo->usri3_home_dir_drive) == 0);
43 CheckRadioButton(hwndDlg, IDC_USER_PROFILE_LOCAL, IDC_USER_PROFILE_REMOTE,
44 bLocal ? IDC_USER_PROFILE_LOCAL : IDC_USER_PROFILE_REMOTE);
45
46 for (i = 0; i < 26; i++)
47 {
48 wsprintf(szDrive, _T("%c:"), (TCHAR)('A' + i));
49 nSel = SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
50 CB_INSERTSTRING, -1, (LPARAM)szDrive);
51 }
52
53 if (bLocal)
54 {
55 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH, userInfo->usri3_home_dir);
56 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), FALSE);
57 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), FALSE);
58 }
59 else
60 {
61 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH, userInfo->usri3_home_dir);
62 nSel = SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
63 CB_FINDSTRINGEXACT, -1, (LPARAM)userInfo->usri3_home_dir_drive);
64 }
65
66 SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
67 CB_SETCURSEL, nSel, 0);
68
69 NetApiBufferFree(userInfo);
70 }
71
72
73 INT_PTR CALLBACK
74 UserProfilePageProc(HWND hwndDlg,
75 UINT uMsg,
76 WPARAM wParam,
77 LPARAM lParam)
78 {
79
80 UNREFERENCED_PARAMETER(lParam);
81 UNREFERENCED_PARAMETER(wParam);
82 UNREFERENCED_PARAMETER(hwndDlg);
83
84 switch (uMsg)
85 {
86 case WM_INITDIALOG:
87 GetProfileData(hwndDlg,
88 (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
89 break;
90
91 case WM_COMMAND:
92 switch (LOWORD(wParam))
93 {
94 case IDC_USER_PROFILE_LOCAL:
95 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH), TRUE);
96 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), FALSE);
97 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), FALSE);
98 break;
99
100 case IDC_USER_PROFILE_REMOTE:
101 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH), FALSE);
102 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), TRUE);
103 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), TRUE);
104 break;
105 }
106 break;
107 }
108
109 return FALSE;
110 }
111
112
113 static VOID
114 GetMembershipData(HWND hwndDlg, LPTSTR lpUserName)
115 {
116 PLOCALGROUP_USERS_INFO_0 usersInfo = NULL;
117 NET_API_STATUS status;
118 DWORD dwRead;
119 DWORD dwTotal;
120 DWORD i;
121 HIMAGELIST hImgList;
122 HICON hIcon;
123 LV_ITEM lvi;
124 HWND hwndLV;
125 LV_COLUMN column;
126 RECT rect;
127
128
129 hwndLV = GetDlgItem(hwndDlg, IDC_USER_MEMBERSHIP_LIST);
130
131 /* Create the image list */
132 hImgList = ImageList_Create(16, 16, ILC_COLOR8 | ILC_MASK, 5, 5);
133 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_GROUP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
134 ImageList_AddIcon(hImgList, hIcon);
135 DestroyIcon(hIcon);
136 (void)ListView_SetImageList(hwndLV, hImgList, LVSIL_SMALL);
137
138 /* Set the list column */
139 GetClientRect(hwndLV, &rect);
140
141 memset(&column, 0x00, sizeof(column));
142 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
143 column.fmt = LVCFMT_LEFT;
144 column.cx = (INT)(rect.right - rect.left);
145 column.iSubItem = 0;
146 (void)ListView_InsertColumn(hwndLV, 0, &column);
147
148
149 status = NetUserGetLocalGroups(NULL, lpUserName, 0, 0,
150 (LPBYTE*)&usersInfo,
151 MAX_PREFERRED_LENGTH,
152 &dwRead,
153 &dwTotal);
154 if (status != NERR_Success)
155 return;
156
157 for (i = 0; i < dwRead; i++)
158 {
159 ZeroMemory(&lvi, sizeof(lvi));
160 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
161 lvi.pszText = usersInfo[i].lgrui0_name;
162 lvi.state = 0;
163 lvi.iImage = 0;
164
165 (void)ListView_InsertItem(hwndLV, &lvi);
166 }
167
168
169 NetApiBufferFree(usersInfo);
170
171 }
172
173
174 INT_PTR CALLBACK
175 UserMembershipPageProc(HWND hwndDlg,
176 UINT uMsg,
177 WPARAM wParam,
178 LPARAM lParam)
179 {
180
181 UNREFERENCED_PARAMETER(lParam);
182 UNREFERENCED_PARAMETER(wParam);
183 UNREFERENCED_PARAMETER(hwndDlg);
184
185 switch (uMsg)
186 {
187 case WM_INITDIALOG:
188 GetMembershipData(hwndDlg,
189 (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
190 break;
191
192 }
193
194 return FALSE;
195 }
196
197
198 static VOID
199 UpdateUserOptions(HWND hwndDlg,
200 PGENERAL_USER_DATA pUserData,
201 BOOL bInit)
202 {
203 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_CANNOT_CHANGE),
204 !pUserData->dwPasswordExpired);
205 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_NEVER_EXPIRES),
206 !pUserData->dwPasswordExpired);
207 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_FORCE_CHANGE),
208 (pUserData->dwFlags & (UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD)) == 0);
209
210 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_LOCKED),
211 (pUserData->dwFlags & UF_LOCKOUT) != 0);
212
213 if (bInit)
214 {
215 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_FORCE_CHANGE,
216 pUserData->dwPasswordExpired ? BST_CHECKED : BST_UNCHECKED);
217
218 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_CANNOT_CHANGE,
219 (pUserData->dwFlags & UF_PASSWD_CANT_CHANGE) ? BST_CHECKED : BST_UNCHECKED);
220
221 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_NEVER_EXPIRES,
222 (pUserData->dwFlags & UF_DONT_EXPIRE_PASSWD) ? BST_CHECKED : BST_UNCHECKED);
223
224 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_DISABLED,
225 (pUserData->dwFlags & UF_ACCOUNTDISABLE) ? BST_CHECKED : BST_UNCHECKED);
226
227 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_LOCKED,
228 (pUserData->dwFlags & UF_LOCKOUT) ? BST_CHECKED : BST_UNCHECKED);
229 }
230 }
231
232
233 static VOID
234 GetGeneralUserData(HWND hwndDlg,
235 PGENERAL_USER_DATA pUserData)
236 {
237 PUSER_INFO_3 pUserInfo = NULL;
238
239 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_NAME, pUserData->szUserName);
240
241 NetUserGetInfo(NULL, pUserData->szUserName, 3, (LPBYTE*)&pUserInfo);
242
243 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_FULL_NAME, pUserInfo->usri3_full_name);
244 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_DESCRIPTION, pUserInfo->usri3_comment);
245
246 pUserData->dwFlags = pUserInfo->usri3_flags;
247 pUserData->dwPasswordExpired = pUserInfo->usri3_password_expired;
248
249 NetApiBufferFree(pUserInfo);
250
251 UpdateUserOptions(hwndDlg, pUserData, TRUE);
252 }
253
254
255 static BOOL
256 SetGeneralUserData(HWND hwndDlg,
257 PGENERAL_USER_DATA pUserData)
258 {
259 PUSER_INFO_3 pUserInfo = NULL;
260 LPTSTR pszFullName = NULL;
261 LPTSTR pszComment = NULL;
262 NET_API_STATUS status;
263 #if 0
264 DWORD dwIndex;
265 #endif
266 INT nLength;
267
268 NetUserGetInfo(NULL, pUserData->szUserName, 3, (LPBYTE*)&pUserInfo);
269
270 pUserInfo->usri3_flags =
271 (pUserData->dwFlags & VALID_GENERAL_FLAGS) |
272 (pUserInfo->usri3_flags & ~VALID_GENERAL_FLAGS);
273
274 pUserInfo->usri3_password_expired = pUserData->dwPasswordExpired;
275
276 nLength = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_USER_GENERAL_FULL_NAME));
277 if (nLength == 0)
278 {
279 pUserInfo->usri3_full_name = NULL;
280 }
281 else
282 {
283 pszFullName = HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(TCHAR));
284 GetDlgItemText(hwndDlg, IDC_USER_GENERAL_FULL_NAME, pszFullName, nLength + 1);
285 pUserInfo->usri3_full_name = pszFullName;
286 }
287
288 nLength = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_USER_GENERAL_DESCRIPTION));
289 if (nLength == 0)
290 {
291 pUserInfo->usri3_full_name = NULL;
292 }
293 else
294 {
295 pszComment = HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(TCHAR));
296 GetDlgItemText(hwndDlg, IDC_USER_GENERAL_DESCRIPTION, pszComment, nLength + 1);
297 pUserInfo->usri3_comment = pszComment;
298 }
299
300 #if 0
301 status = NetUserSetInfo(NULL, pUserData->szUserName, 3, (LPBYTE)pUserInfo, &dwIndex);
302 if (status != NERR_Success)
303 {
304 DebugPrintf(_T("Status: %lu Index: %lu"), status, dwIndex);
305 }
306 #else
307 status = NERR_Success;
308 #endif
309
310 if (pszFullName)
311 HeapFree(GetProcessHeap(), 0, pszFullName);
312
313 if (pszComment)
314 HeapFree(GetProcessHeap(), 0, pszComment);
315
316 NetApiBufferFree(pUserInfo);
317
318 return (status == NERR_Success);
319 }
320
321
322 INT_PTR CALLBACK
323 UserGeneralPageProc(HWND hwndDlg,
324 UINT uMsg,
325 WPARAM wParam,
326 LPARAM lParam)
327 {
328 PGENERAL_USER_DATA pUserData;
329
330 UNREFERENCED_PARAMETER(lParam);
331 UNREFERENCED_PARAMETER(wParam);
332 UNREFERENCED_PARAMETER(hwndDlg);
333
334 pUserData= (PGENERAL_USER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
335
336 switch (uMsg)
337 {
338 case WM_INITDIALOG:
339 pUserData = (PGENERAL_USER_DATA)HeapAlloc(GetProcessHeap(),
340 HEAP_ZERO_MEMORY,
341 sizeof(GENERAL_USER_DATA) +
342 lstrlen((LPTSTR)((PROPSHEETPAGE *)lParam)->lParam) * sizeof(TCHAR));
343 lstrcpy(pUserData->szUserName, (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
344
345 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pUserData);
346
347 GetGeneralUserData(hwndDlg,
348 pUserData);
349 break;
350
351 case WM_COMMAND:
352 switch (LOWORD(wParam))
353 {
354 case IDC_USER_GENERAL_FULL_NAME:
355 case IDC_USER_GENERAL_DESCRIPTION:
356 if (HIWORD(wParam) == EN_CHANGE)
357 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
358 break;
359
360 case IDC_USER_GENERAL_FORCE_CHANGE:
361 pUserData->dwPasswordExpired = !pUserData->dwPasswordExpired;
362 UpdateUserOptions(hwndDlg, pUserData, FALSE);
363 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
364 break;
365
366 case IDC_USER_GENERAL_CANNOT_CHANGE:
367 pUserData->dwFlags ^= UF_PASSWD_CANT_CHANGE;
368 UpdateUserOptions(hwndDlg, pUserData, FALSE);
369 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
370 break;
371
372 case IDC_USER_GENERAL_NEVER_EXPIRES:
373 pUserData->dwFlags ^= UF_DONT_EXPIRE_PASSWD;
374 UpdateUserOptions(hwndDlg, pUserData, FALSE);
375 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
376 break;
377
378 case IDC_USER_GENERAL_DISABLED:
379 pUserData->dwFlags ^= UF_ACCOUNTDISABLE;
380 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
381 break;
382
383 case IDC_USER_GENERAL_LOCKED:
384 pUserData->dwFlags ^= UF_LOCKOUT;
385 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
386 break;
387 }
388 break;
389
390 case WM_NOTIFY:
391 if (((LPPSHNOTIFY)lParam)->hdr.code == PSN_APPLY)
392 {
393 SetGeneralUserData(hwndDlg, pUserData);
394 return TRUE;
395 }
396 break;
397
398 case WM_DESTROY:
399 HeapFree(GetProcessHeap(), 0, pUserData);
400 break;
401 }
402
403 return FALSE;
404 }
405
406
407 static VOID
408 InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc, LPTSTR pszUser)
409 {
410 ZeroMemory(psp, sizeof(PROPSHEETPAGE));
411 psp->dwSize = sizeof(PROPSHEETPAGE);
412 psp->dwFlags = PSP_DEFAULT;
413 psp->hInstance = hApplet;
414 psp->pszTemplate = MAKEINTRESOURCE(idDlg);
415 psp->pfnDlgProc = DlgProc;
416 psp->lParam = (LPARAM)pszUser;
417 }
418
419
420 BOOL
421 UserProperties(HWND hwndDlg)
422 {
423 PROPSHEETPAGE psp[3];
424 PROPSHEETHEADER psh;
425 TCHAR szUserName[UNLEN];
426 INT nItem;
427 HWND hwndLV;
428
429 hwndLV = GetDlgItem(hwndDlg, IDC_USERS_LIST);
430 nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
431 if (nItem == -1)
432 return FALSE;
433
434 /* Get the new user name */
435 ListView_GetItemText(hwndLV,
436 nItem, 0,
437 szUserName,
438 UNLEN);
439
440 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
441 psh.dwSize = sizeof(PROPSHEETHEADER);
442 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE;
443 psh.hwndParent = hwndDlg;
444 psh.hInstance = hApplet;
445 psh.hIcon = NULL;
446 psh.pszCaption = szUserName;
447 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
448 psh.nStartPage = 0;
449 psh.ppsp = psp;
450
451 InitPropSheetPage(&psp[0], IDD_USER_GENERAL, (DLGPROC)UserGeneralPageProc, szUserName);
452 InitPropSheetPage(&psp[1], IDD_USER_MEMBERSHIP, (DLGPROC)UserMembershipPageProc, szUserName);
453 InitPropSheetPage(&psp[2], IDD_USER_PROFILE, (DLGPROC)UserProfilePageProc, szUserName);
454
455 return (PropertySheet(&psh) == IDOK);
456 }