xref: /reactos/dll/cpl/usrmgr/groups.c (revision 72ea2d4c)
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                     /* Get Name */
159                     groupInfo->lgrpi1_name = GetDlgItemTextAlloc(hwndDlg, IDC_GROUP_NEW_NAME);
160 
161                     /* Get Description */
162                     groupInfo->lgrpi1_comment = GetDlgItemTextAlloc(hwndDlg, IDC_GROUP_NEW_DESCRIPTION);
163 
164                     EndDialog(hwndDlg, IDOK);
165                     break;
166 
167                 case IDCANCEL:
168                     EndDialog(hwndDlg, IDCANCEL);
169                     break;
170             }
171             break;
172 
173         default:
174             return FALSE;
175     }
176 
177     return TRUE;
178 }
179 
180 
181 static VOID
182 GroupNew(HWND hwndDlg)
183 {
184     NET_API_STATUS status;
185     LOCALGROUP_INFO_1 group;
186     LV_ITEM lvi;
187     INT iItem;
188     HWND hwndLV;
189 
190     ZeroMemory(&group, sizeof(LOCALGROUP_INFO_1));
191 
192     if (DialogBoxParam(hApplet,
193                        MAKEINTRESOURCE(IDD_GROUP_NEW),
194                        hwndDlg,
195                        NewGroupDlgProc,
196                        (LPARAM)&group) == IDOK)
197     {
198         status = NetLocalGroupAdd(NULL,
199                                   1,
200                                   (LPBYTE)&group,
201                                   NULL);
202         if (status != NERR_Success)
203         {
204             TCHAR szText[256];
205             wsprintf(szText, TEXT("Error: %u"), status);
206             MessageBox(NULL, szText, TEXT("NetUserAdd"), MB_ICONERROR | MB_OK);
207             return;
208         }
209 
210         hwndLV = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
211 
212         ZeroMemory(&lvi, sizeof(lvi));
213         lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE;
214         lvi.pszText = group.lgrpi1_name;
215         lvi.state = 0;
216         lvi.iImage = 0;
217         iItem = ListView_InsertItem(hwndLV, &lvi);
218 
219         ListView_SetItemText(hwndLV, iItem, 1,
220                              group.lgrpi1_comment);
221     }
222 
223     HeapFree(GetProcessHeap(), 0, group.lgrpi1_name);
224     HeapFree(GetProcessHeap(), 0, group.lgrpi1_comment);
225 }
226 
227 
228 static VOID
229 GroupRename(HWND hwndDlg)
230 {
231     INT nItem;
232     HWND hwndLV;
233 
234     hwndLV = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
235     nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
236     if (nItem != -1)
237     {
238         (void)ListView_EditLabel(hwndLV, nItem);
239     }
240 }
241 
242 
243 static BOOL
244 GroupDelete(HWND hwndDlg)
245 {
246     TCHAR szGroupName[UNLEN + 1];
247     TCHAR szText[256];
248     INT nItem;
249     HWND hwndLV;
250     NET_API_STATUS status;
251 
252     hwndLV = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
253     nItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
254     if (nItem == -1)
255         return FALSE;
256 
257     /* Get the new group name */
258     ListView_GetItemText(hwndLV,
259                          nItem, 0,
260                          szGroupName,
261                          UNLEN + 1);
262 
263     /* Display a warning message, because the delete operation cannot be reverted */
264     wsprintf(szText, TEXT("Dou you really want to delete the user group \"%s\"?"), szGroupName);
265     if (MessageBox(NULL, szText, TEXT("User Groups"), MB_ICONWARNING | MB_YESNO) == IDNO)
266         return FALSE;
267 
268     /* Delete the group */
269     status = NetLocalGroupDel(NULL, szGroupName);
270     if (status != NERR_Success)
271     {
272         TCHAR szText[256];
273         wsprintf(szText, TEXT("Error: %u"), status);
274         MessageBox(NULL, szText, TEXT("NetLocalGroupDel"), MB_ICONERROR | MB_OK);
275         return FALSE;
276     }
277 
278     /* Delete the group from the list */
279     (void)ListView_DeleteItem(hwndLV, nItem);
280 
281     return TRUE;
282 }
283 
284 
285 static VOID
286 OnGroupsPageInitDialog(HWND hwndDlg)
287 {
288     HWND hwndListView;
289     HIMAGELIST hImgList;
290     HICON hIcon;
291 
292     /* Create the image list */
293     hImgList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 5, 5);
294     hIcon = LoadImage(hApplet, MAKEINTRESOURCE(IDI_GROUP), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
295     ImageList_AddIcon(hImgList, hIcon);
296     DestroyIcon(hIcon);
297 
298     hwndListView = GetDlgItem(hwndDlg, IDC_GROUPS_LIST);
299 
300     (VOID)ListView_SetImageList(hwndListView, hImgList, LVSIL_SMALL);
301 
302     (void)ListView_SetExtendedListViewStyle(hwndListView, LVS_EX_FULLROWSELECT);
303 
304     SetGroupsListColumns(hwndListView);
305 
306     UpdateGroupsList(hwndListView);
307 }
308 
309 
310 static BOOL
311 OnGroupsPageBeginLabelEdit(LPNMLVDISPINFO pnmv)
312 {
313     HWND hwndEdit;
314 
315     hwndEdit = ListView_GetEditControl(pnmv->hdr.hwndFrom);
316     if (hwndEdit == NULL)
317         return TRUE;
318 
319     SendMessage(hwndEdit, EM_SETLIMITTEXT, 20, 0);
320 
321     return FALSE;
322 }
323 
324 
325 static BOOL
326 OnGroupsPageEndLabelEdit(LPNMLVDISPINFO pnmv)
327 {
328     TCHAR szOldGroupName[UNLEN + 1];
329     TCHAR szNewGroupName[UNLEN + 1];
330     LOCALGROUP_INFO_0 lgrpi0;
331     NET_API_STATUS status;
332 
333     /* Leave, if there is no valid listview item */
334     if (pnmv->item.iItem == -1)
335         return FALSE;
336 
337     /* Get the new user name */
338     ListView_GetItemText(pnmv->hdr.hwndFrom,
339                          pnmv->item.iItem, 0,
340                          szOldGroupName,
341                          UNLEN + 1);
342 
343     /* Leave, if the user canceled the edit action */
344     if (pnmv->item.pszText == NULL)
345         return FALSE;
346 
347     /* Get the new user name */
348     lstrcpy(szNewGroupName, pnmv->item.pszText);
349 
350     /* Leave, if the user name was not changed */
351     if (lstrcmp(szOldGroupName, szNewGroupName) == 0)
352         return FALSE;
353 
354     /* Check the group name for illegal characters */
355     if (!CheckAccountName(NULL, 0, szNewGroupName))
356         return FALSE;
357 
358     /* Change the user name */
359     lgrpi0.lgrpi0_name = szNewGroupName;
360 
361     status = NetLocalGroupSetInfo(NULL, szOldGroupName, 0, (LPBYTE)&lgrpi0, NULL);
362     if (status != NERR_Success)
363     {
364         TCHAR szText[256];
365         wsprintf(szText, TEXT("Error: %u"), status);
366         MessageBox(NULL, szText, TEXT("NetLocalGroupSetInfo"), MB_ICONERROR | MB_OK);
367         return FALSE;
368     }
369 
370     /* Update the listview item */
371     ListView_SetItemText(pnmv->hdr.hwndFrom,
372                          pnmv->item.iItem, 0,
373                          szNewGroupName);
374 
375     return TRUE;
376 }
377 
378 
379 static BOOL
380 OnGroupsPageNotify(HWND hwndDlg, PGROUP_DATA pGroupData, NMHDR *phdr)
381 {
382     LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)phdr;
383 
384     switch (phdr->idFrom)
385     {
386         case IDC_GROUPS_LIST:
387             switch(phdr->code)
388             {
389                 case NM_CLICK:
390                     pGroupData->iCurrentItem = lpnmlv->iItem;
391                     break;
392 
393                 case NM_DBLCLK:
394                     if (lpnmlv->iItem != -1)
395                     {
396                         UINT uItem;
397 
398                         uItem =  GetMenuDefaultItem(GetSubMenu(pGroupData->hPopupMenu, 1),
399                                                     FALSE, 0);
400                         if (uItem != (UINT)-1)
401                             SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(uItem, 0), 0);
402                     }
403                     break;
404 
405                 case NM_RCLICK:
406                     ClientToScreen(GetDlgItem(hwndDlg, IDC_GROUPS_LIST), &lpnmlv->ptAction);
407                     TrackPopupMenu(GetSubMenu(pGroupData->hPopupMenu, (lpnmlv->iItem == -1) ? 0 : 1),
408                                    TPM_LEFTALIGN, lpnmlv->ptAction.x, lpnmlv->ptAction.y, 0, hwndDlg, NULL);
409                     break;
410 
411                 case LVN_BEGINLABELEDIT:
412                     return OnGroupsPageBeginLabelEdit((LPNMLVDISPINFO)phdr);
413 
414                 case LVN_ENDLABELEDIT:
415                     return OnGroupsPageEndLabelEdit((LPNMLVDISPINFO)phdr);
416             }
417             break;
418     }
419 
420     return FALSE;
421 }
422 
423 
424 INT_PTR CALLBACK
425 GroupsPageProc(HWND hwndDlg,
426                UINT uMsg,
427                WPARAM wParam,
428                LPARAM lParam)
429 {
430     PGROUP_DATA pGroupData;
431 
432     UNREFERENCED_PARAMETER(lParam);
433     UNREFERENCED_PARAMETER(wParam);
434     UNREFERENCED_PARAMETER(hwndDlg);
435 
436 
437     pGroupData = (PGROUP_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
438 
439     switch (uMsg)
440     {
441         case WM_INITDIALOG:
442             pGroupData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GROUP_DATA));
443             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGroupData);
444 
445             pGroupData->hPopupMenu = LoadMenu(hApplet, MAKEINTRESOURCE(IDM_POPUP_GROUP));
446 
447             OnGroupsPageInitDialog(hwndDlg);
448             SetMenuDefaultItem(GetSubMenu(pGroupData->hPopupMenu, 1),
449                                IDM_GROUP_PROPERTIES,
450                                FALSE);
451             break;
452 
453         case WM_COMMAND:
454             switch (LOWORD(wParam))
455             {
456                 case IDM_GROUP_NEW:
457                 case IDC_GROUPS_ADD:
458                     GroupNew(hwndDlg);
459                     break;
460 
461                 case IDM_GROUP_RENAME:
462                     GroupRename(hwndDlg);
463                     break;
464 
465                 case IDM_GROUP_DELETE:
466                 case IDC_GROUPS_REMOVE:
467                     GroupDelete(hwndDlg);
468                     break;
469 
470                 case IDM_GROUP_PROPERTIES:
471                 case IDC_GROUPS_PROPERTIES:
472                     if (GroupProperties(hwndDlg) == IDOK)
473                         UpdateGroupProperties(hwndDlg);
474                     break;
475             }
476             break;
477 
478         case WM_NOTIFY:
479             return OnGroupsPageNotify(hwndDlg, pGroupData, (NMHDR *)lParam);
480 
481         case WM_DESTROY:
482             DestroyMenu(pGroupData->hPopupMenu);
483             HeapFree(GetProcessHeap(), 0, pGroupData);
484             break;
485     }
486 
487     return FALSE;
488 }
489