1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS net command 4 * FILE: base/applications/network/net/cmdUser.c 5 * PURPOSE: 6 * 7 * PROGRAMMERS: Eric Kohl 8 * Curtis Wilson 9 */ 10 11 #include "net.h" 12 13 static WCHAR szPasswordChars[] = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@#$%_-+:"; 14 15 static 16 int 17 CompareInfo(const void *a, const void *b) 18 { 19 return _wcsicmp(((PUSER_INFO_0)a)->usri0_name, 20 ((PUSER_INFO_0)b)->usri0_name); 21 } 22 23 24 static 25 NET_API_STATUS 26 EnumerateUsers(VOID) 27 { 28 PUSER_INFO_0 pBuffer = NULL; 29 PSERVER_INFO_100 pServer = NULL; 30 DWORD dwRead = 0, dwTotal = 0; 31 DWORD i; 32 DWORD ResumeHandle = 0; 33 NET_API_STATUS Status; 34 35 Status = NetServerGetInfo(NULL, 36 100, 37 (LPBYTE*)&pServer); 38 if (Status != NERR_Success) 39 return Status; 40 41 ConPuts(StdOut, L"\n"); 42 ConResPrintf(StdOut, IDS_USER_ACCOUNTS, pServer->sv100_name); 43 ConPuts(StdOut, L"\n\n"); 44 PrintPadding(L'-', 79); 45 ConPuts(StdOut, L"\n"); 46 47 NetApiBufferFree(pServer); 48 49 do 50 { 51 Status = NetUserEnum(NULL, 52 0, 53 0, 54 (LPBYTE*)&pBuffer, 55 MAX_PREFERRED_LENGTH, 56 &dwRead, 57 &dwTotal, 58 &ResumeHandle); 59 if ((Status != NERR_Success) && (Status != ERROR_MORE_DATA)) 60 return Status; 61 62 qsort(pBuffer, 63 dwRead, 64 sizeof(PUSER_INFO_0), 65 CompareInfo); 66 67 for (i = 0; i < dwRead; i++) 68 { 69 if (pBuffer[i].usri0_name) 70 ConPrintf(StdOut, L"%s\n", pBuffer[i].usri0_name); 71 } 72 73 NetApiBufferFree(pBuffer); 74 pBuffer = NULL; 75 } 76 while (Status == ERROR_MORE_DATA); 77 78 return NERR_Success; 79 } 80 81 82 static 83 VOID 84 PrintDateTime(DWORD dwSeconds) 85 { 86 LARGE_INTEGER Time; 87 FILETIME FileTime; 88 SYSTEMTIME SystemTime; 89 WCHAR DateBuffer[80]; 90 WCHAR TimeBuffer[80]; 91 92 RtlSecondsSince1970ToTime(dwSeconds, &Time); 93 FileTime.dwLowDateTime = Time.u.LowPart; 94 FileTime.dwHighDateTime = Time.u.HighPart; 95 FileTimeToLocalFileTime(&FileTime, &FileTime); 96 FileTimeToSystemTime(&FileTime, &SystemTime); 97 98 GetDateFormatW(LOCALE_USER_DEFAULT, 99 DATE_SHORTDATE, 100 &SystemTime, 101 NULL, 102 DateBuffer, 103 80); 104 105 GetTimeFormatW(LOCALE_USER_DEFAULT, 106 TIME_NOSECONDS, 107 &SystemTime, 108 NULL, 109 TimeBuffer, 110 80); 111 112 ConPrintf(StdOut, L"%s %s", DateBuffer, TimeBuffer); 113 } 114 115 116 static 117 DWORD 118 GetTimeInSeconds(VOID) 119 { 120 LARGE_INTEGER Time; 121 FILETIME FileTime; 122 DWORD dwSeconds; 123 124 GetSystemTimeAsFileTime(&FileTime); 125 Time.u.LowPart = FileTime.dwLowDateTime; 126 Time.u.HighPart = FileTime.dwHighDateTime; 127 RtlTimeToSecondsSince1970(&Time, &dwSeconds); 128 129 return dwSeconds; 130 } 131 132 133 static 134 NET_API_STATUS 135 DisplayUser(LPWSTR lpUserName) 136 { 137 PUSER_MODALS_INFO_0 pUserModals = NULL; 138 PUSER_INFO_4 pUserInfo = NULL; 139 PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL; 140 PGROUP_USERS_INFO_0 pGroupInfo = NULL; 141 DWORD dwLocalGroupRead, dwLocalGroupTotal; 142 DWORD dwGroupRead, dwGroupTotal; 143 DWORD dwLastSet; 144 DWORD i; 145 INT nPaddedLength = 29; 146 NET_API_STATUS Status; 147 148 /* Modify the user */ 149 Status = NetUserGetInfo(NULL, 150 lpUserName, 151 4, 152 (LPBYTE*)&pUserInfo); 153 if (Status != NERR_Success) 154 return Status; 155 156 Status = NetUserModalsGet(NULL, 157 0, 158 (LPBYTE*)&pUserModals); 159 if (Status != NERR_Success) 160 goto done; 161 162 Status = NetUserGetLocalGroups(NULL, 163 lpUserName, 164 0, 165 0, 166 (LPBYTE*)&pLocalGroupInfo, 167 MAX_PREFERRED_LENGTH, 168 &dwLocalGroupRead, 169 &dwLocalGroupTotal); 170 if (Status != NERR_Success) 171 goto done; 172 173 Status = NetUserGetGroups(NULL, 174 lpUserName, 175 0, 176 (LPBYTE*)&pGroupInfo, 177 MAX_PREFERRED_LENGTH, 178 &dwGroupRead, 179 &dwGroupTotal); 180 if (Status != NERR_Success) 181 goto done; 182 183 PrintPaddedResourceString(IDS_USER_NAME, nPaddedLength); 184 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_name); 185 186 PrintPaddedResourceString(IDS_USER_FULL_NAME, nPaddedLength); 187 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_full_name); 188 189 PrintPaddedResourceString(IDS_USER_COMMENT, nPaddedLength); 190 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_comment); 191 192 PrintPaddedResourceString(IDS_USER_USER_COMMENT, nPaddedLength); 193 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_usr_comment); 194 195 PrintPaddedResourceString(IDS_USER_COUNTRY_CODE, nPaddedLength); 196 ConPrintf(StdOut, L"%03ld ()\n", pUserInfo->usri4_country_code); 197 198 PrintPaddedResourceString(IDS_USER_ACCOUNT_ACTIVE, nPaddedLength); 199 if (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE) 200 ConResPuts(StdOut, IDS_GENERIC_NO); 201 else if (pUserInfo->usri4_flags & UF_LOCKOUT) 202 ConResPuts(StdOut, IDS_GENERIC_LOCKED); 203 else 204 ConResPuts(StdOut, IDS_GENERIC_YES); 205 ConPuts(StdOut, L"\n"); 206 207 PrintPaddedResourceString(IDS_USER_ACCOUNT_EXPIRES, nPaddedLength); 208 if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER) 209 ConResPuts(StdOut, IDS_GENERIC_NEVER); 210 else 211 PrintDateTime(pUserInfo->usri4_acct_expires); 212 ConPuts(StdOut, L"\n\n"); 213 214 PrintPaddedResourceString(IDS_USER_PW_LAST_SET, nPaddedLength); 215 dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age; 216 PrintDateTime(dwLastSet); 217 ConPuts(StdOut, L"\n"); 218 219 PrintPaddedResourceString(IDS_USER_PW_EXPIRES, nPaddedLength); 220 if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER) 221 ConResPuts(StdOut, IDS_GENERIC_NEVER); 222 else 223 PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age); 224 ConPuts(StdOut, L"\n"); 225 226 PrintPaddedResourceString(IDS_USER_PW_CHANGEABLE, nPaddedLength); 227 PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age); 228 ConPuts(StdOut, L"\n"); 229 230 PrintPaddedResourceString(IDS_USER_PW_REQUIRED, nPaddedLength); 231 ConResPuts(StdOut, (pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? IDS_GENERIC_NO : IDS_GENERIC_YES); 232 ConPuts(StdOut, L"\n"); 233 234 PrintPaddedResourceString(IDS_USER_CHANGE_PW, nPaddedLength); 235 ConResPuts(StdOut, (pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? IDS_GENERIC_NO : IDS_GENERIC_YES); 236 ConPuts(StdOut, L"\n\n"); 237 238 PrintPaddedResourceString(IDS_USER_WORKSTATIONS, nPaddedLength); 239 if (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0) 240 ConResPuts(StdOut, IDS_GENERIC_ALL); 241 else 242 ConPrintf(StdOut, L"%s", pUserInfo->usri4_workstations); 243 ConPuts(StdOut, L"\n"); 244 245 PrintPaddedResourceString(IDS_USER_LOGON_SCRIPT, nPaddedLength); 246 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_script_path); 247 248 PrintPaddedResourceString(IDS_USER_PROFILE, nPaddedLength); 249 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_profile); 250 251 PrintPaddedResourceString(IDS_USER_HOME_DIR, nPaddedLength); 252 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_home_dir); 253 254 PrintPaddedResourceString(IDS_USER_LAST_LOGON, nPaddedLength); 255 if (pUserInfo->usri4_last_logon == 0) 256 ConResPuts(StdOut, IDS_GENERIC_NEVER); 257 else 258 PrintDateTime(pUserInfo->usri4_last_logon); 259 ConPuts(StdOut, L"\n\n"); 260 261 PrintPaddedResourceString(IDS_USER_LOGON_HOURS, nPaddedLength); 262 if (pUserInfo->usri4_logon_hours == NULL) 263 ConResPuts(StdOut, IDS_GENERIC_ALL); 264 ConPuts(StdOut, L"\n\n"); 265 266 ConPuts(StdOut, L"\n"); 267 PrintPaddedResourceString(IDS_USER_LOCAL_GROUPS, nPaddedLength); 268 if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL) 269 { 270 for (i = 0; i < dwLocalGroupTotal; i++) 271 { 272 if (i != 0) 273 PrintPadding(L' ', nPaddedLength); 274 ConPrintf(StdOut, L"*%s\n", pLocalGroupInfo[i].lgrui0_name); 275 } 276 } 277 else 278 { 279 ConPuts(StdOut, L"\n"); 280 } 281 282 PrintPaddedResourceString(IDS_USER_GLOBAL_GROUPS, nPaddedLength); 283 if (dwGroupTotal != 0 && pGroupInfo != NULL) 284 { 285 for (i = 0; i < dwGroupTotal; i++) 286 { 287 if (i != 0) 288 PrintPadding(L' ', nPaddedLength); 289 ConPrintf(StdOut, L"*%s\n", pGroupInfo[i].grui0_name); 290 } 291 } 292 else 293 { 294 ConPuts(StdOut, L"\n"); 295 } 296 297 done: 298 if (pGroupInfo != NULL) 299 NetApiBufferFree(pGroupInfo); 300 301 if (pLocalGroupInfo != NULL) 302 NetApiBufferFree(pLocalGroupInfo); 303 304 if (pUserModals != NULL) 305 NetApiBufferFree(pUserModals); 306 307 if (pUserInfo != NULL) 308 NetApiBufferFree(pUserInfo); 309 310 return NERR_Success; 311 } 312 313 314 static 315 VOID 316 ReadPassword( 317 LPWSTR *lpPassword, 318 LPBOOL lpAllocated) 319 { 320 WCHAR szPassword1[PWLEN + 1]; 321 WCHAR szPassword2[PWLEN + 1]; 322 LPWSTR ptr; 323 324 *lpAllocated = FALSE; 325 326 while (TRUE) 327 { 328 ConResPuts(StdOut, IDS_USER_ENTER_PASSWORD1); 329 ReadFromConsole(szPassword1, PWLEN + 1, FALSE); 330 ConPuts(StdOut, L"\n"); 331 332 ConResPuts(StdOut, IDS_USER_ENTER_PASSWORD2); 333 ReadFromConsole(szPassword2, PWLEN + 1, FALSE); 334 ConPuts(StdOut, L"\n"); 335 336 if (wcslen(szPassword1) == wcslen(szPassword2) && 337 wcscmp(szPassword1, szPassword2) == 0) 338 { 339 ptr = HeapAlloc(GetProcessHeap(), 340 0, 341 (wcslen(szPassword1) + 1) * sizeof(WCHAR)); 342 if (ptr != NULL) 343 { 344 wcscpy(ptr, szPassword1); 345 *lpPassword = ptr; 346 *lpAllocated = TRUE; 347 return; 348 } 349 } 350 else 351 { 352 ConPuts(StdOut, L"\n"); 353 ConResPuts(StdOut, IDS_USER_NO_PASSWORD_MATCH); 354 ConPuts(StdOut, L"\n"); 355 *lpPassword = NULL; 356 } 357 } 358 } 359 360 361 static 362 VOID 363 GenerateRandomPassword( 364 LPWSTR *lpPassword, 365 LPBOOL lpAllocated) 366 { 367 LPWSTR pPassword = NULL; 368 INT nCharsLen, i, nLength = 8; 369 370 srand(GetTickCount()); 371 372 pPassword = HeapAlloc(GetProcessHeap(), 373 HEAP_ZERO_MEMORY, 374 (nLength + 1) * sizeof(WCHAR)); 375 if (pPassword == NULL) 376 return; 377 378 nCharsLen = wcslen(szPasswordChars); 379 380 for (i = 0; i < nLength; i++) 381 { 382 pPassword[i] = szPasswordChars[rand() % nCharsLen]; 383 } 384 385 *lpPassword = pPassword; 386 *lpAllocated = TRUE; 387 } 388 389 390 static 391 NET_API_STATUS 392 BuildWorkstationsList( 393 _Out_ PWSTR *pWorkstationsList, 394 _In_ PWSTR pRaw) 395 { 396 BOOL isLastSep, isSep; 397 INT i, j; 398 WCHAR c; 399 INT nLength = 0; 400 INT nArgs = 0; 401 INT nRawLength; 402 PWSTR pList; 403 404 /* Check for invalid characters in the raw string */ 405 if (wcspbrk(pRaw, L"/[]=?\\+:.") != NULL) 406 return 3952; 407 408 /* Count the number of workstations in the list and 409 * the required buffer size */ 410 isLastSep = FALSE; 411 isSep = FALSE; 412 nRawLength = wcslen(pRaw); 413 for (i = 0; i < nRawLength; i++) 414 { 415 c = pRaw[i]; 416 if (c == L',' || c == L';') 417 isSep = TRUE; 418 419 if (isSep == TRUE) 420 { 421 if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1)) 422 nLength++; 423 } 424 else 425 { 426 nLength++; 427 428 if (isLastSep == TRUE || (isLastSep == FALSE && i == 0)) 429 nArgs++; 430 } 431 432 isLastSep = isSep; 433 isSep = FALSE; 434 } 435 436 nLength++; 437 438 /* Leave, if there are no workstations in the list */ 439 if (nArgs == 0) 440 { 441 pWorkstationsList = NULL; 442 return NERR_Success; 443 } 444 445 /* Fail if there are more than eight workstations in the list */ 446 if (nArgs > 8) 447 return 3951; 448 449 /* Allocate the buffer for the clean workstation list */ 450 pList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(WCHAR)); 451 if (pList == NULL) 452 return ERROR_NOT_ENOUGH_MEMORY; 453 454 /* Build the clean workstation list */ 455 isLastSep = FALSE; 456 isSep = FALSE; 457 nRawLength = wcslen(pRaw); 458 for (i = 0, j = 0; i < nRawLength; i++) 459 { 460 c = pRaw[i]; 461 if (c == L',' || c == L';') 462 isSep = TRUE; 463 464 if (isSep == TRUE) 465 { 466 if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1)) 467 { 468 pList[j] = L','; 469 j++; 470 } 471 } 472 else 473 { 474 pList[j] = c; 475 j++; 476 477 if (isLastSep == TRUE || (isLastSep == FALSE && i == 0)) 478 nArgs++; 479 } 480 481 isLastSep = isSep; 482 isSep = FALSE; 483 } 484 485 *pWorkstationsList = pList; 486 487 return NERR_Success; 488 } 489 490 491 INT 492 cmdUser( 493 INT argc, 494 WCHAR **argv) 495 { 496 INT i, j; 497 INT result = 0; 498 BOOL bAdd = FALSE; 499 BOOL bDelete = FALSE; 500 #if 0 501 BOOL bDomain = FALSE; 502 #endif 503 BOOL bRandomPassword = FALSE; 504 LPWSTR lpUserName = NULL; 505 LPWSTR lpPassword = NULL; 506 PUSER_INFO_4 pUserInfo = NULL; 507 USER_INFO_4 UserInfo; 508 LPWSTR pWorkstations = NULL; 509 LPWSTR p; 510 LPWSTR endptr; 511 DWORD value; 512 BOOL bPasswordAllocated = FALSE; 513 NET_API_STATUS Status; 514 515 if (argc == 2) 516 { 517 Status = EnumerateUsers(); 518 ConPrintf(StdOut, L"Status: %lu\n", Status); 519 return 0; 520 } 521 else if (argc == 3) 522 { 523 Status = DisplayUser(argv[2]); 524 ConPrintf(StdOut, L"Status: %lu\n", Status); 525 return 0; 526 } 527 528 i = 2; 529 if (argv[i][0] != L'/') 530 { 531 lpUserName = argv[i]; 532 // ConPrintf(StdOut, L"User: %s\n", lpUserName); 533 i++; 534 } 535 536 if (argv[i][0] != L'/') 537 { 538 lpPassword = argv[i]; 539 // ConPrintf(StdOut, L"Password: %s\n", lpPassword); 540 i++; 541 } 542 543 for (j = i; j < argc; j++) 544 { 545 if (_wcsicmp(argv[j], L"/help") == 0) 546 { 547 ConResPuts(StdOut, IDS_USER_HELP); 548 return 0; 549 } 550 else if (_wcsicmp(argv[j], L"/add") == 0) 551 { 552 bAdd = TRUE; 553 } 554 else if (_wcsicmp(argv[j], L"/delete") == 0) 555 { 556 bDelete = TRUE; 557 } 558 else if (_wcsicmp(argv[j], L"/domain") == 0) 559 { 560 ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/DOMAIN"); 561 #if 0 562 bDomain = TRUE; 563 #endif 564 } 565 else if (_wcsicmp(argv[j], L"/random") == 0) 566 { 567 bRandomPassword = TRUE; 568 GenerateRandomPassword(&lpPassword, 569 &bPasswordAllocated); 570 } 571 } 572 573 if (bAdd && bDelete) 574 { 575 result = 1; 576 goto done; 577 } 578 579 /* Interactive password input */ 580 if (lpPassword != NULL && wcscmp(lpPassword, L"*") == 0) 581 { 582 ReadPassword(&lpPassword, 583 &bPasswordAllocated); 584 } 585 586 if (!bAdd && !bDelete) 587 { 588 /* Modify the user */ 589 Status = NetUserGetInfo(NULL, 590 lpUserName, 591 4, 592 (LPBYTE*)&pUserInfo); 593 if (Status != NERR_Success) 594 { 595 ConPrintf(StdOut, L"Status: %lu\n", Status); 596 result = 1; 597 goto done; 598 } 599 } 600 else if (bAdd && !bDelete) 601 { 602 /* Add the user */ 603 ZeroMemory(&UserInfo, sizeof(USER_INFO_4)); 604 605 UserInfo.usri4_name = lpUserName; 606 UserInfo.usri4_password = lpPassword; 607 UserInfo.usri4_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT; 608 609 pUserInfo = &UserInfo; 610 } 611 612 for (j = i; j < argc; j++) 613 { 614 if (_wcsnicmp(argv[j], L"/active:", 8) == 0) 615 { 616 p = &argv[i][8]; 617 if (_wcsicmp(p, L"yes") == 0) 618 { 619 pUserInfo->usri4_flags &= ~UF_ACCOUNTDISABLE; 620 } 621 else if (_wcsicmp(p, L"no") == 0) 622 { 623 pUserInfo->usri4_flags |= UF_ACCOUNTDISABLE; 624 } 625 else 626 { 627 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/ACTIVE"); 628 result = 1; 629 goto done; 630 } 631 } 632 else if (_wcsnicmp(argv[j], L"/comment:", 9) == 0) 633 { 634 pUserInfo->usri4_comment = &argv[j][9]; 635 } 636 else if (_wcsnicmp(argv[j], L"/countrycode:", 13) == 0) 637 { 638 p = &argv[i][13]; 639 value = wcstoul(p, &endptr, 10); 640 if (*endptr != 0) 641 { 642 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/COUNTRYCODE"); 643 result = 1; 644 goto done; 645 } 646 647 /* FIXME: verify the country code */ 648 649 pUserInfo->usri4_country_code = value; 650 } 651 else if (_wcsnicmp(argv[j], L"/expires:", 9) == 0) 652 { 653 p = &argv[i][9]; 654 if (_wcsicmp(p, L"never") == 0) 655 { 656 pUserInfo->usri4_acct_expires = TIMEQ_FOREVER; 657 } 658 else 659 { 660 /* FIXME: Parse the date */ 661 ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/EXPIRES"); 662 } 663 } 664 else if (_wcsnicmp(argv[j], L"/fullname:", 10) == 0) 665 { 666 pUserInfo->usri4_full_name = &argv[j][10]; 667 } 668 else if (_wcsnicmp(argv[j], L"/homedir:", 9) == 0) 669 { 670 pUserInfo->usri4_home_dir = &argv[j][9]; 671 } 672 else if (_wcsnicmp(argv[j], L"/passwordchg:", 13) == 0) 673 { 674 p = &argv[i][13]; 675 if (_wcsicmp(p, L"yes") == 0) 676 { 677 pUserInfo->usri4_flags &= ~UF_PASSWD_CANT_CHANGE; 678 } 679 else if (_wcsicmp(p, L"no") == 0) 680 { 681 pUserInfo->usri4_flags |= UF_PASSWD_CANT_CHANGE; 682 } 683 else 684 { 685 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/PASSWORDCHG"); 686 result = 1; 687 goto done; 688 } 689 } 690 else if (_wcsnicmp(argv[j], L"/passwordreq:", 13) == 0) 691 { 692 p = &argv[i][13]; 693 if (_wcsicmp(p, L"yes") == 0) 694 { 695 pUserInfo->usri4_flags &= ~UF_PASSWD_NOTREQD; 696 } 697 else if (_wcsicmp(p, L"no") == 0) 698 { 699 pUserInfo->usri4_flags |= UF_PASSWD_NOTREQD; 700 } 701 else 702 { 703 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/PASSWORDREQ"); 704 result = 1; 705 goto done; 706 } 707 } 708 else if (_wcsnicmp(argv[j], L"/profilepath:", 13) == 0) 709 { 710 pUserInfo->usri4_profile = &argv[j][13]; 711 } 712 else if (_wcsnicmp(argv[j], L"/scriptpath:", 12) == 0) 713 { 714 pUserInfo->usri4_script_path = &argv[j][12]; 715 } 716 else if (_wcsnicmp(argv[j], L"/times:", 7) == 0) 717 { 718 /* FIXME */ 719 ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/TIMES"); 720 } 721 else if (_wcsnicmp(argv[j], L"/usercomment:", 13) == 0) 722 { 723 pUserInfo->usri4_usr_comment = &argv[j][13]; 724 } 725 else if (_wcsnicmp(argv[j], L"/workstations:", 14) == 0) 726 { 727 p = &argv[i][14]; 728 if (wcscmp(p, L"*") == 0 || wcscmp(p, L"") == 0) 729 { 730 pUserInfo->usri4_workstations = NULL; 731 } 732 else 733 { 734 Status = BuildWorkstationsList(&pWorkstations, p); 735 if (Status == NERR_Success) 736 { 737 pUserInfo->usri4_workstations = pWorkstations; 738 } 739 else 740 { 741 ConPrintf(StdOut, L"Status %lu\n\n", Status); 742 result = 1; 743 goto done; 744 } 745 } 746 } 747 } 748 749 if (!bAdd && !bDelete) 750 { 751 /* Modify the user */ 752 Status = NetUserSetInfo(NULL, 753 lpUserName, 754 4, 755 (LPBYTE)pUserInfo, 756 NULL); 757 ConPrintf(StdOut, L"Status: %lu\n", Status); 758 } 759 else if (bAdd && !bDelete) 760 { 761 /* Add the user */ 762 Status = NetUserAdd(NULL, 763 4, 764 (LPBYTE)pUserInfo, 765 NULL); 766 ConPrintf(StdOut, L"Status: %lu\n", Status); 767 } 768 else if (!bAdd && bDelete) 769 { 770 /* Delete the user */ 771 Status = NetUserDel(NULL, 772 lpUserName); 773 ConPrintf(StdOut, L"Status: %lu\n", Status); 774 } 775 776 if (Status == NERR_Success && 777 lpPassword != NULL && 778 bRandomPassword == TRUE) 779 { 780 ConPrintf(StdOut, L"The password for %s is: %s\n", lpUserName, lpPassword); 781 } 782 783 done: 784 if (pWorkstations != NULL) 785 HeapFree(GetProcessHeap(), 0, pWorkstations); 786 787 if ((bPasswordAllocated == TRUE) && (lpPassword != NULL)) 788 HeapFree(GetProcessHeap(), 0, lpPassword); 789 790 if (!bAdd && !bDelete && pUserInfo != NULL) 791 NetApiBufferFree(pUserInfo); 792 793 if (result != 0) 794 { 795 ConResPuts(StdOut, IDS_GENERIC_SYNTAX); 796 ConResPuts(StdOut, IDS_USER_SYNTAX); 797 } 798 799 return result; 800 } 801 802 /* EOF */ 803