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