[DINPUT]
[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 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);
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];
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);
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 OnInitDialog(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_COLOR8 | 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 OnBeginLabelEdit(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 OnEndLabelEdit(LPNMLVDISPINFO pnmv)
338 {
339 TCHAR szOldGroupName[UNLEN];
340 TCHAR szNewGroupName[UNLEN];
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);
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 OnNotify(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 OnBeginLabelEdit((LPNMLVDISPINFO)phdr);
424
425 case LVN_ENDLABELEDIT:
426 return OnEndLabelEdit((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 OnInitDialog(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 OnNotify(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 }