[CRT] Massively improve performance of rand_s
[reactos.git] / 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 typedef struct _PROFILE_USER_DATA
22 {
23 TCHAR szUserName[1];
24 } PROFILE_USER_DATA, *PPROFILE_USER_DATA;
25
26 typedef struct _MEMBERSHIP_USER_DATA
27 {
28 PLOCALGROUP_USERS_INFO_0 pGroupData;
29 DWORD dwGroupCount;
30 TCHAR szUserName[1];
31 } MEMBERSHIP_USER_DATA, *PMEMBERSHIP_USER_DATA;
32
33
34 static VOID
35 GetUserProfileData(HWND hwndDlg,
36 PPROFILE_USER_DATA pUserData)
37 {
38 PUSER_INFO_3 userInfo = NULL;
39 NET_API_STATUS status;
40 BOOL bLocal;
41 TCHAR szDrive[8];
42 INT i;
43 INT nSel;
44
45 status = NetUserGetInfo(NULL, pUserData->szUserName, 3, (LPBYTE*)&userInfo);
46 if (status != NERR_Success)
47 return;
48
49 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_PATH, userInfo->usri3_profile);
50 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_SCRIPT, userInfo->usri3_script_path);
51
52
53 bLocal = (userInfo->usri3_home_dir_drive == NULL) ||
54 (_tcslen(userInfo->usri3_home_dir_drive) == 0);
55 CheckRadioButton(hwndDlg, IDC_USER_PROFILE_LOCAL, IDC_USER_PROFILE_REMOTE,
56 bLocal ? IDC_USER_PROFILE_LOCAL : IDC_USER_PROFILE_REMOTE);
57
58 for (i = 0; i < 26; i++)
59 {
60 wsprintf(szDrive, _T("%c:"), (TCHAR)('A' + i));
61 nSel = SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
62 CB_INSERTSTRING, -1, (LPARAM)szDrive);
63 }
64
65 if (bLocal)
66 {
67 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH, userInfo->usri3_home_dir);
68 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), FALSE);
69 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), FALSE);
70 }
71 else
72 {
73 SetDlgItemText(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH, userInfo->usri3_home_dir);
74 nSel = SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
75 CB_FINDSTRINGEXACT, -1, (LPARAM)userInfo->usri3_home_dir_drive);
76 }
77
78 SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE),
79 CB_SETCURSEL, nSel, 0);
80
81 NetApiBufferFree(userInfo);
82 }
83
84
85 static BOOL
86 SetUserProfileData(HWND hwndDlg,
87 PPROFILE_USER_DATA pUserData)
88 {
89 PUSER_INFO_3 pUserInfo = NULL;
90 NET_API_STATUS status;
91 DWORD dwIndex;
92 INT nIndex;
93
94 NetUserGetInfo(NULL, pUserData->szUserName, 3, (LPBYTE*)&pUserInfo);
95
96 /* Get the profile path */
97 pUserInfo->usri3_profile = GetDlgItemTextAlloc(hwndDlg, IDC_USER_PROFILE_PATH);
98
99 /* Get the script path */
100 pUserInfo->usri3_script_path = GetDlgItemTextAlloc(hwndDlg, IDC_USER_PROFILE_SCRIPT);
101
102 if (IsDlgButtonChecked(hwndDlg, IDC_USER_PROFILE_LOCAL) == BST_CHECKED)
103 {
104 /* Local home directory */
105 pUserInfo->usri3_home_dir = GetDlgItemTextAlloc(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH);
106 }
107 else
108 {
109 /* Remote home directory */
110 pUserInfo->usri3_home_dir = GetDlgItemTextAlloc(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH);
111
112 nIndex = SendMessage(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), CB_GETCURSEL, 0, 0);
113 if (nIndex != CB_ERR)
114 {
115 pUserInfo->usri3_home_dir_drive =
116 GetComboBoxLBTextAlloc(hwndDlg, IDC_USER_PROFILE_DRIVE, nIndex);
117 }
118 else
119 {
120 pUserInfo->usri3_home_dir_drive =
121 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TCHAR));
122 }
123 }
124
125 status = NetUserSetInfo(NULL, pUserData->szUserName, 3, (LPBYTE)pUserInfo, &dwIndex);
126 if (status != NERR_Success)
127 {
128 ERR("NetUserSetInfo failed. Status: %lu Index: %lu", status, dwIndex);
129 }
130
131 HeapFree(GetProcessHeap(), 0, pUserInfo->usri3_profile);
132 HeapFree(GetProcessHeap(), 0, pUserInfo->usri3_script_path);
133 HeapFree(GetProcessHeap(), 0, pUserInfo->usri3_home_dir);
134 HeapFree(GetProcessHeap(), 0, pUserInfo->usri3_home_dir_drive);
135
136 NetApiBufferFree(pUserInfo);
137
138 return (status == NERR_Success);
139 }
140
141
142 INT_PTR CALLBACK
143 UserProfilePageProc(HWND hwndDlg,
144 UINT uMsg,
145 WPARAM wParam,
146 LPARAM lParam)
147 {
148 PPROFILE_USER_DATA pUserData;
149
150 UNREFERENCED_PARAMETER(lParam);
151 UNREFERENCED_PARAMETER(wParam);
152 UNREFERENCED_PARAMETER(hwndDlg);
153
154 pUserData= (PPROFILE_USER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
155
156 switch (uMsg)
157 {
158 case WM_INITDIALOG:
159 pUserData = (PPROFILE_USER_DATA)HeapAlloc(GetProcessHeap(),
160 HEAP_ZERO_MEMORY,
161 sizeof(PROFILE_USER_DATA) +
162 lstrlen((LPTSTR)((PROPSHEETPAGE *)lParam)->lParam) * sizeof(TCHAR));
163 lstrcpy(pUserData->szUserName, (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
164
165 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pUserData);
166
167 GetUserProfileData(hwndDlg,
168 pUserData);
169 break;
170
171 case WM_COMMAND:
172 switch (LOWORD(wParam))
173 {
174 case IDC_USER_PROFILE_PATH:
175 case IDC_USER_PROFILE_SCRIPT:
176 if (HIWORD(wParam) == EN_CHANGE)
177 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
178 break;
179
180 case IDC_USER_PROFILE_LOCAL:
181 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH), TRUE);
182 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), FALSE);
183 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), FALSE);
184 break;
185
186 case IDC_USER_PROFILE_REMOTE:
187 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_LOCAL_PATH), FALSE);
188 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_DRIVE), TRUE);
189 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_PROFILE_REMOTE_PATH), TRUE);
190 break;
191 }
192 break;
193
194 case WM_DESTROY:
195 HeapFree(GetProcessHeap(), 0, pUserData);
196 break;
197
198 case WM_NOTIFY:
199 if (((LPPSHNOTIFY)lParam)->hdr.code == PSN_APPLY)
200 {
201 SetUserProfileData(hwndDlg, pUserData);
202 return TRUE;
203 }
204 break;
205 }
206
207 return FALSE;
208 }
209
210
211 static VOID
212 GetUserMembershipData(HWND hwndDlg, PMEMBERSHIP_USER_DATA pUserData)
213 {
214 NET_API_STATUS status;
215 DWORD dwTotal;
216 DWORD i;
217 HIMAGELIST hImgList;
218 HICON hIcon;
219 LV_ITEM lvi;
220 HWND hwndLV;
221 LV_COLUMN column;
222 RECT rect;
223
224
225 hwndLV = GetDlgItem(hwndDlg, IDC_USER_MEMBERSHIP_LIST);
226
227 /* Create the image list */
228 hImgList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 5, 5);
229 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_GROUP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
230 ImageList_AddIcon(hImgList, hIcon);
231 DestroyIcon(hIcon);
232 (void)ListView_SetImageList(hwndLV, hImgList, LVSIL_SMALL);
233
234 /* Set the list column */
235 GetClientRect(hwndLV, &rect);
236
237 memset(&column, 0x00, sizeof(column));
238 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
239 column.fmt = LVCFMT_LEFT;
240 column.cx = (INT)(rect.right - rect.left);
241 column.iSubItem = 0;
242 (void)ListView_InsertColumn(hwndLV, 0, &column);
243
244
245 status = NetUserGetLocalGroups(NULL, pUserData->szUserName, 0, 0,
246 (LPBYTE*)&pUserData->pGroupData,
247 MAX_PREFERRED_LENGTH,
248 &pUserData->dwGroupCount,
249 &dwTotal);
250 if (status != NERR_Success)
251 return;
252
253 for (i = 0; i < pUserData->dwGroupCount; i++)
254 {
255 ZeroMemory(&lvi, sizeof(lvi));
256 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
257 lvi.pszText = pUserData->pGroupData[i].lgrui0_name;
258 lvi.state = 0;
259 lvi.iImage = 0;
260
261 (void)ListView_InsertItem(hwndLV, &lvi);
262 }
263 }
264
265
266 static VOID
267 RemoveGroupFromUser(HWND hwndDlg,
268 PMEMBERSHIP_USER_DATA pUserData)
269 {
270 TCHAR szGroupName[UNLEN + 1];
271 TCHAR szText[256];
272 LOCALGROUP_MEMBERS_INFO_3 memberInfo;
273 HWND hwndLV;
274 INT nItem;
275 NET_API_STATUS status;
276
277 hwndLV = GetDlgItem(hwndDlg, IDC_USER_MEMBERSHIP_LIST);
278 nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
279 if (nItem == -1)
280 return;
281
282 /* Get the new user name */
283 ListView_GetItemText(hwndLV,
284 nItem, 0,
285 szGroupName,
286 UNLEN + 1);
287
288 /* Display a warning message because the remove operation cannot be reverted */
289 wsprintf(szText, TEXT("Do you really want to remove the user \"%s\" from the group \"%s\"?"),
290 pUserData->szUserName, szGroupName);
291 if (MessageBox(NULL, szText, TEXT("User Accounts"), MB_ICONWARNING | MB_YESNO) == IDNO)
292 return;
293
294 memberInfo.lgrmi3_domainandname = pUserData->szUserName;
295
296 status = NetLocalGroupDelMembers(NULL, szGroupName,
297 3, (LPBYTE)&memberInfo, 1);
298 if (status != NERR_Success)
299 {
300 TCHAR szText[256];
301 wsprintf(szText, TEXT("Error: %u"), status);
302 MessageBox(NULL, szText, TEXT("NetLocalGroupDelMembers"), MB_ICONERROR | MB_OK);
303 return;
304 }
305
306 (void)ListView_DeleteItem(hwndLV, nItem);
307
308 if (ListView_GetItemCount(hwndLV) == 0)
309 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_MEMBERSHIP_REMOVE), FALSE);
310 }
311
312
313 static VOID
314 InitUserGroupsList(HWND hwndDlg)
315 {
316 HWND hwndLV;
317 LV_COLUMN column;
318 RECT rect;
319 TCHAR szStr[32];
320
321 NET_API_STATUS netStatus;
322 PLOCALGROUP_INFO_1 pBuffer;
323 DWORD entriesread;
324 DWORD totalentries;
325 DWORD_PTR resume_handle = 0;
326 DWORD i;
327 LV_ITEM lvi;
328 INT iItem;
329
330 HIMAGELIST hImgList;
331 HICON hIcon;
332
333 hwndLV = GetDlgItem(hwndDlg, IDC_USER_ADD_MEMBERSHIP_LIST);
334 GetClientRect(hwndLV, &rect);
335
336 hImgList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 5, 5);
337 hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_GROUP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
338 ImageList_AddIcon(hImgList, hIcon);
339 DestroyIcon(hIcon);
340
341 (void)ListView_SetImageList(hwndLV, hImgList, LVSIL_SMALL);
342 (void)ListView_SetExtendedListViewStyle(hwndLV, LVS_EX_FULLROWSELECT);
343
344 memset(&column, 0x00, sizeof(column));
345 column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
346 column.fmt = LVCFMT_LEFT;
347 column.cx = (INT)((rect.right - rect.left) * 0.40);
348 column.iSubItem = 0;
349 LoadString(hApplet, IDS_NAME, szStr, sizeof(szStr) / sizeof(szStr[0]));
350 column.pszText = szStr;
351 (void)ListView_InsertColumn(hwndLV, 0, &column);
352
353 column.cx = (INT)((rect.right - rect.left) * 0.60);
354 column.iSubItem = 1;
355 LoadString(hApplet, IDS_DESCRIPTION, szStr, sizeof(szStr) / sizeof(szStr[0]));
356 column.pszText = szStr;
357 (void)ListView_InsertColumn(hwndLV, 1, &column);
358
359 for (;;)
360 {
361 netStatus = NetLocalGroupEnum(NULL, 1, (LPBYTE*)&pBuffer,
362 1024, &entriesread,
363 &totalentries, &resume_handle);
364 if (netStatus != NERR_Success && netStatus != ERROR_MORE_DATA)
365 break;
366
367 for (i = 0; i < entriesread; i++)
368 {
369 memset(&lvi, 0x00, sizeof(lvi));
370 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
371 lvi.pszText = pBuffer[i].lgrpi1_name;
372 lvi.state = 0;
373 lvi.iImage = 0;
374 iItem = ListView_InsertItem(hwndLV, &lvi);
375
376 ListView_SetItemText(hwndLV, iItem, 1,
377 pBuffer[i].lgrpi1_comment);
378 }
379
380 NetApiBufferFree(pBuffer);
381
382 /* No more data left */
383 if (netStatus != ERROR_MORE_DATA)
384 break;
385 }
386 }
387
388
389 static BOOL
390 AddSelectedGroupsToUser(HWND hwndDlg,
391 PMEMBERSHIP_USER_DATA pUserData)
392 {
393 HWND hwndLV;
394 INT nItem;
395 TCHAR szGroupName[UNLEN + 1];
396 BOOL bResult = FALSE;
397 BOOL bFound;
398 DWORD i;
399 LOCALGROUP_MEMBERS_INFO_3 memberInfo;
400 NET_API_STATUS status;
401
402 hwndLV = GetDlgItem(hwndDlg, IDC_USER_ADD_MEMBERSHIP_LIST);
403
404 if (ListView_GetSelectedCount(hwndLV) > 0)
405 {
406 nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
407 while (nItem != -1)
408 {
409 /* Get the new user name */
410 ListView_GetItemText(hwndLV,
411 nItem, 0,
412 szGroupName,
413 UNLEN + 1);
414
415 bFound = FALSE;
416 for (i = 0; i < pUserData->dwGroupCount; i++)
417 {
418 if (_tcscmp(pUserData->pGroupData[i].lgrui0_name, szGroupName) == 0)
419 bFound = TRUE;
420 }
421
422 if (!bFound)
423 {
424 memberInfo.lgrmi3_domainandname = pUserData->szUserName;
425
426 status = NetLocalGroupAddMembers(NULL, szGroupName, 3,
427 (LPBYTE)&memberInfo, 1);
428 if (status == NERR_Success)
429 {
430 TRACE("Selected group: %s", dbgstrx(szGroupName));
431 bResult = TRUE;
432 }
433 else
434 {
435 TCHAR szText[256];
436 wsprintf(szText, TEXT("Error: %u"), status);
437 MessageBox(NULL, szText, TEXT("NetLocalGroupAddMembers"), MB_ICONERROR | MB_OK);
438 }
439 }
440
441 nItem = ListView_GetNextItem(hwndLV, nItem, LVNI_SELECTED);
442 }
443 }
444
445 return bResult;
446 }
447
448
449 INT_PTR CALLBACK
450 AddGroupToUserDlgProc(HWND hwndDlg,
451 UINT uMsg,
452 WPARAM wParam,
453 LPARAM lParam)
454 {
455 PMEMBERSHIP_USER_DATA pUserData;
456
457 UNREFERENCED_PARAMETER(wParam);
458
459 pUserData= (PMEMBERSHIP_USER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
460
461 switch (uMsg)
462 {
463 case WM_INITDIALOG:
464 pUserData= (PMEMBERSHIP_USER_DATA)lParam;
465 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pUserData);
466 InitUserGroupsList(hwndDlg);
467 break;
468
469 case WM_COMMAND:
470 switch (LOWORD(wParam))
471 {
472 case IDOK:
473 if (AddSelectedGroupsToUser(hwndDlg, pUserData))
474 EndDialog(hwndDlg, IDOK);
475 else
476 EndDialog(hwndDlg, IDCANCEL);
477 break;
478
479 case IDCANCEL:
480 EndDialog(hwndDlg, IDCANCEL);
481 break;
482 }
483 break;
484
485 default:
486 return FALSE;
487 }
488
489 return TRUE;
490 }
491
492
493 static VOID
494 AddGroupToUser(HWND hwndDlg,
495 PMEMBERSHIP_USER_DATA pUserData)
496 {
497 HWND hwndLV;
498 NET_API_STATUS status;
499 DWORD i;
500 DWORD dwTotal;
501 LV_ITEM lvi;
502
503 if (DialogBoxParam(hApplet,
504 MAKEINTRESOURCE(IDD_USER_ADD_MEMBERSHIP),
505 hwndDlg,
506 AddGroupToUserDlgProc,
507 (LPARAM)pUserData) == IDOK)
508 {
509 // TODO: Update Membership list!
510 hwndLV = GetDlgItem(hwndDlg, IDC_USER_MEMBERSHIP_LIST);
511
512 if (pUserData->pGroupData)
513 NetApiBufferFree(pUserData->pGroupData);
514
515 (void)ListView_DeleteAllItems(hwndLV);
516
517 status = NetUserGetLocalGroups(NULL, pUserData->szUserName, 0, 0,
518 (LPBYTE*)&pUserData->pGroupData,
519 MAX_PREFERRED_LENGTH,
520 &pUserData->dwGroupCount,
521 &dwTotal);
522 if (status != NERR_Success)
523 return;
524
525 for (i = 0; i < pUserData->dwGroupCount; i++)
526 {
527 ZeroMemory(&lvi, sizeof(lvi));
528 lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
529 lvi.pszText = pUserData->pGroupData[i].lgrui0_name;
530 lvi.state = 0;
531 lvi.iImage = 0;
532
533 (void)ListView_InsertItem(hwndLV, &lvi);
534 }
535 }
536 }
537
538
539 static BOOL
540 OnUserPropSheetNotify(HWND hwndDlg,
541 PMEMBERSHIP_USER_DATA pUserData,
542 LPARAM lParam)
543 {
544 LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam;
545
546 switch (((LPNMHDR)lParam)->idFrom)
547 {
548 case IDC_USER_MEMBERSHIP_LIST:
549 switch (((LPNMHDR)lParam)->code)
550 {
551 case NM_CLICK:
552 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_MEMBERSHIP_REMOVE), (lpnmlv->iItem != -1));
553 break;
554
555 case LVN_KEYDOWN:
556 if (((LPNMLVKEYDOWN)lParam)->wVKey == VK_DELETE)
557 {
558 RemoveGroupFromUser(hwndDlg, pUserData);
559 }
560 break;
561
562 }
563 break;
564 }
565
566 return FALSE;
567 }
568
569
570 INT_PTR CALLBACK
571 UserMembershipPageProc(HWND hwndDlg,
572 UINT uMsg,
573 WPARAM wParam,
574 LPARAM lParam)
575 {
576 PMEMBERSHIP_USER_DATA pUserData;
577
578 UNREFERENCED_PARAMETER(lParam);
579 UNREFERENCED_PARAMETER(wParam);
580 UNREFERENCED_PARAMETER(hwndDlg);
581
582 pUserData= (PMEMBERSHIP_USER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
583
584 switch (uMsg)
585 {
586 case WM_INITDIALOG:
587 pUserData = (PMEMBERSHIP_USER_DATA)HeapAlloc(GetProcessHeap(),
588 HEAP_ZERO_MEMORY,
589 sizeof(MEMBERSHIP_USER_DATA) +
590 lstrlen((LPTSTR)((PROPSHEETPAGE *)lParam)->lParam) * sizeof(TCHAR));
591 lstrcpy(pUserData->szUserName, (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
592
593 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pUserData);
594
595 GetUserMembershipData(hwndDlg, pUserData);
596 break;
597
598 case WM_COMMAND:
599 switch (LOWORD(wParam))
600 {
601 case IDC_USER_MEMBERSHIP_ADD:
602 AddGroupToUser(hwndDlg, pUserData);
603 break;
604
605 case IDC_USER_MEMBERSHIP_REMOVE:
606 RemoveGroupFromUser(hwndDlg, pUserData);
607 break;
608 }
609 break;
610
611 case WM_NOTIFY:
612 if (((LPPSHNOTIFY)lParam)->hdr.code == PSN_APPLY)
613 {
614 return TRUE;
615 }
616 else
617 {
618 return OnUserPropSheetNotify(hwndDlg, pUserData, lParam);
619 }
620 break;
621
622
623 case WM_DESTROY:
624 if (pUserData->pGroupData)
625 NetApiBufferFree(pUserData->pGroupData);
626
627 HeapFree(GetProcessHeap(), 0, pUserData);
628 break;
629 }
630
631 return FALSE;
632 }
633
634
635 static VOID
636 UpdateUserOptions(HWND hwndDlg,
637 PGENERAL_USER_DATA pUserData,
638 BOOL bInit)
639 {
640 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_CANNOT_CHANGE),
641 !pUserData->dwPasswordExpired);
642 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_NEVER_EXPIRES),
643 !pUserData->dwPasswordExpired);
644 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_FORCE_CHANGE),
645 (pUserData->dwFlags & (UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD)) == 0);
646
647 EnableWindow(GetDlgItem(hwndDlg, IDC_USER_GENERAL_LOCKED),
648 (pUserData->dwFlags & UF_LOCKOUT) != 0);
649
650 if (bInit)
651 {
652 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_FORCE_CHANGE,
653 pUserData->dwPasswordExpired ? BST_CHECKED : BST_UNCHECKED);
654
655 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_CANNOT_CHANGE,
656 (pUserData->dwFlags & UF_PASSWD_CANT_CHANGE) ? BST_CHECKED : BST_UNCHECKED);
657
658 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_NEVER_EXPIRES,
659 (pUserData->dwFlags & UF_DONT_EXPIRE_PASSWD) ? BST_CHECKED : BST_UNCHECKED);
660
661 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_DISABLED,
662 (pUserData->dwFlags & UF_ACCOUNTDISABLE) ? BST_CHECKED : BST_UNCHECKED);
663
664 CheckDlgButton(hwndDlg, IDC_USER_GENERAL_LOCKED,
665 (pUserData->dwFlags & UF_LOCKOUT) ? BST_CHECKED : BST_UNCHECKED);
666 }
667 }
668
669
670 static VOID
671 GetUserGeneralData(HWND hwndDlg,
672 PGENERAL_USER_DATA pUserData)
673 {
674 PUSER_INFO_3 pUserInfo = NULL;
675
676 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_NAME, pUserData->szUserName);
677
678 NetUserGetInfo(NULL, pUserData->szUserName, 3, (LPBYTE*)&pUserInfo);
679
680 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_FULL_NAME, pUserInfo->usri3_full_name);
681 SetDlgItemText(hwndDlg, IDC_USER_GENERAL_DESCRIPTION, pUserInfo->usri3_comment);
682
683 pUserData->dwFlags = pUserInfo->usri3_flags;
684 pUserData->dwPasswordExpired = pUserInfo->usri3_password_expired;
685
686 NetApiBufferFree(pUserInfo);
687
688 UpdateUserOptions(hwndDlg, pUserData, TRUE);
689 }
690
691
692 static BOOL
693 SetUserGeneralData(HWND hwndDlg,
694 PGENERAL_USER_DATA pUserData)
695 {
696 PUSER_INFO_3 pUserInfo = NULL;
697 NET_API_STATUS status;
698 DWORD dwIndex;
699
700 NetUserGetInfo(NULL, pUserData->szUserName, 3, (LPBYTE*)&pUserInfo);
701
702 pUserInfo->usri3_flags =
703 (pUserData->dwFlags & VALID_GENERAL_FLAGS) |
704 (pUserInfo->usri3_flags & ~VALID_GENERAL_FLAGS);
705
706 pUserInfo->usri3_password_expired = pUserData->dwPasswordExpired;
707
708 /* Get full name */
709 pUserInfo->usri3_full_name = GetDlgItemTextAlloc(hwndDlg, IDC_USER_GENERAL_FULL_NAME);
710
711 /* Get desciption */
712 pUserInfo->usri3_comment = GetDlgItemTextAlloc(hwndDlg, IDC_USER_GENERAL_DESCRIPTION);
713
714 status = NetUserSetInfo(NULL, pUserData->szUserName, 3, (LPBYTE)pUserInfo, &dwIndex);
715 if (status != NERR_Success)
716 {
717 ERR("NetUserSetInfo failed. Status: %lu Index: %lu", status, dwIndex);
718 }
719
720 HeapFree(GetProcessHeap(), 0, pUserInfo->usri3_full_name);
721 HeapFree(GetProcessHeap(), 0, pUserInfo->usri3_comment);
722
723 NetApiBufferFree(pUserInfo);
724
725 return (status == NERR_Success);
726 }
727
728
729 INT_PTR CALLBACK
730 UserGeneralPageProc(HWND hwndDlg,
731 UINT uMsg,
732 WPARAM wParam,
733 LPARAM lParam)
734 {
735 PGENERAL_USER_DATA pUserData;
736
737 UNREFERENCED_PARAMETER(lParam);
738 UNREFERENCED_PARAMETER(wParam);
739 UNREFERENCED_PARAMETER(hwndDlg);
740
741 pUserData= (PGENERAL_USER_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
742
743 switch (uMsg)
744 {
745 case WM_INITDIALOG:
746 pUserData = (PGENERAL_USER_DATA)HeapAlloc(GetProcessHeap(),
747 HEAP_ZERO_MEMORY,
748 sizeof(GENERAL_USER_DATA) +
749 lstrlen((LPTSTR)((PROPSHEETPAGE *)lParam)->lParam) * sizeof(TCHAR));
750 lstrcpy(pUserData->szUserName, (LPTSTR)((PROPSHEETPAGE *)lParam)->lParam);
751
752 SetWindowLongPtr(hwndDlg, DWLP_USER, (INT_PTR)pUserData);
753
754 GetUserGeneralData(hwndDlg,
755 pUserData);
756 break;
757
758 case WM_COMMAND:
759 switch (LOWORD(wParam))
760 {
761 case IDC_USER_GENERAL_FULL_NAME:
762 case IDC_USER_GENERAL_DESCRIPTION:
763 if (HIWORD(wParam) == EN_CHANGE)
764 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
765 break;
766
767 case IDC_USER_GENERAL_FORCE_CHANGE:
768 pUserData->dwPasswordExpired = !pUserData->dwPasswordExpired;
769 UpdateUserOptions(hwndDlg, pUserData, FALSE);
770 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
771 break;
772
773 case IDC_USER_GENERAL_CANNOT_CHANGE:
774 pUserData->dwFlags ^= UF_PASSWD_CANT_CHANGE;
775 UpdateUserOptions(hwndDlg, pUserData, FALSE);
776 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
777 break;
778
779 case IDC_USER_GENERAL_NEVER_EXPIRES:
780 pUserData->dwFlags ^= UF_DONT_EXPIRE_PASSWD;
781 UpdateUserOptions(hwndDlg, pUserData, FALSE);
782 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
783 break;
784
785 case IDC_USER_GENERAL_DISABLED:
786 pUserData->dwFlags ^= UF_ACCOUNTDISABLE;
787 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
788 break;
789
790 case IDC_USER_GENERAL_LOCKED:
791 pUserData->dwFlags ^= UF_LOCKOUT;
792 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
793 break;
794 }
795 break;
796
797 case WM_NOTIFY:
798 if (((LPPSHNOTIFY)lParam)->hdr.code == PSN_APPLY)
799 {
800 SetUserGeneralData(hwndDlg, pUserData);
801 return TRUE;
802 }
803 break;
804
805 case WM_DESTROY:
806 HeapFree(GetProcessHeap(), 0, pUserData);
807 break;
808 }
809
810 return FALSE;
811 }
812
813
814 static VOID
815 InitUserPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc, LPTSTR pszUser)
816 {
817 ZeroMemory(psp, sizeof(PROPSHEETPAGE));
818 psp->dwSize = sizeof(PROPSHEETPAGE);
819 psp->dwFlags = PSP_DEFAULT;
820 psp->hInstance = hApplet;
821 psp->pszTemplate = MAKEINTRESOURCE(idDlg);
822 psp->pfnDlgProc = DlgProc;
823 psp->lParam = (LPARAM)pszUser;
824 }
825
826
827 BOOL
828 UserProperties(HWND hwndDlg)
829 {
830 PROPSHEETPAGE psp[3];
831 PROPSHEETHEADER psh;
832 TCHAR szUserName[UNLEN + 1];
833 INT nItem;
834 HWND hwndLV;
835
836 hwndLV = GetDlgItem(hwndDlg, IDC_USERS_LIST);
837 nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
838 if (nItem == -1)
839 return FALSE;
840
841 /* Get the new user name */
842 ListView_GetItemText(hwndLV,
843 nItem, 0,
844 szUserName,
845 UNLEN + 1);
846
847 ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
848 psh.dwSize = sizeof(PROPSHEETHEADER);
849 psh.dwFlags = PSH_PROPSHEETPAGE | PSH_PROPTITLE;
850 psh.hwndParent = hwndDlg;
851 psh.hInstance = hApplet;
852 psh.hIcon = NULL;
853 psh.pszCaption = szUserName;
854 psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
855 psh.nStartPage = 0;
856 psh.ppsp = psp;
857
858 InitUserPropSheetPage(&psp[0], IDD_USER_GENERAL, UserGeneralPageProc, szUserName);
859 InitUserPropSheetPage(&psp[1], IDD_USER_MEMBERSHIP, UserMembershipPageProc, szUserName);
860 InitUserPropSheetPage(&psp[2], IDD_USER_PROFILE, UserProfilePageProc, szUserName);
861
862 return (PropertySheet(&psh) == IDOK);
863 }