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
SetGroupsListColumns(HWND hwndListView)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
UpdateGroupsList(HWND hwndListView)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
UpdateGroupProperties(HWND hwndDlg)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
NewGroupDlgProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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
GroupNew(HWND hwndDlg)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
GroupRename(HWND hwndDlg)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
GroupDelete(HWND hwndDlg)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
OnGroupsPageInitDialog(HWND hwndDlg)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
OnGroupsPageBeginLabelEdit(LPNMLVDISPINFO pnmv)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
OnGroupsPageEndLabelEdit(LPNMLVDISPINFO pnmv)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
OnGroupsPageNotify(HWND hwndDlg,PGROUP_DATA pGroupData,NMHDR * phdr)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
GroupsPageProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)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