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
7 * PROGRAMMERS: Eric Kohl
12 * - Add new user to the users group.
13 * - Remove a user from all groups.
14 * - Use localized messages.
19 typedef struct _USER_DATA
25 } USER_DATA
, *PUSER_DATA
;
30 CheckPasswords(HWND hwndDlg
,
34 TCHAR szPassword1
[PWLEN
];
35 TCHAR szPassword2
[PWLEN
];
39 uLen1
= GetDlgItemText(hwndDlg
, nIdDlgItem1
, szPassword1
, PWLEN
);
40 uLen2
= GetDlgItemText(hwndDlg
, nIdDlgItem2
, szPassword2
, PWLEN
);
42 /* Check the passwords */
43 if (uLen1
!= uLen2
|| _tcscmp(szPassword1
, szPassword2
) != 0)
46 TEXT("The passwords you entered are not the same!"),
48 MB_OK
| MB_ICONERROR
);
57 ChangePasswordDlgProc(HWND hwndDlg
,
62 PUSER_INFO_1003 userInfo
;
65 UNREFERENCED_PARAMETER(wParam
);
67 userInfo
= (PUSER_INFO_1003
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
72 userInfo
= (PUSER_INFO_1003
)lParam
;
73 SetWindowLongPtr(hwndDlg
, DWLP_USER
, lParam
);
77 switch (LOWORD(wParam
))
80 if (CheckPasswords(hwndDlg
, IDC_EDIT_PASSWORD1
, IDC_EDIT_PASSWORD2
))
83 /* Store the password */
84 nLength
= SendDlgItemMessage(hwndDlg
, IDC_EDIT_PASSWORD1
, WM_GETTEXTLENGTH
, 0, 0);
87 userInfo
->usri1003_password
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
88 GetDlgItemText(hwndDlg
, IDC_EDIT_PASSWORD1
, userInfo
->usri1003_password
, nLength
+ 1);
91 EndDialog(hwndDlg
, IDOK
);
96 EndDialog(hwndDlg
, IDCANCEL
);
110 UserChangePassword(HWND hwndDlg
)
112 TCHAR szUserName
[UNLEN
];
116 NET_API_STATUS status
;
118 ZeroMemory(&user
, sizeof(USER_INFO_1003
));
120 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
121 nItem
= ListView_GetNextItem(hwndLV
, -1, LVNI_SELECTED
);
125 /* Get the new user name */
126 ListView_GetItemText(hwndLV
,
131 if (DialogBoxParam(hApplet
,
132 MAKEINTRESOURCE(IDD_CHANGE_PASSWORD
),
134 ChangePasswordDlgProc
,
135 (LPARAM
)&user
) == IDOK
)
137 status
= NetUserSetInfo(NULL
,
142 if (status
!= NERR_Success
)
145 wsprintf(szText
, TEXT("Error: %u"), status
);
146 MessageBox(NULL
, szText
, TEXT("NetUserSetInfo"), MB_ICONERROR
| MB_OK
);
150 if (user
.usri1003_password
)
151 HeapFree(GetProcessHeap(), 0, user
.usri1003_password
);
156 UpdateUserOptions(HWND hwndDlg
,
157 PUSER_INFO_3 userInfo
,
160 EnableWindow(GetDlgItem(hwndDlg
, IDC_USER_NEW_CANNOT_CHANGE
),
161 !userInfo
->usri3_password_expired
);
162 EnableWindow(GetDlgItem(hwndDlg
, IDC_USER_NEW_NEVER_EXPIRES
),
163 !userInfo
->usri3_password_expired
);
165 EnableWindow(GetDlgItem(hwndDlg
, IDC_USER_NEW_FORCE_CHANGE
),
166 (userInfo
->usri3_flags
& (UF_PASSWD_CANT_CHANGE
| UF_DONT_EXPIRE_PASSWD
)) == 0);
170 CheckDlgButton(hwndDlg
, IDC_USER_NEW_FORCE_CHANGE
,
171 userInfo
->usri3_password_expired
? BST_CHECKED
: BST_UNCHECKED
);
173 CheckDlgButton(hwndDlg
, IDC_USER_NEW_CANNOT_CHANGE
,
174 (userInfo
->usri3_flags
& UF_PASSWD_CANT_CHANGE
) ? BST_CHECKED
: BST_UNCHECKED
);
176 CheckDlgButton(hwndDlg
, IDC_USER_NEW_NEVER_EXPIRES
,
177 (userInfo
->usri3_flags
& UF_DONT_EXPIRE_PASSWD
) ? BST_CHECKED
: BST_UNCHECKED
);
179 CheckDlgButton(hwndDlg
, IDC_USER_NEW_DISABLED
,
180 (userInfo
->usri3_flags
& UF_ACCOUNTDISABLE
) ? BST_CHECKED
: BST_UNCHECKED
);
186 NewUserDlgProc(HWND hwndDlg
,
191 PUSER_INFO_3 userInfo
;
194 UNREFERENCED_PARAMETER(wParam
);
196 userInfo
= (PUSER_INFO_3
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
201 userInfo
= (PUSER_INFO_3
)lParam
;
202 SetWindowLongPtr(hwndDlg
, DWLP_USER
, lParam
);
203 SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_NAME
, EM_SETLIMITTEXT
, 20, 0);
204 UpdateUserOptions(hwndDlg
, userInfo
, TRUE
);
208 switch (LOWORD(wParam
))
210 case IDC_USER_NEW_NAME
:
211 if (HIWORD(wParam
) == EN_CHANGE
)
213 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_NAME
, WM_GETTEXTLENGTH
, 0, 0);
214 EnableWindow(GetDlgItem(hwndDlg
, IDOK
), (nLength
> 0));
218 case IDC_USER_NEW_FORCE_CHANGE
:
219 userInfo
->usri3_password_expired
= !userInfo
->usri3_password_expired
;
220 UpdateUserOptions(hwndDlg
, userInfo
, FALSE
);
223 case IDC_USER_NEW_CANNOT_CHANGE
:
224 userInfo
->usri3_flags
^= UF_PASSWD_CANT_CHANGE
;
225 UpdateUserOptions(hwndDlg
, userInfo
, FALSE
);
228 case IDC_USER_NEW_NEVER_EXPIRES
:
229 userInfo
->usri3_flags
^= UF_DONT_EXPIRE_PASSWD
;
230 UpdateUserOptions(hwndDlg
, userInfo
, FALSE
);
233 case IDC_USER_NEW_DISABLED
:
234 userInfo
->usri3_flags
^= UF_ACCOUNTDISABLE
;
238 if (!CheckAccountName(hwndDlg
, IDC_USER_NEW_NAME
, NULL
))
240 SetFocus(GetDlgItem(hwndDlg
, IDC_USER_NEW_NAME
));
241 SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_NAME
, EM_SETSEL
, 0, -1);
245 if (!CheckPasswords(hwndDlg
, IDC_USER_NEW_PASSWORD1
, IDC_USER_NEW_PASSWORD2
))
247 SetDlgItemText(hwndDlg
, IDC_USER_NEW_PASSWORD1
, TEXT(""));
248 SetDlgItemText(hwndDlg
, IDC_USER_NEW_PASSWORD2
, TEXT(""));
252 /* Store the user name */
253 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_NAME
, WM_GETTEXTLENGTH
, 0, 0);
256 userInfo
->usri3_name
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
257 GetDlgItemText(hwndDlg
, IDC_USER_NEW_NAME
, userInfo
->usri3_name
, nLength
+ 1);
260 /* Store the full user name */
261 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_FULL_NAME
, WM_GETTEXTLENGTH
, 0, 0);
264 userInfo
->usri3_full_name
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
265 GetDlgItemText(hwndDlg
, IDC_USER_NEW_FULL_NAME
, userInfo
->usri3_full_name
, nLength
+ 1);
268 /* Store the description */
269 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_DESCRIPTION
, WM_GETTEXTLENGTH
, 0, 0);
272 userInfo
->usri3_comment
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
273 GetDlgItemText(hwndDlg
, IDC_USER_NEW_DESCRIPTION
, userInfo
->usri3_comment
, nLength
+ 1);
276 /* Store the password */
277 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_PASSWORD1
, WM_GETTEXTLENGTH
, 0, 0);
280 userInfo
->usri3_password
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
281 GetDlgItemText(hwndDlg
, IDC_USER_NEW_PASSWORD1
, userInfo
->usri3_password
, nLength
+ 1);
284 EndDialog(hwndDlg
, IDOK
);
288 EndDialog(hwndDlg
, IDCANCEL
);
302 UserNew(HWND hwndDlg
)
305 NET_API_STATUS status
;
310 ZeroMemory(&user
, sizeof(USER_INFO_3
));
312 user
.usri3_priv
= USER_PRIV_USER
;
313 user
.usri3_flags
= UF_SCRIPT
;
314 user
.usri3_acct_expires
= TIMEQ_FOREVER
;
315 user
.usri3_max_storage
= USER_MAXSTORAGE_UNLIMITED
;
316 user
.usri3_primary_group_id
= DOMAIN_GROUP_RID_USERS
;
318 user
.usri3_password_expired
= TRUE
;
320 if (DialogBoxParam(hApplet
,
321 MAKEINTRESOURCE(IDD_USER_NEW
),
324 (LPARAM
)&user
) == IDOK
)
326 status
= NetUserAdd(NULL
,
330 if (status
!= NERR_Success
)
333 wsprintf(szText
, TEXT("Error: %u"), status
);
334 MessageBox(NULL
, szText
, TEXT("NetUserAdd"), MB_ICONERROR
| MB_OK
);
338 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
340 ZeroMemory(&lvi
, sizeof(lvi
));
341 lvi
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_IMAGE
;
342 lvi
.pszText
= user
.usri3_name
;
344 lvi
.iImage
= (user
.usri3_flags
& UF_ACCOUNTDISABLE
) ? 1 : 0;
345 iItem
= ListView_InsertItem(hwndLV
, &lvi
);
347 ListView_SetItemText(hwndLV
, iItem
, 1,
348 user
.usri3_full_name
);
350 ListView_SetItemText(hwndLV
, iItem
, 2,
355 HeapFree(GetProcessHeap(), 0, user
.usri3_name
);
357 if (user
.usri3_full_name
)
358 HeapFree(GetProcessHeap(), 0, user
.usri3_full_name
);
360 if (user
.usri3_comment
)
361 HeapFree(GetProcessHeap(), 0, user
.usri3_comment
);
363 if (user
.usri3_password
)
364 HeapFree(GetProcessHeap(), 0, user
.usri3_password
);
369 UserRename(HWND hwndDlg
)
374 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
378 nItem
= ListView_GetNextItem(hwndLV
, -1, LVNI_SELECTED
);
381 (void)ListView_EditLabel(hwndLV
, nItem
);
387 UserDelete(HWND hwndDlg
)
389 TCHAR szUserName
[UNLEN
];
393 NET_API_STATUS status
;
395 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
396 nItem
= ListView_GetNextItem(hwndLV
, -1, LVNI_SELECTED
);
400 /* Get the new user name */
401 ListView_GetItemText(hwndLV
,
406 /* Display a warning message because the delete operation cannot be reverted */
407 wsprintf(szText
, TEXT("Do you really want to delete the user \"%s\"?"), szUserName
);
408 if (MessageBox(NULL
, szText
, TEXT("User Accounts"), MB_ICONWARNING
| MB_YESNO
) == IDNO
)
411 /* Delete the user */
412 status
= NetUserDel(NULL
, szUserName
);
413 if (status
!= NERR_Success
)
416 wsprintf(szText
, TEXT("Error: %u"), status
);
417 MessageBox(NULL
, szText
, TEXT("NetUserDel"), MB_ICONERROR
| MB_OK
);
421 /* Delete the user from the list */
422 (void)ListView_DeleteItem(hwndLV
, nItem
);
429 SetUsersListColumns(HWND hwndListView
)
435 GetClientRect(hwndListView
, &rect
);
437 memset(&column
, 0x00, sizeof(column
));
438 column
.mask
=LVCF_FMT
| LVCF_WIDTH
| LVCF_SUBITEM
| LVCF_TEXT
;
439 column
.fmt
=LVCFMT_LEFT
;
440 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.25);
442 LoadString(hApplet
, IDS_NAME
, szStr
, sizeof(szStr
) / sizeof(szStr
[0]));
443 column
.pszText
= szStr
;
444 (void)ListView_InsertColumn(hwndListView
, 0, &column
);
446 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.50);
448 LoadString(hApplet
, IDS_FULLNAME
, szStr
, sizeof(szStr
) / sizeof(szStr
[0]));
449 column
.pszText
= szStr
;
450 (void)ListView_InsertColumn(hwndListView
, 1, &column
);
452 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.25);
454 LoadString(hApplet
, IDS_DESCRIPTION
, szStr
, sizeof(szStr
) / sizeof(szStr
[0]));
455 column
.pszText
= szStr
;
456 (void)ListView_InsertColumn(hwndListView
, 2, &column
);
461 UpdateUsersList(HWND hwndListView
)
463 NET_API_STATUS netStatus
;
464 PUSER_INFO_20 pBuffer
;
467 DWORD resume_handle
= 0;
474 netStatus
= NetUserEnum(NULL
, 20, FILTER_NORMAL_ACCOUNT
,
477 &totalentries
, &resume_handle
);
478 if (netStatus
!= NERR_Success
&& netStatus
!= ERROR_MORE_DATA
)
481 for (i
= 0; i
< entriesread
; i
++)
483 memset(&lvi
, 0x00, sizeof(lvi
));
484 lvi
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_IMAGE
;
485 lvi
.pszText
= pBuffer
[i
].usri20_name
;
487 lvi
.iImage
= (pBuffer
[i
].usri20_flags
& UF_ACCOUNTDISABLE
) ? 1 : 0;
488 iItem
= ListView_InsertItem(hwndListView
, &lvi
);
490 if (pBuffer
[i
].usri20_full_name
!= NULL
)
491 ListView_SetItemText(hwndListView
, iItem
, 1,
492 pBuffer
[i
].usri20_full_name
);
494 if (pBuffer
[i
].usri20_comment
!= NULL
)
495 ListView_SetItemText(hwndListView
, iItem
, 2,
496 pBuffer
[i
].usri20_comment
);
499 NetApiBufferFree(pBuffer
);
501 /* No more data left */
502 if (netStatus
!= ERROR_MORE_DATA
)
509 OnInitDialog(HWND hwndDlg
)
515 /* Create the image list */
516 hImgList
= ImageList_Create(16, 16, ILC_COLOR8
| ILC_MASK
, 5, 5);
517 hIcon
= LoadImage(hApplet
, MAKEINTRESOURCE(IDI_USER
), IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
518 ImageList_AddIcon(hImgList
, hIcon
);
519 hIcon
= LoadImage(hApplet
, MAKEINTRESOURCE(IDI_LOCKED_USER
), IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
520 ImageList_AddIcon(hImgList
, hIcon
);
523 hwndListView
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
525 (VOID
)ListView_SetImageList(hwndListView
, hImgList
, LVSIL_SMALL
);
527 (void)ListView_SetExtendedListViewStyle(hwndListView
, LVS_EX_FULLROWSELECT
);
529 SetUsersListColumns(hwndListView
);
531 UpdateUsersList(hwndListView
);
536 OnBeginLabelEdit(LPNMLVDISPINFO pnmv
)
540 hwndEdit
= ListView_GetEditControl(pnmv
->hdr
.hwndFrom
);
541 if (hwndEdit
== NULL
)
544 SendMessage(hwndEdit
, EM_SETLIMITTEXT
, 20, 0);
551 OnEndLabelEdit(LPNMLVDISPINFO pnmv
)
553 TCHAR szOldUserName
[UNLEN
];
554 TCHAR szNewUserName
[UNLEN
];
556 NET_API_STATUS status
;
558 /* Leave, if there is no valid listview item */
559 if (pnmv
->item
.iItem
== -1)
562 /* Get the new user name */
563 ListView_GetItemText(pnmv
->hdr
.hwndFrom
,
568 /* Leave, if the user canceled the edit action */
569 if (pnmv
->item
.pszText
== NULL
)
572 /* Get the new user name */
573 lstrcpy(szNewUserName
, pnmv
->item
.pszText
);
575 /* Leave, if the user name was not changed */
576 if (lstrcmp(szOldUserName
, szNewUserName
) == 0)
579 /* Check the user name for illegal characters */
580 if (!CheckAccountName(NULL
, 0, szNewUserName
))
583 /* Change the user name */
584 useri0
.usri0_name
= szNewUserName
;
586 status
= NetUserSetInfo(NULL
, szOldUserName
, 0, (LPBYTE
)&useri0
, NULL
);
587 if (status
!= NERR_Success
)
590 wsprintf(szText
, TEXT("Error: %u"), status
);
591 MessageBox(NULL
, szText
, TEXT("NetUserSetInfo"), MB_ICONERROR
| MB_OK
);
595 /* Update the listview item */
596 ListView_SetItemText(pnmv
->hdr
.hwndFrom
,
605 OnNotify(HWND hwndDlg
, PUSER_DATA pUserData
, NMHDR
*phdr
)
607 LPNMLISTVIEW lpnmlv
= (LPNMLISTVIEW
)phdr
;
609 switch (phdr
->idFrom
)
615 pUserData
->iCurrentItem
= lpnmlv
->iItem
;
619 if (lpnmlv
->iItem
!= -1)
623 uItem
= GetMenuDefaultItem(GetSubMenu(pUserData
->hPopupMenu
, 1),
625 if (uItem
!= (UINT
)-1)
626 SendMessage(hwndDlg
, WM_COMMAND
, MAKEWPARAM(uItem
, 0), 0);
631 ClientToScreen(GetDlgItem(hwndDlg
, IDC_USERS_LIST
), &lpnmlv
->ptAction
);
632 TrackPopupMenu(GetSubMenu(pUserData
->hPopupMenu
, (lpnmlv
->iItem
== -1) ? 0 : 1),
633 TPM_LEFTALIGN
, lpnmlv
->ptAction
.x
, lpnmlv
->ptAction
.y
, 0, hwndDlg
, NULL
);
636 case LVN_BEGINLABELEDIT
:
637 return OnBeginLabelEdit((LPNMLVDISPINFO
)phdr
);
639 case LVN_ENDLABELEDIT
:
640 return OnEndLabelEdit((LPNMLVDISPINFO
)phdr
);
650 UpdateUserProperties(HWND hwndDlg
)
652 TCHAR szUserName
[UNLEN
];
655 PUSER_INFO_2 pUserInfo
= NULL
;
658 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
659 iItem
= ListView_GetNextItem(hwndLV
, -1, LVNI_SELECTED
);
663 /* Get the new user name */
664 ListView_GetItemText(hwndLV
,
669 NetUserGetInfo(NULL
, szUserName
, 2, (LPBYTE
*)&pUserInfo
);
671 memset(&lvi
, 0x00, sizeof(lvi
));
674 lvi
.mask
= LVIF_IMAGE
;
675 lvi
.iImage
= (pUserInfo
->usri2_flags
& UF_ACCOUNTDISABLE
) ? 1 : 0;
676 (void)ListView_SetItem(hwndLV
, &lvi
);
678 ListView_SetItemText(hwndLV
, iItem
, 1,
679 pUserInfo
->usri2_full_name
);
681 ListView_SetItemText(hwndLV
, iItem
, 2,
682 pUserInfo
->usri2_comment
);
684 NetApiBufferFree(pUserInfo
);
689 UsersPageProc(HWND hwndDlg
,
694 PUSER_DATA pUserData
;
696 UNREFERENCED_PARAMETER(wParam
);
698 pUserData
= (PUSER_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
703 pUserData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(USER_DATA
));
704 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pUserData
);
706 pUserData
->hPopupMenu
= LoadMenu(hApplet
, MAKEINTRESOURCE(IDM_POPUP_USER
));
708 OnInitDialog(hwndDlg
);
709 SetMenuDefaultItem(GetSubMenu(pUserData
->hPopupMenu
, 1),
715 switch (LOWORD(wParam
))
717 case IDM_USER_CHANGE_PASSWORD
:
718 UserChangePassword(hwndDlg
);
721 case IDM_USER_RENAME
:
730 case IDM_USER_DELETE
:
731 case IDC_USERS_REMOVE
:
735 case IDM_USER_PROPERTIES
:
736 case IDC_USERS_PROPERTIES
:
737 if (UserProperties(hwndDlg
))
739 UpdateUserProperties(hwndDlg
);
746 return OnNotify(hwndDlg
, pUserData
, (NMHDR
*)lParam
);
749 DestroyMenu(pUserData
->hPopupMenu
);
750 HeapFree(GetProcessHeap(), 0, pUserData
);