xref: /reactos/dll/cpl/usrmgr/userprops.c (revision 8532f187)
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
GetUserProfileData(HWND hwndDlg,PPROFILE_USER_DATA pUserData)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
SetUserProfileData(HWND hwndDlg,PPROFILE_USER_DATA pUserData)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
UserProfilePageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
GetUserMembershipData(HWND hwndDlg,PMEMBERSHIP_USER_DATA pUserData)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
RemoveGroupFromUser(HWND hwndDlg,PMEMBERSHIP_USER_DATA pUserData)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
InitUserGroupsList(HWND hwndDlg)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
AddSelectedGroupsToUser(HWND hwndDlg,PMEMBERSHIP_USER_DATA pUserData)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
AddGroupToUserDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
AddGroupToUser(HWND hwndDlg,PMEMBERSHIP_USER_DATA pUserData)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
OnUserPropSheetNotify(HWND hwndDlg,PMEMBERSHIP_USER_DATA pUserData,LPARAM lParam)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
UserMembershipPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
UpdateUserOptions(HWND hwndDlg,PGENERAL_USER_DATA pUserData,BOOL bInit)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
GetUserGeneralData(HWND hwndDlg,PGENERAL_USER_DATA pUserData)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
SetUserGeneralData(HWND hwndDlg,PGENERAL_USER_DATA pUserData)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
UserGeneralPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
InitUserPropSheetPage(PROPSHEETPAGE * psp,WORD idDlg,DLGPROC DlgProc,LPTSTR pszUser)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
UserProperties(HWND hwndDlg)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 }
864