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 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 + 1]; 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 + 1); 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 OnGroupsPageInitDialog(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_COLOR32 | 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 OnGroupsPageBeginLabelEdit(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 OnGroupsPageEndLabelEdit(LPNMLVDISPINFO pnmv) 338 { 339 TCHAR szOldGroupName[UNLEN + 1]; 340 TCHAR szNewGroupName[UNLEN + 1]; 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 + 1); 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 OnGroupsPageNotify(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 OnGroupsPageBeginLabelEdit((LPNMLVDISPINFO)phdr); 424 425 case LVN_ENDLABELEDIT: 426 return OnGroupsPageEndLabelEdit((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 OnGroupsPageInitDialog(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 OnGroupsPageNotify(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 } 500