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