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 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 } 510