43c206fb51d36ead6fd6c143a4e947f34dd5097d
[reactos.git] / reactos / dll / cpl / usrmgr / users.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS User Manager Control Panel
4 * FILE: dll/cpl/usrmgr/users.c
5 * PURPOSE: Users property page
6 *
7 * PROGRAMMERS: Eric Kohl
8 */
9
10 /*
11 * TODO:
12 * - Add new user to the users group.
13 * - Remove a user from all groups.
14 * - Implement user property pages.
15 * - Use localized messages.
16 */
17
18 #include "usrmgr.h"
19
20
21 typedef struct _USER_DATA
22 {
23 HMENU hPopupMenu;
24
25 INT iCurrentItem;
26
27 } USER_DATA, *PUSER_DATA;
28
29
30
31 static BOOL
32 CheckPasswords(HWND hwndDlg,
33 INT nIdDlgItem1,
34 INT nIdDlgItem2)
35 {
36 TCHAR szPassword1[256];
37 TCHAR szPassword2[256];
38 UINT uLen1;
39 UINT uLen2;
40
41 uLen1 = GetDlgItemText(hwndDlg, nIdDlgItem1, szPassword1, 256);
42 uLen2 = GetDlgItemText(hwndDlg, nIdDlgItem2, szPassword2, 256);
43
44 /* Check the passwords */
45 if (uLen1 != uLen2 || _tcscmp(szPassword1, szPassword2) != 0)
46 {
47 MessageBox(hwndDlg,
48 TEXT("The passwords you entered are not the same!"),
49 TEXT("ERROR"),
50 MB_OK | MB_ICONERROR);
51 return FALSE;
52 }
53
54
55 return TRUE;
56 }
57
58
59 static BOOL
60 CheckUserName(HWND hwndDlg,
61 INT nIdDlgItem)
62 {
63 TCHAR szUserName[256];
64 UINT uLen;
65
66 uLen = GetDlgItemText(hwndDlg, nIdDlgItem, szUserName, 256);
67
68 /* Check the user name */
69 if (uLen > 0 && _tcspbrk(szUserName, TEXT("\"*+,/\\:;<=>?[]|")) != NULL)
70 {
71 MessageBox(hwndDlg,
72 TEXT("The user name you entered is invalid! A user name must not contain the following charecters: *+,/:;<=>?[\\]|"),
73 TEXT("ERROR"),
74 MB_OK | MB_ICONERROR);
75 return FALSE;
76 }
77
78
79 return TRUE;
80 }
81
82
83
84 INT_PTR CALLBACK
85 ChangePasswordDlgProc(HWND hwndDlg,
86 UINT uMsg,
87 WPARAM wParam,
88 LPARAM lParam)
89 {
90 UNREFERENCED_PARAMETER(wParam);
91
92 switch (uMsg)
93 {
94 case WM_INITDIALOG:
95 break;
96
97 case WM_COMMAND:
98 switch (LOWORD(wParam))
99 {
100 case IDOK:
101 if (CheckPasswords(hwndDlg, IDC_EDIT_PASSWORD1, IDC_EDIT_PASSWORD2))
102 EndDialog(hwndDlg, 0);
103 break;
104
105 case IDCANCEL:
106 EndDialog(hwndDlg, 0);
107 break;
108 }
109 break;
110
111 default:
112 return FALSE;
113 }
114
115 return TRUE;
116 }
117
118
119 INT_PTR CALLBACK
120 NewUserDlgProc(HWND hwndDlg,
121 UINT uMsg,
122 WPARAM wParam,
123 LPARAM lParam)
124 {
125 PUSER_INFO_3 userInfo;
126 INT nLength;
127
128 UNREFERENCED_PARAMETER(wParam);
129
130 switch (uMsg)
131 {
132 case WM_INITDIALOG:
133 SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
134 SendDlgItemMessage(hwndDlg, IDC_USER_NEW_NAME, EM_SETLIMITTEXT, 20, 0);
135 CheckDlgButton(hwndDlg, IDC_USER_NEW_FORCE_CHANGE, BST_CHECKED);
136 break;
137
138 case WM_COMMAND:
139 switch (LOWORD(wParam))
140 {
141 case IDC_USER_NEW_NAME:
142 if (HIWORD(wParam) == EN_CHANGE)
143 {
144 nLength = SendDlgItemMessage(hwndDlg, IDC_USER_NEW_NAME, WM_GETTEXTLENGTH, 0, 0);
145 EnableWindow(GetDlgItem(hwndDlg, IDOK), (nLength > 0));
146 }
147 break;
148
149 case IDOK:
150 if (!CheckUserName(hwndDlg, IDC_USER_NEW_NAME))
151 {
152 SetFocus(GetDlgItem(hwndDlg, IDC_USER_NEW_NAME));
153 SendDlgItemMessage(hwndDlg, IDC_USER_NEW_NAME, EM_SETSEL, 0, -1);
154 break;
155 }
156
157 if (!CheckPasswords(hwndDlg, IDC_USER_NEW_PASSWORD1, IDC_USER_NEW_PASSWORD2))
158 {
159 SetDlgItemText(hwndDlg, IDC_USER_NEW_PASSWORD1, TEXT(""));
160 SetDlgItemText(hwndDlg, IDC_USER_NEW_PASSWORD2, TEXT(""));
161 break;
162 }
163
164 userInfo = (LPUSER_INFO_3)GetWindowLongPtr(hwndDlg, DWLP_USER);
165
166 nLength = SendDlgItemMessage(hwndDlg, IDC_USER_NEW_NAME, WM_GETTEXTLENGTH, 0, 0);
167 if (nLength > 0)
168 {
169 userInfo->usri3_name = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nLength + 1) * sizeof(WCHAR));
170 GetDlgItemText(hwndDlg, IDC_USER_NEW_NAME, userInfo->usri3_name, nLength + 1);
171 }
172
173 nLength = SendDlgItemMessage(hwndDlg, IDC_USER_NEW_FULL_NAME, WM_GETTEXTLENGTH, 0, 0);
174 if (nLength > 0)
175 {
176 userInfo->usri3_full_name = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nLength + 1) * sizeof(WCHAR));
177 GetDlgItemText(hwndDlg, IDC_USER_NEW_FULL_NAME, userInfo->usri3_full_name, nLength + 1);
178 }
179
180 nLength = SendDlgItemMessage(hwndDlg, IDC_USER_NEW_DESCRIPTION, WM_GETTEXTLENGTH, 0, 0);
181 if (nLength > 0)
182 {
183 userInfo->usri3_comment = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nLength + 1) * sizeof(WCHAR));
184 GetDlgItemText(hwndDlg, IDC_USER_NEW_DESCRIPTION, userInfo->usri3_comment, nLength + 1);
185 }
186
187 /* Store the password */
188 nLength = SendDlgItemMessage(hwndDlg, IDC_USER_NEW_PASSWORD1, WM_GETTEXTLENGTH, 0, 0);
189 if (nLength > 0)
190 {
191 userInfo->usri3_password = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nLength + 1) * sizeof(WCHAR));
192 GetDlgItemText(hwndDlg, IDC_USER_NEW_PASSWORD1, userInfo->usri3_password, nLength + 1);
193 }
194
195 if (IsDlgButtonChecked(hwndDlg, IDC_USER_NEW_FORCE_CHANGE) == BST_CHECKED)
196 userInfo->usri3_password_expired = TRUE;
197
198 if (IsDlgButtonChecked(hwndDlg, IDC_USER_NEW_DISABLED) == BST_CHECKED)
199 userInfo->usri3_flags |= UF_ACCOUNTDISABLE;
200
201 EndDialog(hwndDlg, IDOK);
202 break;
203
204 case IDCANCEL:
205 EndDialog(hwndDlg, IDCANCEL);
206 break;
207 }
208 break;
209
210 default:
211 return FALSE;
212 }
213
214 return TRUE;
215 }
216
217
218 static VOID
219 UserNew(HWND hwndDlg)
220 {
221 USER_INFO_3 user;
222 NET_API_STATUS status;
223 LV_ITEM lvi;
224 INT iItem;
225 HWND hwndLV;
226
227 ZeroMemory(&user, sizeof(USER_INFO_3));
228
229 user.usri3_priv = USER_PRIV_USER;
230 user.usri3_flags = UF_SCRIPT;
231 user.usri3_acct_expires = TIMEQ_FOREVER;
232 user.usri3_max_storage = USER_MAXSTORAGE_UNLIMITED;
233 user.usri3_primary_group_id = DOMAIN_GROUP_RID_USERS;
234
235 if (DialogBoxParam(hApplet,
236 MAKEINTRESOURCE(IDD_USER_NEW),
237 hwndDlg,
238 NewUserDlgProc,
239 (LPARAM)&user) == IDOK)
240 {
241 #if 0
242 status = NetUserAdd(NULL,
243 3,
244 (LPBYTE)&user,
245 NULL);
246 #else
247 status = NERR_Success;
248 #endif
249 if (status != NERR_Success)
250 {
251 TCHAR szText[256];
252 wsprintf(szText, TEXT("Error: %u"), status);
253 MessageBox(NULL, szText, TEXT("NetUserAdd"), MB_ICONERROR | MB_OK);
254 return;
255 }
256
257 hwndLV = GetDlgItem(hwndDlg, IDC_USERS_LIST);
258
259 ZeroMemory(&lvi, sizeof(lvi));
260 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
261 lvi.pszText = user.usri3_name;
262 lvi.state = 0;
263 lvi.iImage = (user.usri3_flags & UF_ACCOUNTDISABLE) ? 1 : 0;
264 iItem = ListView_InsertItem(hwndLV, &lvi);
265
266 ListView_SetItemText(hwndLV, iItem, 1,
267 user.usri3_full_name);
268
269 ListView_SetItemText(hwndLV, iItem, 2,
270 user.usri3_comment);
271 }
272
273 if (user.usri3_name)
274 HeapFree(GetProcessHeap, 0, user.usri3_name);
275
276 if (user.usri3_full_name)
277 HeapFree(GetProcessHeap, 0, user.usri3_full_name);
278
279 if (user.usri3_comment)
280 HeapFree(GetProcessHeap, 0, user.usri3_comment);
281
282 if (user.usri3_password)
283 HeapFree(GetProcessHeap, 0, user.usri3_password);
284 }
285
286
287 static BOOL
288 UserDelete(HWND hwndDlg)
289 {
290 TCHAR szUserName[UNLEN];
291 TCHAR szText[256];
292 INT nItem;
293 HWND hwndLV;
294 NET_API_STATUS status;
295
296 hwndLV = GetDlgItem(hwndDlg, IDC_USERS_LIST);
297 nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
298 if (nItem == -1)
299 return FALSE;
300
301 /* Get the new user name */
302 ListView_GetItemText(hwndLV,
303 nItem, 0,
304 szUserName,
305 UNLEN);
306
307 /* Display a warning message because the delete operation cannot be reverted */
308 wsprintf(szText, TEXT("Dou you really want to delete the user \"%s\"?"), szUserName);
309 if (MessageBox(NULL, szText, TEXT("User Accounts"), MB_ICONWARNING | MB_YESNO) == IDNO)
310 return FALSE;
311
312 /* Delete the user */
313 #if 0
314 status = NetUserDel(NULL, szUserName);
315 #else
316 status = NERR_Success;
317 #endif
318 if (status != NERR_Success)
319 {
320 TCHAR szText[256];
321 wsprintf(szText, TEXT("Error: %u"), status);
322 MessageBox(NULL, szText, TEXT("NetUserDel"), MB_ICONERROR | MB_OK);
323 return FALSE;
324 }
325
326 /* Delete the user from the list */
327 (void)ListView_DeleteItem(hwndLV, nItem);
328
329 return TRUE;
330 }
331
332
333 static VOID
334 SetUsersListColumns(HWND hwndListView)
335 {
336 LV_COLUMN column;
337 RECT rect;
338 TCHAR szStr[32];
339
340 GetClientRect(hwndListView, &rect);
341
342 memset(&column, 0x00, sizeof(column));
343 column.mask=LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
344 column.fmt=LVCFMT_LEFT;
345 column.cx = (INT)((rect.right - rect.left) * 0.25);
346 column.iSubItem = 0;
347 LoadString(hApplet, IDS_NAME, szStr, sizeof(szStr) / sizeof(szStr[0]));
348 column.pszText = szStr;
349 (void)ListView_InsertColumn(hwndListView, 0, &column);
350
351 column.cx = (INT)((rect.right - rect.left) * 0.50);
352 column.iSubItem = 1;
353 LoadString(hApplet, IDS_FULLNAME, szStr, sizeof(szStr) / sizeof(szStr[0]));
354 column.pszText = szStr;
355 (void)ListView_InsertColumn(hwndListView, 1, &column);
356
357 column.cx = (INT)((rect.right - rect.left) * 0.25);
358 column.iSubItem = 2;
359 LoadString(hApplet, IDS_DESCRIPTION, szStr, sizeof(szStr) / sizeof(szStr[0]));
360 column.pszText = szStr;
361 (void)ListView_InsertColumn(hwndListView, 2, &column);
362 }
363
364
365 static VOID
366 UpdateUsersList(HWND hwndListView)
367 {
368 NET_API_STATUS netStatus;
369 PUSER_INFO_20 pBuffer;
370 DWORD entriesread;
371 DWORD totalentries;
372 DWORD resume_handle = 0;
373 DWORD i;
374 LV_ITEM lvi;
375 INT iItem;
376
377
378 for (;;)
379 {
380 netStatus = NetUserEnum(NULL, 20, FILTER_NORMAL_ACCOUNT,
381 (LPBYTE*)&pBuffer,
382 1024, &entriesread,
383 &totalentries, &resume_handle);
384 if (netStatus != NERR_Success && netStatus != ERROR_MORE_DATA)
385 break;
386
387 for (i = 0; i < entriesread; i++)
388 {
389 memset(&lvi, 0x00, sizeof(lvi));
390 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
391 lvi.pszText = pBuffer[i].usri20_name;
392 lvi.state = 0;
393 lvi.iImage = (pBuffer[i].usri20_flags & UF_ACCOUNTDISABLE) ? 1 : 0;
394 iItem = ListView_InsertItem(hwndListView, &lvi);
395
396 ListView_SetItemText(hwndListView, iItem, 1,
397 pBuffer[i].usri20_full_name);
398
399 ListView_SetItemText(hwndListView, iItem, 2,
400 pBuffer[i].usri20_comment);
401 }
402
403 NetApiBufferFree(&pBuffer);
404
405 /* No more data left */
406 if (netStatus != ERROR_MORE_DATA)
407 break;
408 }
409
410 }
411
412
413 static VOID
414 OnInitDialog(HWND hwndDlg)
415 {
416 HWND hwndListView;
417 HIMAGELIST hImgList;
418 HICON hIcon;
419
420 /* Create the image list */
421 hImgList = ImageList_Create(16, 16, ILC_COLOR8 | ILC_MASK, 5, 5);
422 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_USER), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
423 ImageList_AddIcon(hImgList, hIcon);
424 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_LOCKED_USER), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
425 ImageList_AddIcon(hImgList, hIcon);
426 DestroyIcon(hIcon);
427
428 hwndListView = GetDlgItem(hwndDlg, IDC_USERS_LIST);
429
430 (VOID)ListView_SetImageList(hwndListView, hImgList, LVSIL_SMALL);
431
432 (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
433
434 SetUsersListColumns(hwndListView);
435
436 UpdateUsersList(hwndListView);
437 }
438
439
440 static BOOL
441 OnEndLabelEdit(LPNMLVDISPINFO pnmv)
442 {
443 TCHAR szOldUserName[UNLEN];
444 TCHAR szNewUserName[UNLEN];
445 USER_INFO_0 useri0;
446 NET_API_STATUS status;
447
448 /* Leave, if there is no valid listview item */
449 if (pnmv->item.iItem == -1)
450 return FALSE;
451
452 /* Get the new user name */
453 ListView_GetItemText(pnmv->hdr.hwndFrom,
454 pnmv->item.iItem, 0,
455 szOldUserName,
456 UNLEN);
457
458 /* Leave, if the user canceled the edit action */
459 if (pnmv->item.pszText == NULL)
460 return FALSE;
461
462 /* Get the new user name */
463 lstrcpy(szNewUserName, pnmv->item.pszText);
464
465 /* Leave, if the user name was not changed */
466 if (lstrcmp(szOldUserName, szNewUserName) == 0)
467 return FALSE;
468
469
470 /* Change the user name */
471 useri0.usri0_name = szNewUserName;
472
473 #if 0
474 status = NetUserSetInfo(NULL, szOldUserName, 0, (LPBYTE)&useri0, NULL);
475 #else
476 status = NERR_Success;
477 #endif
478 if (status != NERR_Success)
479 {
480 TCHAR szText[256];
481 wsprintf(szText, TEXT("Error: %u"), status);
482 MessageBox(NULL, szText, TEXT("NetUserSetInfo"), MB_ICONERROR | MB_OK);
483 return FALSE;
484 }
485
486 /* Update the listview item */
487 ListView_SetItemText(pnmv->hdr.hwndFrom,
488 pnmv->item.iItem, 0,
489 szNewUserName);
490
491 return TRUE;
492 }
493
494
495 static BOOL
496 OnNotify(HWND hwndDlg, PUSER_DATA pUserData, NMHDR *phdr)
497 {
498 LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
499
500 switch (phdr->idFrom)
501 {
502 case IDC_USERS_LIST:
503 switch(phdr->code)
504 {
505 case NM_CLICK:
506 pUserData->iCurrentItem = lpnmlv->iItem;
507 if (lpnmlv->iItem == -1)
508 {
509 }
510 else
511 {
512 }
513 break;
514
515 case NM_DBLCLK:
516 break;
517
518 case LVN_ENDLABELEDIT:
519 return OnEndLabelEdit((LPNMLVDISPINFO)phdr);
520
521 case NM_RCLICK:
522 ClientToScreen(GetDlgItem(hwndDlg, IDC_USERS_LIST), &lpnmlv->ptAction);
523 TrackPopupMenu(GetSubMenu(pUserData->hPopupMenu, (lpnmlv->iItem == -1) ? 0 : 1),
524 TPM_LEFTALIGN, lpnmlv->ptAction.x, lpnmlv->ptAction.y, 0, hwndDlg, NULL);
525 break;
526 }
527 break;
528 }
529
530 return FALSE;
531 }
532
533
534 INT_PTR CALLBACK
535 UsersPageProc(HWND hwndDlg,
536 UINT uMsg,
537 WPARAM wParam,
538 LPARAM lParam)
539 {
540 PUSER_DATA pUserData;
541
542 UNREFERENCED_PARAMETER(wParam);
543
544 pUserData = (PUSER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
545
546 switch (uMsg)
547 {
548 case WM_INITDIALOG:
549 pUserData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(USER_DATA));
550 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pUserData);
551
552 pUserData->hPopupMenu = LoadMenu(hApplet, MAKEINTRESOURCE(IDM_POPUP_USER));
553
554 OnInitDialog(hwndDlg);
555 break;
556
557 case WM_COMMAND:
558 switch (LOWORD(wParam))
559 {
560 case IDM_USER_CHANGE_PASSWORD:
561 DialogBoxParam(hApplet,
562 MAKEINTRESOURCE(IDD_CHANGE_PASSWORD),
563 hwndDlg,
564 ChangePasswordDlgProc,
565 (LPARAM)NULL);
566 break;
567
568 case IDM_USER_RENAME:
569 {
570 INT nItem;
571 HWND hwndLV;
572
573 hwndLV = GetDlgItem(hwndDlg, IDC_USERS_LIST);
574 nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
575 if (nItem != -1)
576 {
577 (void)ListView_EditLabel(hwndLV, nItem);
578 }
579 }
580 break;
581
582 case IDM_USER_NEW:
583 UserNew(hwndDlg);
584 break;
585
586 case IDM_USER_DELETE:
587 UserDelete(hwndDlg);
588 break;
589
590 case IDM_USER_PROPERTIES:
591 MessageBeep(-1);
592 break;
593 }
594 break;
595
596 case WM_NOTIFY:
597 return OnNotify(hwndDlg, pUserData, (NMHDR *)lParam);
598
599 case WM_DESTROY:
600 DestroyMenu(pUserData->hPopupMenu);
601 HeapFree(GetProcessHeap(), 0, pUserData);
602 break;
603 }
604
605 return FALSE;
606 }