xref: /reactos/dll/cpl/usrmgr/groups.c (revision 2196a06f)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS User Manager Control Panel
4  * FILE:            dll/cpl/usrmgr/groups.c
5  * PURPOSE:         Groups property page
6  *
7  * PROGRAMMERS:     Eric Kohl
8  */
9 
10 #include "usrmgr.h"
11 
12 typedef struct _GROUP_DATA
13 {
14     HMENU hPopupMenu;
15 
16     INT iCurrentItem;
17 
18 } GROUP_DATA, *PGROUP_DATA;
19 
20 
21 static VOID
22 SetGroupsListColumns(HWND hwndListView)
23 {
24     LV_COLUMN column;
25     RECT rect;
26     TCHAR szStr[32];
27 
28     GetClientRect(hwndListView, &rect);
29 
30     memset(&column, 0x00, sizeof(column));
31     column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_TEXT;
32     column.fmt = LVCFMT_LEFT;
33     column.cx = (INT)((rect.right - rect.left) * 0.40);
34     column.iSubItem = 0;
35     LoadString(hApplet, IDS_NAME, szStr, sizeof(szStr) / sizeof(szStr[0]));
36     column.pszText = szStr;
37     (void)ListView_InsertColumn(hwndListView, 0, &column);
38 
39     column.cx = (INT)((rect.right - rect.left) * 0.60);
40     column.iSubItem = 1;
41     LoadString(hApplet, IDS_DESCRIPTION, szStr, sizeof(szStr) / sizeof(szStr[0]));
42     column.pszText = szStr;
43     (void)ListView_InsertColumn(hwndListView, 1, &column);
44 }
45 
46 
47 static VOID
48 UpdateGroupsList(HWND hwndListView)
49 {
50     NET_API_STATUS netStatus;
51     PLOCALGROUP_INFO_1 pBuffer;
52     DWORD entriesread;
53     DWORD totalentries;
54     DWORD_PTR resume_handle = 0;
55     DWORD i;
56     LV_ITEM lvi;
57     INT iItem;
58 
59     for (;;)
60     {
61         netStatus = NetLocalGroupEnum(NULL, 1, (LPBYTE*)&pBuffer,
62                                       1024, &entriesread,
63                                       &totalentries, &resume_handle);
64         if (netStatus != NERR_Success && netStatus != ERROR_MORE_DATA)
65             break;
66 
67         for (i = 0; i < entriesread; i++)
68         {
69            memset(&lvi, 0x00, sizeof(lvi));
70            lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
71            lvi.pszText = pBuffer[i].lgrpi1_name;
72            lvi.state = 0;
73            lvi.iImage = 0;
74            iItem = ListView_InsertItem(hwndListView, &lvi);
75 
76            ListView_SetItemText(hwndListView, iItem, 1,
77                                 pBuffer[i].lgrpi1_comment);
78         }
79 
80         NetApiBufferFree(pBuffer);
81 
82         /* No more data left */
83         if (netStatus != ERROR_MORE_DATA)
84             break;
85     }
86 
87 }
88 
89 
90 static VOID
91 UpdateGroupProperties(HWND hwndDlg)
92 {
93     TCHAR szGroupName[UNLEN + 1];
94     INT iItem;
95     HWND hwndLV;
96     PLOCALGROUP_INFO_1 pGroupInfo = NULL;
97 
98     hwndLV = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
99     iItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
100     if (iItem == -1)
101         return;
102 
103     /* Get the group name */
104     ListView_GetItemText(hwndLV,
105                          iItem, 0,
106                          szGroupName,
107                          UNLEN + 1);
108 
109     NetLocalGroupGetInfo(NULL, szGroupName, 1, (LPBYTE*)&pGroupInfo);
110 
111     ListView_SetItemText(hwndLV, iItem, 1,
112                          pGroupInfo->lgrpi1_comment);
113 
114     NetApiBufferFree(pGroupInfo);
115 }
116 
117 
118 INT_PTR CALLBACK
119 NewGroupDlgProc(HWND hwndDlg,
120                UINT uMsg,
121                WPARAM wParam,
122                LPARAM lParam)
123 {
124     PLOCALGROUP_INFO_1 groupInfo;
125     INT nLength;
126 
127     UNREFERENCED_PARAMETER(wParam);
128 
129     groupInfo = (PLOCALGROUP_INFO_1)GetWindowLongPtr(hwndDlg, DWLP_USER);
130 
131     switch (uMsg)
132     {
133         case WM_INITDIALOG:
134             SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
135             groupInfo = (PLOCALGROUP_INFO_1)lParam;
136             SendDlgItemMessage(hwndDlg, IDC_GROUP_NEW_NAME, EM_SETLIMITTEXT, 20, 0);
137             break;
138 
139         case WM_COMMAND:
140             switch (LOWORD(wParam))
141             {
142                 case IDC_GROUP_NEW_NAME:
143                     if (HIWORD(wParam) == EN_CHANGE)
144                     {
145                         nLength = SendDlgItemMessage(hwndDlg, IDC_GROUP_NEW_NAME, WM_GETTEXTLENGTH, 0, 0);
146                         EnableWindow(GetDlgItem(hwndDlg, IDOK), (nLength > 0));
147                     }
148                     break;
149 
150                 case IDOK:
151                     if (!CheckAccountName(hwndDlg, IDC_GROUP_NEW_NAME, NULL))
152                     {
153                         SetFocus(GetDlgItem(hwndDlg, IDC_GROUP_NEW_NAME));
154                         SendDlgItemMessage(hwndDlg, IDC_GROUP_NEW_NAME, EM_SETSEL, 0, -1);
155                         break;
156                     }
157 
158                     nLength = SendDlgItemMessage(hwndDlg, IDC_GROUP_NEW_NAME, WM_GETTEXTLENGTH, 0, 0);
159                     if (nLength > 0)
160                     {
161                         groupInfo->lgrpi1_name = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nLength + 1) * sizeof(WCHAR));
162                         GetDlgItemText(hwndDlg, IDC_GROUP_NEW_NAME, groupInfo->lgrpi1_name, nLength + 1);
163                     }
164 
165                     nLength = SendDlgItemMessage(hwndDlg, IDC_GROUP_NEW_DESCRIPTION, WM_GETTEXTLENGTH, 0, 0);
166                     if (nLength > 0)
167                     {
168                         groupInfo->lgrpi1_comment = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (nLength + 1) * sizeof(WCHAR));
169                         GetDlgItemText(hwndDlg, IDC_GROUP_NEW_DESCRIPTION, groupInfo->lgrpi1_comment, nLength + 1);
170                     }
171 
172                     EndDialog(hwndDlg, IDOK);
173                     break;
174 
175                 case IDCANCEL:
176                     EndDialog(hwndDlg, IDCANCEL);
177                     break;
178             }
179             break;
180 
181         default:
182             return FALSE;
183     }
184 
185     return TRUE;
186 }
187 
188 
189 static VOID
190 GroupNew(HWND hwndDlg)
191 {
192     NET_API_STATUS status;
193     LOCALGROUP_INFO_1 group;
194     LV_ITEM lvi;
195     INT iItem;
196     HWND hwndLV;
197 
198     ZeroMemory(&group, sizeof(LOCALGROUP_INFO_1));
199 
200     if (DialogBoxParam(hApplet,
201                        MAKEINTRESOURCE(IDD_GROUP_NEW),
202                        hwndDlg,
203                        NewGroupDlgProc,
204                        (LPARAM)&group) == IDOK)
205     {
206         status = NetLocalGroupAdd(NULL,
207                                   1,
208                                   (LPBYTE)&group,
209                                   NULL);
210         if (status != NERR_Success)
211         {
212             TCHAR szText[256];
213             wsprintf(szText, TEXT("Error: %u"), status);
214             MessageBox(NULL, szText, TEXT("NetUserAdd"), MB_ICONERROR | MB_OK);
215             return;
216         }
217 
218         hwndLV = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
219 
220         ZeroMemory(&lvi, sizeof(lvi));
221         lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
222         lvi.pszText = group.lgrpi1_name;
223         lvi.state = 0;
224         lvi.iImage = 0;
225         iItem = ListView_InsertItem(hwndLV, &lvi);
226 
227         ListView_SetItemText(hwndLV, iItem, 1,
228                              group.lgrpi1_comment);
229     }
230 
231     if (group.lgrpi1_name)
232         HeapFree(GetProcessHeap(), 0, group.lgrpi1_name);
233 
234     if (group.lgrpi1_comment)
235         HeapFree(GetProcessHeap(), 0, group.lgrpi1_comment);
236 }
237 
238 
239 static VOID
240 GroupRename(HWND hwndDlg)
241 {
242     INT nItem;
243     HWND hwndLV;
244 
245     hwndLV = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
246     nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
247     if (nItem != -1)
248     {
249         (void)ListView_EditLabel(hwndLV, nItem);
250     }
251 }
252 
253 
254 static BOOL
255 GroupDelete(HWND hwndDlg)
256 {
257     TCHAR szGroupName[UNLEN + 1];
258     TCHAR szText[256];
259     INT nItem;
260     HWND hwndLV;
261     NET_API_STATUS status;
262 
263     hwndLV = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
264     nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
265     if (nItem == -1)
266         return FALSE;
267 
268     /* Get the new group name */
269     ListView_GetItemText(hwndLV,
270                          nItem, 0,
271                          szGroupName,
272                          UNLEN + 1);
273 
274     /* Display a warning message, because the delete operation cannot be reverted */
275     wsprintf(szText, TEXT("Dou you really want to delete the user group \"%s\"?"), szGroupName);
276     if (MessageBox(NULL, szText, TEXT("User Groups"), MB_ICONWARNING | MB_YESNO) == IDNO)
277         return FALSE;
278 
279     /* Delete the group */
280     status = NetLocalGroupDel(NULL, szGroupName);
281     if (status != NERR_Success)
282     {
283         TCHAR szText[256];
284         wsprintf(szText, TEXT("Error: %u"), status);
285         MessageBox(NULL, szText, TEXT("NetLocalGroupDel"), MB_ICONERROR | MB_OK);
286         return FALSE;
287     }
288 
289     /* Delete the group from the list */
290     (void)ListView_DeleteItem(hwndLV, nItem);
291 
292     return TRUE;
293 }
294 
295 
296 static VOID
297 OnGroupsPageInitDialog(HWND hwndDlg)
298 {
299     HWND hwndListView;
300     HIMAGELIST hImgList;
301     HICON hIcon;
302 
303     /* Create the image list */
304     hImgList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 5, 5);
305     hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_GROUP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
306     ImageList_AddIcon(hImgList, hIcon);
307     DestroyIcon(hIcon);
308 
309     hwndListView = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
310 
311     (VOID)ListView_SetImageList(hwndListView, hImgList, LVSIL_SMALL);
312 
313     (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
314 
315     SetGroupsListColumns(hwndListView);
316 
317     UpdateGroupsList(hwndListView);
318 }
319 
320 
321 static BOOL
322 OnGroupsPageBeginLabelEdit(LPNMLVDISPINFO pnmv)
323 {
324     HWND hwndEdit;
325 
326     hwndEdit = ListView_GetEditControl(pnmv->hdr.hwndFrom);
327     if (hwndEdit == NULL)
328         return TRUE;
329 
330     SendMessage(hwndEdit, EM_SETLIMITTEXT, 20, 0);
331 
332     return FALSE;
333 }
334 
335 
336 static BOOL
337 OnGroupsPageEndLabelEdit(LPNMLVDISPINFO pnmv)
338 {
339     TCHAR szOldGroupName[UNLEN + 1];
340     TCHAR szNewGroupName[UNLEN + 1];
341     LOCALGROUP_INFO_0 lgrpi0;
342     NET_API_STATUS status;
343 
344     /* Leave, if there is no valid listview item */
345     if (pnmv->item.iItem == -1)
346         return FALSE;
347 
348     /* Get the new user name */
349     ListView_GetItemText(pnmv->hdr.hwndFrom,
350                          pnmv->item.iItem, 0,
351                          szOldGroupName,
352                          UNLEN + 1);
353 
354     /* Leave, if the user canceled the edit action */
355     if (pnmv->item.pszText == NULL)
356         return FALSE;
357 
358     /* Get the new user name */
359     lstrcpy(szNewGroupName, pnmv->item.pszText);
360 
361     /* Leave, if the user name was not changed */
362     if (lstrcmp(szOldGroupName, szNewGroupName) == 0)
363         return FALSE;
364 
365     /* Check the group name for illegal characters */
366     if (!CheckAccountName(NULL, 0, szNewGroupName))
367         return FALSE;
368 
369     /* Change the user name */
370     lgrpi0.lgrpi0_name = szNewGroupName;
371 
372     status = NetLocalGroupSetInfo(NULL, szOldGroupName, 0, (LPBYTE)&lgrpi0, NULL);
373     if (status != NERR_Success)
374     {
375         TCHAR szText[256];
376         wsprintf(szText, TEXT("Error: %u"), status);
377         MessageBox(NULL, szText, TEXT("NetLocalGroupSetInfo"), MB_ICONERROR | MB_OK);
378         return FALSE;
379     }
380 
381     /* Update the listview item */
382     ListView_SetItemText(pnmv->hdr.hwndFrom,
383                          pnmv->item.iItem, 0,
384                          szNewGroupName);
385 
386     return TRUE;
387 }
388 
389 
390 static BOOL
391 OnGroupsPageNotify(HWND hwndDlg, PGROUP_DATA pGroupData, NMHDR *phdr)
392 {
393     LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
394 
395     switch (phdr->idFrom)
396     {
397         case IDC_GROUPS_LIST:
398             switch(phdr->code)
399             {
400                 case NM_CLICK:
401                     pGroupData->iCurrentItem = lpnmlv->iItem;
402                     break;
403 
404                 case NM_DBLCLK:
405                     if (lpnmlv->iItem != -1)
406                     {
407                         UINT uItem;
408 
409                         uItem =  GetMenuDefaultItem(GetSubMenu(pGroupData->hPopupMenu, 1),
410                                                     FALSE, 0);
411                         if (uItem != (UINT)-1)
412                             SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(uItem, 0), 0);
413                     }
414                     break;
415 
416                 case NM_RCLICK:
417                     ClientToScreen(GetDlgItem(hwndDlg, IDC_GROUPS_LIST), &lpnmlv->ptAction);
418                     TrackPopupMenu(GetSubMenu(pGroupData->hPopupMenu, (lpnmlv->iItem == -1) ? 0 : 1),
419                                    TPM_LEFTALIGN, lpnmlv->ptAction.x, lpnmlv->ptAction.y, 0, hwndDlg, NULL);
420                     break;
421 
422                 case LVN_BEGINLABELEDIT:
423                     return OnGroupsPageBeginLabelEdit((LPNMLVDISPINFO)phdr);
424 
425                 case LVN_ENDLABELEDIT:
426                     return OnGroupsPageEndLabelEdit((LPNMLVDISPINFO)phdr);
427             }
428             break;
429     }
430 
431     return FALSE;
432 }
433 
434 
435 INT_PTR CALLBACK
436 GroupsPageProc(HWND hwndDlg,
437                UINT uMsg,
438                WPARAM wParam,
439                LPARAM lParam)
440 {
441     PGROUP_DATA pGroupData;
442 
443     UNREFERENCED_PARAMETER(lParam);
444     UNREFERENCED_PARAMETER(wParam);
445     UNREFERENCED_PARAMETER(hwndDlg);
446 
447 
448     pGroupData = (PGROUP_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
449 
450     switch (uMsg)
451     {
452         case WM_INITDIALOG:
453             pGroupData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GROUP_DATA));
454             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGroupData);
455 
456             pGroupData->hPopupMenu = LoadMenu(hApplet, MAKEINTRESOURCE(IDM_POPUP_GROUP));
457 
458             OnGroupsPageInitDialog(hwndDlg);
459             SetMenuDefaultItem(GetSubMenu(pGroupData->hPopupMenu, 1),
460                                IDM_GROUP_PROPERTIES,
461                                FALSE);
462             break;
463 
464         case WM_COMMAND:
465             switch (LOWORD(wParam))
466             {
467                 case IDM_GROUP_NEW:
468                 case IDC_GROUPS_ADD:
469                     GroupNew(hwndDlg);
470                     break;
471 
472                 case IDM_GROUP_RENAME:
473                     GroupRename(hwndDlg);
474                     break;
475 
476                 case IDM_GROUP_DELETE:
477                 case IDC_GROUPS_REMOVE:
478                     GroupDelete(hwndDlg);
479                     break;
480 
481                 case IDM_GROUP_PROPERTIES:
482                 case IDC_GROUPS_PROPERTIES:
483                     if (GroupProperties(hwndDlg) == IDOK)
484                         UpdateGroupProperties(hwndDlg);
485                     break;
486             }
487             break;
488 
489         case WM_NOTIFY:
490             return OnGroupsPageNotify(hwndDlg, pGroupData, (NMHDR *)lParam);
491 
492         case WM_DESTROY:
493             DestroyMenu(pGroupData->hPopupMenu);
494             HeapFree(GetProcessHeap(), 0, pGroupData);
495             break;
496     }
497 
498     return FALSE;
499 }
500