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.
20 typedef struct _USER_DATA
26 } USER_DATA
, *PUSER_DATA
;
31 CheckPasswords(HWND hwndDlg
,
35 TCHAR szPassword1
[256];
36 TCHAR szPassword2
[256];
40 uLen1
= GetDlgItemText(hwndDlg
, nIdDlgItem1
, szPassword1
, 256);
41 uLen2
= GetDlgItemText(hwndDlg
, nIdDlgItem2
, szPassword2
, 256);
43 /* Check the passwords */
44 if (uLen1
!= uLen2
|| _tcscmp(szPassword1
, szPassword2
) != 0)
47 TEXT("The passwords you entered are not the same!"),
49 MB_OK
| MB_ICONERROR
);
59 ChangePasswordDlgProc(HWND hwndDlg
,
64 UNREFERENCED_PARAMETER(wParam
);
72 switch (LOWORD(wParam
))
75 if (CheckPasswords(hwndDlg
, IDC_EDIT_PASSWORD1
, IDC_EDIT_PASSWORD2
))
76 EndDialog(hwndDlg
, 0);
80 EndDialog(hwndDlg
, 0);
94 UpdateUserOptions(HWND hwndDlg
,
95 PUSER_INFO_3 userInfo
,
98 EnableWindow(GetDlgItem(hwndDlg
, IDC_USER_NEW_CANNOT_CHANGE
),
99 !userInfo
->usri3_password_expired
);
100 EnableWindow(GetDlgItem(hwndDlg
, IDC_USER_NEW_NEVER_EXPIRES
),
101 !userInfo
->usri3_password_expired
);
103 EnableWindow(GetDlgItem(hwndDlg
, IDC_USER_NEW_FORCE_CHANGE
),
104 (userInfo
->usri3_flags
& (UF_PASSWD_CANT_CHANGE
| UF_DONT_EXPIRE_PASSWD
)) == 0);
108 CheckDlgButton(hwndDlg
, IDC_USER_NEW_FORCE_CHANGE
,
109 userInfo
->usri3_password_expired
? BST_CHECKED
: BST_UNCHECKED
);
111 CheckDlgButton(hwndDlg
, IDC_USER_NEW_CANNOT_CHANGE
,
112 (userInfo
->usri3_flags
& UF_PASSWD_CANT_CHANGE
) ? BST_CHECKED
: BST_UNCHECKED
);
114 CheckDlgButton(hwndDlg
, IDC_USER_NEW_NEVER_EXPIRES
,
115 (userInfo
->usri3_flags
& UF_DONT_EXPIRE_PASSWD
) ? BST_CHECKED
: BST_UNCHECKED
);
117 CheckDlgButton(hwndDlg
, IDC_USER_NEW_DISABLED
,
118 (userInfo
->usri3_flags
& UF_ACCOUNTDISABLE
) ? BST_CHECKED
: BST_UNCHECKED
);
124 NewUserDlgProc(HWND hwndDlg
,
129 PUSER_INFO_3 userInfo
;
132 UNREFERENCED_PARAMETER(wParam
);
134 userInfo
= (PUSER_INFO_3
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
139 userInfo
= (PUSER_INFO_3
)lParam
;
140 SetWindowLongPtr(hwndDlg
, DWLP_USER
, lParam
);
141 SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_NAME
, EM_SETLIMITTEXT
, 20, 0);
142 UpdateUserOptions(hwndDlg
, userInfo
, TRUE
);
146 switch (LOWORD(wParam
))
148 case IDC_USER_NEW_NAME
:
149 if (HIWORD(wParam
) == EN_CHANGE
)
151 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_NAME
, WM_GETTEXTLENGTH
, 0, 0);
152 EnableWindow(GetDlgItem(hwndDlg
, IDOK
), (nLength
> 0));
156 case IDC_USER_NEW_FORCE_CHANGE
:
157 userInfo
->usri3_password_expired
= !userInfo
->usri3_password_expired
;
158 UpdateUserOptions(hwndDlg
, userInfo
, FALSE
);
161 case IDC_USER_NEW_CANNOT_CHANGE
:
162 userInfo
->usri3_flags
^= UF_PASSWD_CANT_CHANGE
;
163 UpdateUserOptions(hwndDlg
, userInfo
, FALSE
);
166 case IDC_USER_NEW_NEVER_EXPIRES
:
167 userInfo
->usri3_flags
^= UF_DONT_EXPIRE_PASSWD
;
168 UpdateUserOptions(hwndDlg
, userInfo
, FALSE
);
171 case IDC_USER_NEW_DISABLED
:
172 userInfo
->usri3_flags
^= UF_ACCOUNTDISABLE
;
176 if (!CheckAccountName(hwndDlg
, IDC_USER_NEW_NAME
, NULL
))
178 SetFocus(GetDlgItem(hwndDlg
, IDC_USER_NEW_NAME
));
179 SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_NAME
, EM_SETSEL
, 0, -1);
183 if (!CheckPasswords(hwndDlg
, IDC_USER_NEW_PASSWORD1
, IDC_USER_NEW_PASSWORD2
))
185 SetDlgItemText(hwndDlg
, IDC_USER_NEW_PASSWORD1
, TEXT(""));
186 SetDlgItemText(hwndDlg
, IDC_USER_NEW_PASSWORD2
, TEXT(""));
190 /* Store the user name */
191 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_NAME
, WM_GETTEXTLENGTH
, 0, 0);
194 userInfo
->usri3_name
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
195 GetDlgItemText(hwndDlg
, IDC_USER_NEW_NAME
, userInfo
->usri3_name
, nLength
+ 1);
198 /* Store the full user name */
199 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_FULL_NAME
, WM_GETTEXTLENGTH
, 0, 0);
202 userInfo
->usri3_full_name
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
203 GetDlgItemText(hwndDlg
, IDC_USER_NEW_FULL_NAME
, userInfo
->usri3_full_name
, nLength
+ 1);
206 /* Store the description */
207 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_DESCRIPTION
, WM_GETTEXTLENGTH
, 0, 0);
210 userInfo
->usri3_comment
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
211 GetDlgItemText(hwndDlg
, IDC_USER_NEW_DESCRIPTION
, userInfo
->usri3_comment
, nLength
+ 1);
214 /* Store the password */
215 nLength
= SendDlgItemMessage(hwndDlg
, IDC_USER_NEW_PASSWORD1
, WM_GETTEXTLENGTH
, 0, 0);
218 userInfo
->usri3_password
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (nLength
+ 1) * sizeof(WCHAR
));
219 GetDlgItemText(hwndDlg
, IDC_USER_NEW_PASSWORD1
, userInfo
->usri3_password
, nLength
+ 1);
222 EndDialog(hwndDlg
, IDOK
);
226 EndDialog(hwndDlg
, IDCANCEL
);
240 UserNew(HWND hwndDlg
)
243 NET_API_STATUS status
;
248 ZeroMemory(&user
, sizeof(USER_INFO_3
));
250 user
.usri3_priv
= USER_PRIV_USER
;
251 user
.usri3_flags
= UF_SCRIPT
;
252 user
.usri3_acct_expires
= TIMEQ_FOREVER
;
253 user
.usri3_max_storage
= USER_MAXSTORAGE_UNLIMITED
;
254 user
.usri3_primary_group_id
= DOMAIN_GROUP_RID_USERS
;
256 user
.usri3_password_expired
= TRUE
;
258 if (DialogBoxParam(hApplet
,
259 MAKEINTRESOURCE(IDD_USER_NEW
),
262 (LPARAM
)&user
) == IDOK
)
265 status
= NetUserAdd(NULL
,
270 status
= NERR_Success
;
272 if (status
!= NERR_Success
)
275 wsprintf(szText
, TEXT("Error: %u"), status
);
276 MessageBox(NULL
, szText
, TEXT("NetUserAdd"), MB_ICONERROR
| MB_OK
);
280 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
282 ZeroMemory(&lvi
, sizeof(lvi
));
283 lvi
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_IMAGE
;
284 lvi
.pszText
= user
.usri3_name
;
286 lvi
.iImage
= (user
.usri3_flags
& UF_ACCOUNTDISABLE
) ? 1 : 0;
287 iItem
= ListView_InsertItem(hwndLV
, &lvi
);
289 ListView_SetItemText(hwndLV
, iItem
, 1,
290 user
.usri3_full_name
);
292 ListView_SetItemText(hwndLV
, iItem
, 2,
297 HeapFree(GetProcessHeap(), 0, user
.usri3_name
);
299 if (user
.usri3_full_name
)
300 HeapFree(GetProcessHeap(), 0, user
.usri3_full_name
);
302 if (user
.usri3_comment
)
303 HeapFree(GetProcessHeap(), 0, user
.usri3_comment
);
305 if (user
.usri3_password
)
306 HeapFree(GetProcessHeap(), 0, user
.usri3_password
);
311 UserRename(HWND hwndDlg
)
316 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
320 nItem
= ListView_GetNextItem(hwndLV
, -1, LVNI_SELECTED
);
323 (void)ListView_EditLabel(hwndLV
, nItem
);
329 UserDelete(HWND hwndDlg
)
331 TCHAR szUserName
[UNLEN
];
335 NET_API_STATUS status
;
337 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
338 nItem
= ListView_GetNextItem(hwndLV
, -1, LVNI_SELECTED
);
342 /* Get the new user name */
343 ListView_GetItemText(hwndLV
,
348 /* Display a warning message because the delete operation cannot be reverted */
349 wsprintf(szText
, TEXT("Do you really want to delete the user \"%s\"?"), szUserName
);
350 if (MessageBox(NULL
, szText
, TEXT("User Accounts"), MB_ICONWARNING
| MB_YESNO
) == IDNO
)
353 /* Delete the user */
355 status
= NetUserDel(NULL
, szUserName
);
357 status
= NERR_Success
;
359 if (status
!= NERR_Success
)
362 wsprintf(szText
, TEXT("Error: %u"), status
);
363 MessageBox(NULL
, szText
, TEXT("NetUserDel"), MB_ICONERROR
| MB_OK
);
367 /* Delete the user from the list */
368 (void)ListView_DeleteItem(hwndLV
, nItem
);
375 SetUsersListColumns(HWND hwndListView
)
381 GetClientRect(hwndListView
, &rect
);
383 memset(&column
, 0x00, sizeof(column
));
384 column
.mask
=LVCF_FMT
| LVCF_WIDTH
| LVCF_SUBITEM
| LVCF_TEXT
;
385 column
.fmt
=LVCFMT_LEFT
;
386 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.25);
388 LoadString(hApplet
, IDS_NAME
, szStr
, sizeof(szStr
) / sizeof(szStr
[0]));
389 column
.pszText
= szStr
;
390 (void)ListView_InsertColumn(hwndListView
, 0, &column
);
392 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.50);
394 LoadString(hApplet
, IDS_FULLNAME
, szStr
, sizeof(szStr
) / sizeof(szStr
[0]));
395 column
.pszText
= szStr
;
396 (void)ListView_InsertColumn(hwndListView
, 1, &column
);
398 column
.cx
= (INT
)((rect
.right
- rect
.left
) * 0.25);
400 LoadString(hApplet
, IDS_DESCRIPTION
, szStr
, sizeof(szStr
) / sizeof(szStr
[0]));
401 column
.pszText
= szStr
;
402 (void)ListView_InsertColumn(hwndListView
, 2, &column
);
407 UpdateUsersList(HWND hwndListView
)
409 NET_API_STATUS netStatus
;
410 PUSER_INFO_20 pBuffer
;
413 DWORD resume_handle
= 0;
421 netStatus
= NetUserEnum(NULL
, 20, FILTER_NORMAL_ACCOUNT
,
424 &totalentries
, &resume_handle
);
425 if (netStatus
!= NERR_Success
&& netStatus
!= ERROR_MORE_DATA
)
428 for (i
= 0; i
< entriesread
; i
++)
430 memset(&lvi
, 0x00, sizeof(lvi
));
431 lvi
.mask
= LVIF_TEXT
| LVIF_STATE
| LVIF_IMAGE
;
432 lvi
.pszText
= pBuffer
[i
].usri20_name
;
434 lvi
.iImage
= (pBuffer
[i
].usri20_flags
& UF_ACCOUNTDISABLE
) ? 1 : 0;
435 iItem
= ListView_InsertItem(hwndListView
, &lvi
);
437 ListView_SetItemText(hwndListView
, iItem
, 1,
438 pBuffer
[i
].usri20_full_name
);
440 ListView_SetItemText(hwndListView
, iItem
, 2,
441 pBuffer
[i
].usri20_comment
);
444 NetApiBufferFree(pBuffer
);
446 /* No more data left */
447 if (netStatus
!= ERROR_MORE_DATA
)
455 OnInitDialog(HWND hwndDlg
)
461 /* Create the image list */
462 hImgList
= ImageList_Create(16, 16, ILC_COLOR8
| ILC_MASK
, 5, 5);
463 hIcon
= LoadImage(hApplet
, MAKEINTRESOURCE(IDI_USER
), IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
464 ImageList_AddIcon(hImgList
, hIcon
);
465 hIcon
= LoadImage(hApplet
, MAKEINTRESOURCE(IDI_LOCKED_USER
), IMAGE_ICON
, 16, 16, LR_DEFAULTCOLOR
);
466 ImageList_AddIcon(hImgList
, hIcon
);
469 hwndListView
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
471 (VOID
)ListView_SetImageList(hwndListView
, hImgList
, LVSIL_SMALL
);
473 (void)ListView_SetExtendedListViewStyle(hwndListView
, LVS_EX_FULLROWSELECT
);
475 SetUsersListColumns(hwndListView
);
477 UpdateUsersList(hwndListView
);
482 OnBeginLabelEdit(LPNMLVDISPINFO pnmv
)
486 hwndEdit
= ListView_GetEditControl(pnmv
->hdr
.hwndFrom
);
487 if (hwndEdit
== NULL
)
490 SendMessage(hwndEdit
, EM_SETLIMITTEXT
, 20, 0);
497 OnEndLabelEdit(LPNMLVDISPINFO pnmv
)
499 TCHAR szOldUserName
[UNLEN
];
500 TCHAR szNewUserName
[UNLEN
];
502 NET_API_STATUS status
;
504 /* Leave, if there is no valid listview item */
505 if (pnmv
->item
.iItem
== -1)
508 /* Get the new user name */
509 ListView_GetItemText(pnmv
->hdr
.hwndFrom
,
514 /* Leave, if the user canceled the edit action */
515 if (pnmv
->item
.pszText
== NULL
)
518 /* Get the new user name */
519 lstrcpy(szNewUserName
, pnmv
->item
.pszText
);
521 /* Leave, if the user name was not changed */
522 if (lstrcmp(szOldUserName
, szNewUserName
) == 0)
525 /* Check the user name for illegal characters */
526 if (!CheckAccountName(NULL
, 0, szNewUserName
))
529 /* Change the user name */
530 useri0
.usri0_name
= szNewUserName
;
533 status
= NetUserSetInfo(NULL
, szOldUserName
, 0, (LPBYTE
)&useri0
, NULL
);
535 status
= NERR_Success
;
537 if (status
!= NERR_Success
)
540 wsprintf(szText
, TEXT("Error: %u"), status
);
541 MessageBox(NULL
, szText
, TEXT("NetUserSetInfo"), MB_ICONERROR
| MB_OK
);
545 /* Update the listview item */
546 ListView_SetItemText(pnmv
->hdr
.hwndFrom
,
555 OnNotify(HWND hwndDlg
, PUSER_DATA pUserData
, NMHDR
*phdr
)
557 LPNMLISTVIEW lpnmlv
= (LPNMLISTVIEW
)phdr
;
559 switch (phdr
->idFrom
)
565 pUserData
->iCurrentItem
= lpnmlv
->iItem
;
569 if (lpnmlv
->iItem
!= -1)
573 uItem
= GetMenuDefaultItem(GetSubMenu(pUserData
->hPopupMenu
, 1),
575 if (uItem
!= (UINT
)-1)
576 SendMessage(hwndDlg
, WM_COMMAND
, MAKEWPARAM(uItem
, 0), 0);
581 ClientToScreen(GetDlgItem(hwndDlg
, IDC_USERS_LIST
), &lpnmlv
->ptAction
);
582 TrackPopupMenu(GetSubMenu(pUserData
->hPopupMenu
, (lpnmlv
->iItem
== -1) ? 0 : 1),
583 TPM_LEFTALIGN
, lpnmlv
->ptAction
.x
, lpnmlv
->ptAction
.y
, 0, hwndDlg
, NULL
);
586 case LVN_BEGINLABELEDIT
:
587 return OnBeginLabelEdit((LPNMLVDISPINFO
)phdr
);
589 case LVN_ENDLABELEDIT
:
590 return OnEndLabelEdit((LPNMLVDISPINFO
)phdr
);
600 UpdateUserProperties(HWND hwndDlg
)
602 TCHAR szUserName
[UNLEN
];
605 NET_API_STATUS status
;
606 PUSER_INFO_2 pUserInfo
= NULL
;
609 hwndLV
= GetDlgItem(hwndDlg
, IDC_USERS_LIST
);
610 iItem
= ListView_GetNextItem(hwndLV
, -1, LVNI_SELECTED
);
614 /* Get the new user name */
615 ListView_GetItemText(hwndLV
,
620 status
= NetUserGetInfo(NULL
, szUserName
, 2, (LPBYTE
*)&pUserInfo
);
622 memset(&lvi
, 0x00, sizeof(lvi
));
625 lvi
.mask
= LVIF_IMAGE
;
626 lvi
.iImage
= (pUserInfo
->usri2_flags
& UF_ACCOUNTDISABLE
) ? 1 : 0;
627 (void)ListView_SetItem(hwndLV
, &lvi
);
629 ListView_SetItemText(hwndLV
, iItem
, 1,
630 pUserInfo
->usri2_full_name
);
632 ListView_SetItemText(hwndLV
, iItem
, 2,
633 pUserInfo
->usri2_comment
);
635 NetApiBufferFree(pUserInfo
);
640 UsersPageProc(HWND hwndDlg
,
645 PUSER_DATA pUserData
;
647 UNREFERENCED_PARAMETER(wParam
);
649 pUserData
= (PUSER_DATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
654 pUserData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(USER_DATA
));
655 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pUserData
);
657 pUserData
->hPopupMenu
= LoadMenu(hApplet
, MAKEINTRESOURCE(IDM_POPUP_USER
));
659 OnInitDialog(hwndDlg
);
660 SetMenuDefaultItem(GetSubMenu(pUserData
->hPopupMenu
, 1),
666 switch (LOWORD(wParam
))
668 case IDM_USER_CHANGE_PASSWORD
:
669 DialogBoxParam(hApplet
,
670 MAKEINTRESOURCE(IDD_CHANGE_PASSWORD
),
672 ChangePasswordDlgProc
,
676 case IDM_USER_RENAME
:
684 case IDM_USER_DELETE
:
688 case IDM_USER_PROPERTIES
:
689 if (UserProperties(hwndDlg
))
691 UpdateUserProperties(hwndDlg
);
698 return OnNotify(hwndDlg
, pUserData
, (NMHDR
*)lParam
);
701 DestroyMenu(pUserData
->hPopupMenu
);
702 HeapFree(GetProcessHeap(), 0, pUserData
);