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 typedef struct _COUNTY_TABLE 14 { 15 DWORD dwCountryCode; 16 DWORD dwMessageId; 17 } COUNTRY_TABLE, *PCOUNTRY_TABLE; 18 19 20 static WCHAR szPasswordChars[] = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@#$%_-+:"; 21 static COUNTRY_TABLE CountryTable[] = 22 { { 0, 5080}, // System Default 23 { 1, 5081}, // United States 24 { 2, 5082}, // Canada (French) 25 { 3, 5083}, // Latin America 26 { 31, 5084}, // Netherlands 27 { 32, 5085}, // Belgium 28 { 33, 5086}, // France 29 { 34, 5090}, // Spain 30 { 39, 5087}, // Italy 31 { 41, 5088}, // Switzerland 32 { 44, 5089}, // United Kingdom 33 { 45, 5091}, // Denmark 34 { 46, 5092}, // Sweden 35 { 47, 5093}, // Norway 36 { 49, 5094}, // Germany 37 { 61, 5095}, // Australia 38 { 81, 5096}, // Japan 39 { 82, 5097}, // Korea 40 { 86, 5098}, // China (PRC) 41 { 88, 5099}, // Taiwan 42 { 99, 5100}, // Asia 43 {351, 5101}, // Portugal 44 {358, 5102}, // Finland 45 {785, 5103}, // Arabic 46 {972, 5104} }; // Hebrew 47 48 49 static 50 int 51 CompareInfo(const void *a, const void *b) 52 { 53 return _wcsicmp(((PUSER_INFO_0)a)->usri0_name, 54 ((PUSER_INFO_0)b)->usri0_name); 55 } 56 57 58 static 59 NET_API_STATUS 60 EnumerateUsers(VOID) 61 { 62 PUSER_INFO_0 pBuffer = NULL; 63 PSERVER_INFO_100 pServer = NULL; 64 DWORD dwRead = 0, dwTotal = 0; 65 DWORD i; 66 DWORD ResumeHandle = 0; 67 NET_API_STATUS Status; 68 69 Status = NetServerGetInfo(NULL, 70 100, 71 (LPBYTE*)&pServer); 72 if (Status != NERR_Success) 73 return Status; 74 75 ConPuts(StdOut, L"\n"); 76 PrintMessageStringV(4410, pServer->sv100_name); 77 ConPuts(StdOut, L"\n"); 78 PrintPadding(L'-', 79); 79 ConPuts(StdOut, L"\n"); 80 81 NetApiBufferFree(pServer); 82 83 do 84 { 85 Status = NetUserEnum(NULL, 86 0, 87 0, 88 (LPBYTE*)&pBuffer, 89 MAX_PREFERRED_LENGTH, 90 &dwRead, 91 &dwTotal, 92 &ResumeHandle); 93 if ((Status != NERR_Success) && (Status != ERROR_MORE_DATA)) 94 return Status; 95 96 qsort(pBuffer, 97 dwRead, 98 sizeof(PUSER_INFO_0), 99 CompareInfo); 100 101 for (i = 0; i < dwRead; i++) 102 { 103 if (pBuffer[i].usri0_name) 104 ConPrintf(StdOut, L"%s\n", pBuffer[i].usri0_name); 105 } 106 107 NetApiBufferFree(pBuffer); 108 pBuffer = NULL; 109 } 110 while (Status == ERROR_MORE_DATA); 111 112 return NERR_Success; 113 } 114 115 116 static 117 VOID 118 PrintDateTime(DWORD dwSeconds) 119 { 120 LARGE_INTEGER Time; 121 FILETIME FileTime; 122 SYSTEMTIME SystemTime; 123 WCHAR DateBuffer[80]; 124 WCHAR TimeBuffer[80]; 125 126 RtlSecondsSince1970ToTime(dwSeconds, &Time); 127 FileTime.dwLowDateTime = Time.u.LowPart; 128 FileTime.dwHighDateTime = Time.u.HighPart; 129 FileTimeToLocalFileTime(&FileTime, &FileTime); 130 FileTimeToSystemTime(&FileTime, &SystemTime); 131 132 GetDateFormatW(LOCALE_USER_DEFAULT, 133 DATE_SHORTDATE, 134 &SystemTime, 135 NULL, 136 DateBuffer, 137 80); 138 139 GetTimeFormatW(LOCALE_USER_DEFAULT, 140 TIME_NOSECONDS, 141 &SystemTime, 142 NULL, 143 TimeBuffer, 144 80); 145 146 ConPrintf(StdOut, L"%s %s", DateBuffer, TimeBuffer); 147 } 148 149 150 static 151 DWORD 152 GetTimeInSeconds(VOID) 153 { 154 LARGE_INTEGER Time; 155 FILETIME FileTime; 156 DWORD dwSeconds; 157 158 GetSystemTimeAsFileTime(&FileTime); 159 Time.u.LowPart = FileTime.dwLowDateTime; 160 Time.u.HighPart = FileTime.dwHighDateTime; 161 RtlTimeToSecondsSince1970(&Time, &dwSeconds); 162 163 return dwSeconds; 164 } 165 166 167 static 168 BOOL 169 GetCountryFromCountryCode( 170 _In_ DWORD dwCountryCode, 171 _In_ DWORD dwCountryLength, 172 _Out_ PWSTR szCountryBuffer) 173 { 174 DWORD i; 175 176 for (i = 0; i < ARRAYSIZE(CountryTable); i++) 177 { 178 if (CountryTable[i].dwCountryCode == dwCountryCode) 179 { 180 if (szCountryBuffer != NULL && dwCountryLength > 0) 181 { 182 FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, 183 hModuleNetMsg, 184 CountryTable[i].dwMessageId, 185 LANG_USER_DEFAULT, 186 szCountryBuffer, 187 dwCountryLength, 188 NULL); 189 } 190 191 return TRUE; 192 } 193 } 194 195 return FALSE; 196 } 197 198 199 static 200 NET_API_STATUS 201 DisplayUser(LPWSTR lpUserName) 202 { 203 PUSER_MODALS_INFO_0 pUserModals = NULL; 204 PUSER_INFO_4 pUserInfo = NULL; 205 PLOCALGROUP_USERS_INFO_0 pLocalGroupInfo = NULL; 206 PGROUP_USERS_INFO_0 pGroupInfo = NULL; 207 DWORD dwLocalGroupRead, dwLocalGroupTotal; 208 DWORD dwGroupRead, dwGroupTotal; 209 DWORD dwLastSet; 210 DWORD i; 211 WCHAR szCountry[40]; 212 INT nPaddedLength = 36; 213 NET_API_STATUS Status; 214 215 /* Modify the user */ 216 Status = NetUserGetInfo(NULL, 217 lpUserName, 218 4, 219 (LPBYTE*)&pUserInfo); 220 if (Status != NERR_Success) 221 return Status; 222 223 Status = NetUserModalsGet(NULL, 224 0, 225 (LPBYTE*)&pUserModals); 226 if (Status != NERR_Success) 227 goto done; 228 229 Status = NetUserGetLocalGroups(NULL, 230 lpUserName, 231 0, 232 0, 233 (LPBYTE*)&pLocalGroupInfo, 234 MAX_PREFERRED_LENGTH, 235 &dwLocalGroupRead, 236 &dwLocalGroupTotal); 237 if (Status != NERR_Success) 238 goto done; 239 240 Status = NetUserGetGroups(NULL, 241 lpUserName, 242 0, 243 (LPBYTE*)&pGroupInfo, 244 MAX_PREFERRED_LENGTH, 245 &dwGroupRead, 246 &dwGroupTotal); 247 if (Status != NERR_Success) 248 goto done; 249 250 PrintPaddedMessageString(4411, nPaddedLength); 251 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_name); 252 253 PrintPaddedMessageString(4412, nPaddedLength); 254 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_full_name); 255 256 PrintPaddedMessageString(4413, nPaddedLength); 257 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_comment); 258 259 PrintPaddedMessageString(4414, nPaddedLength); 260 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_usr_comment); 261 262 PrintPaddedMessageString(4416, nPaddedLength); 263 GetCountryFromCountryCode(pUserInfo->usri4_country_code, 264 ARRAYSIZE(szCountry), szCountry); 265 ConPrintf(StdOut, L"%03ld (%s)\n", pUserInfo->usri4_country_code, szCountry); 266 267 PrintPaddedMessageString(4419, nPaddedLength); 268 if (pUserInfo->usri4_flags & UF_ACCOUNTDISABLE) 269 ConResPuts(StdOut, IDS_GENERIC_NO); 270 else if (pUserInfo->usri4_flags & UF_LOCKOUT) 271 PrintMessageString(4440); 272 else 273 ConResPuts(StdOut, IDS_GENERIC_YES); 274 ConPuts(StdOut, L"\n"); 275 276 PrintPaddedMessageString(4420, nPaddedLength); 277 if (pUserInfo->usri4_acct_expires == TIMEQ_FOREVER) 278 ConResPuts(StdOut, IDS_GENERIC_NEVER); 279 else 280 PrintDateTime(pUserInfo->usri4_acct_expires); 281 ConPuts(StdOut, L"\n\n"); 282 283 PrintPaddedMessageString(4421, nPaddedLength); 284 dwLastSet = GetTimeInSeconds() - pUserInfo->usri4_password_age; 285 PrintDateTime(dwLastSet); 286 ConPuts(StdOut, L"\n"); 287 288 PrintPaddedMessageString(4422, nPaddedLength); 289 if ((pUserInfo->usri4_flags & UF_DONT_EXPIRE_PASSWD) || pUserModals->usrmod0_max_passwd_age == TIMEQ_FOREVER) 290 ConResPuts(StdOut, IDS_GENERIC_NEVER); 291 else 292 PrintDateTime(dwLastSet + pUserModals->usrmod0_max_passwd_age); 293 ConPuts(StdOut, L"\n"); 294 295 PrintPaddedMessageString(4423, nPaddedLength); 296 PrintDateTime(dwLastSet + pUserModals->usrmod0_min_passwd_age); 297 ConPuts(StdOut, L"\n"); 298 299 PrintPaddedMessageString(4437, nPaddedLength); 300 ConResPuts(StdOut, (pUserInfo->usri4_flags & UF_PASSWD_NOTREQD) ? IDS_GENERIC_NO : IDS_GENERIC_YES); 301 ConPuts(StdOut, L"\n"); 302 303 PrintPaddedMessageString(4438, nPaddedLength); 304 ConResPuts(StdOut, (pUserInfo->usri4_flags & UF_PASSWD_CANT_CHANGE) ? IDS_GENERIC_NO : IDS_GENERIC_YES); 305 ConPuts(StdOut, L"\n\n"); 306 307 PrintPaddedMessageString(4424, nPaddedLength); 308 if (pUserInfo->usri4_workstations == NULL || wcslen(pUserInfo->usri4_workstations) == 0) 309 ConResPuts(StdOut, IDS_GENERIC_ALL); 310 else 311 ConPrintf(StdOut, L"%s", pUserInfo->usri4_workstations); 312 ConPuts(StdOut, L"\n"); 313 314 PrintPaddedMessageString(4429, nPaddedLength); 315 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_script_path); 316 317 PrintPaddedMessageString(4439, nPaddedLength); 318 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_profile); 319 320 PrintPaddedMessageString(4436, nPaddedLength); 321 ConPrintf(StdOut, L"%s\n", pUserInfo->usri4_home_dir); 322 323 PrintPaddedMessageString(4430, nPaddedLength); 324 if (pUserInfo->usri4_last_logon == 0) 325 ConResPuts(StdOut, IDS_GENERIC_NEVER); 326 else 327 PrintDateTime(pUserInfo->usri4_last_logon); 328 ConPuts(StdOut, L"\n\n"); 329 330 PrintPaddedMessageString(4432, nPaddedLength); 331 if (pUserInfo->usri4_logon_hours == NULL) 332 ConResPuts(StdOut, IDS_GENERIC_ALL); 333 ConPuts(StdOut, L"\n\n"); 334 335 ConPuts(StdOut, L"\n"); 336 PrintPaddedMessageString(4427, nPaddedLength); 337 if (dwLocalGroupTotal != 0 && pLocalGroupInfo != NULL) 338 { 339 for (i = 0; i < dwLocalGroupTotal; i++) 340 { 341 if (i != 0) 342 PrintPadding(L' ', nPaddedLength); 343 ConPrintf(StdOut, L"*%s\n", pLocalGroupInfo[i].lgrui0_name); 344 } 345 } 346 else 347 { 348 ConPuts(StdOut, L"\n"); 349 } 350 351 PrintPaddedMessageString(4431, nPaddedLength); 352 if (dwGroupTotal != 0 && pGroupInfo != NULL) 353 { 354 for (i = 0; i < dwGroupTotal; i++) 355 { 356 if (i != 0) 357 PrintPadding(L' ', nPaddedLength); 358 ConPrintf(StdOut, L"*%s\n", pGroupInfo[i].grui0_name); 359 } 360 } 361 else 362 { 363 ConPuts(StdOut, L"\n"); 364 } 365 366 done: 367 if (pGroupInfo != NULL) 368 NetApiBufferFree(pGroupInfo); 369 370 if (pLocalGroupInfo != NULL) 371 NetApiBufferFree(pLocalGroupInfo); 372 373 if (pUserModals != NULL) 374 NetApiBufferFree(pUserModals); 375 376 if (pUserInfo != NULL) 377 NetApiBufferFree(pUserInfo); 378 379 return NERR_Success; 380 } 381 382 383 static 384 VOID 385 ReadPassword( 386 LPWSTR *lpPassword, 387 LPBOOL lpAllocated) 388 { 389 WCHAR szPassword1[PWLEN + 1]; 390 WCHAR szPassword2[PWLEN + 1]; 391 LPWSTR ptr; 392 393 *lpAllocated = FALSE; 394 395 while (TRUE) 396 { 397 ConResPuts(StdOut, IDS_USER_ENTER_PASSWORD1); 398 ReadFromConsole(szPassword1, PWLEN + 1, FALSE); 399 ConPuts(StdOut, L"\n"); 400 401 ConResPuts(StdOut, IDS_USER_ENTER_PASSWORD2); 402 ReadFromConsole(szPassword2, PWLEN + 1, FALSE); 403 ConPuts(StdOut, L"\n"); 404 405 if (wcslen(szPassword1) == wcslen(szPassword2) && 406 wcscmp(szPassword1, szPassword2) == 0) 407 { 408 ptr = HeapAlloc(GetProcessHeap(), 409 0, 410 (wcslen(szPassword1) + 1) * sizeof(WCHAR)); 411 if (ptr != NULL) 412 { 413 wcscpy(ptr, szPassword1); 414 *lpPassword = ptr; 415 *lpAllocated = TRUE; 416 return; 417 } 418 } 419 else 420 { 421 ConPuts(StdOut, L"\n"); 422 ConResPuts(StdOut, IDS_USER_NO_PASSWORD_MATCH); 423 ConPuts(StdOut, L"\n"); 424 *lpPassword = NULL; 425 } 426 } 427 } 428 429 430 static 431 VOID 432 GenerateRandomPassword( 433 LPWSTR *lpPassword, 434 LPBOOL lpAllocated) 435 { 436 LPWSTR pPassword = NULL; 437 INT nCharsLen, i, nLength = 8; 438 439 srand(GetTickCount()); 440 441 pPassword = HeapAlloc(GetProcessHeap(), 442 HEAP_ZERO_MEMORY, 443 (nLength + 1) * sizeof(WCHAR)); 444 if (pPassword == NULL) 445 return; 446 447 nCharsLen = wcslen(szPasswordChars); 448 449 for (i = 0; i < nLength; i++) 450 { 451 pPassword[i] = szPasswordChars[rand() % nCharsLen]; 452 } 453 454 *lpPassword = pPassword; 455 *lpAllocated = TRUE; 456 } 457 458 459 static 460 NET_API_STATUS 461 BuildWorkstationsList( 462 _Out_ PWSTR *pWorkstationsList, 463 _In_ PWSTR pRaw) 464 { 465 BOOL isLastSep, isSep; 466 INT i, j; 467 WCHAR c; 468 INT nLength = 0; 469 INT nArgs = 0; 470 INT nRawLength; 471 PWSTR pList; 472 473 /* Check for invalid characters in the raw string */ 474 if (wcspbrk(pRaw, L"/[]=?\\+:.") != NULL) 475 return 3952; 476 477 /* Count the number of workstations in the list and 478 * the required buffer size */ 479 isLastSep = FALSE; 480 isSep = FALSE; 481 nRawLength = wcslen(pRaw); 482 for (i = 0; i < nRawLength; i++) 483 { 484 c = pRaw[i]; 485 if (c == L',' || c == L';') 486 isSep = TRUE; 487 488 if (isSep == TRUE) 489 { 490 if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1)) 491 nLength++; 492 } 493 else 494 { 495 nLength++; 496 497 if (isLastSep == TRUE || (isLastSep == FALSE && i == 0)) 498 nArgs++; 499 } 500 501 isLastSep = isSep; 502 isSep = FALSE; 503 } 504 505 nLength++; 506 507 /* Leave, if there are no workstations in the list */ 508 if (nArgs == 0) 509 { 510 pWorkstationsList = NULL; 511 return NERR_Success; 512 } 513 514 /* Fail if there are more than eight workstations in the list */ 515 if (nArgs > 8) 516 return 3951; 517 518 /* Allocate the buffer for the clean workstation list */ 519 pList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLength * sizeof(WCHAR)); 520 if (pList == NULL) 521 return ERROR_NOT_ENOUGH_MEMORY; 522 523 /* Build the clean workstation list */ 524 isLastSep = FALSE; 525 isSep = FALSE; 526 nRawLength = wcslen(pRaw); 527 for (i = 0, j = 0; i < nRawLength; i++) 528 { 529 c = pRaw[i]; 530 if (c == L',' || c == L';') 531 isSep = TRUE; 532 533 if (isSep == TRUE) 534 { 535 if ((isLastSep == FALSE) && (i != 0) && (i != nRawLength - 1)) 536 { 537 pList[j] = L','; 538 j++; 539 } 540 } 541 else 542 { 543 pList[j] = c; 544 j++; 545 546 if (isLastSep == TRUE || (isLastSep == FALSE && i == 0)) 547 nArgs++; 548 } 549 550 isLastSep = isSep; 551 isSep = FALSE; 552 } 553 554 *pWorkstationsList = pList; 555 556 return NERR_Success; 557 } 558 559 560 static 561 BOOL 562 ReadNumber( 563 PWSTR *s, 564 PWORD pwValue) 565 { 566 if (!iswdigit(**s)) 567 return FALSE; 568 569 while (iswdigit(**s)) 570 { 571 *pwValue = *pwValue * 10 + **s - L'0'; 572 (*s)++; 573 } 574 575 return TRUE; 576 } 577 578 579 static 580 BOOL 581 ReadSeparator( 582 PWSTR *s) 583 { 584 if (**s == L'/' || **s == L'.') 585 { 586 (*s)++; 587 return TRUE; 588 } 589 590 return FALSE; 591 } 592 593 594 static 595 BOOL 596 ParseDate( 597 PWSTR s, 598 PULONG pSeconds) 599 { 600 SYSTEMTIME SystemTime = {0}; 601 FILETIME LocalFileTime, FileTime; 602 LARGE_INTEGER Time; 603 INT nDateFormat = 0; 604 PWSTR p = s; 605 606 if (!*s) 607 return FALSE; 608 609 GetLocaleInfoW(LOCALE_USER_DEFAULT, 610 LOCALE_IDATE, 611 (PWSTR)&nDateFormat, 612 sizeof(INT)); 613 614 switch (nDateFormat) 615 { 616 case 0: /* mmddyy */ 617 default: 618 if (!ReadNumber(&p, &SystemTime.wMonth)) 619 return FALSE; 620 if (!ReadSeparator(&p)) 621 return FALSE; 622 if (!ReadNumber(&p, &SystemTime.wDay)) 623 return FALSE; 624 if (!ReadSeparator(&p)) 625 return FALSE; 626 if (!ReadNumber(&p, &SystemTime.wYear)) 627 return FALSE; 628 break; 629 630 case 1: /* ddmmyy */ 631 if (!ReadNumber(&p, &SystemTime.wDay)) 632 return FALSE; 633 if (!ReadSeparator(&p)) 634 return FALSE; 635 if (!ReadNumber(&p, &SystemTime.wMonth)) 636 return FALSE; 637 if (!ReadSeparator(&p)) 638 return FALSE; 639 if (!ReadNumber(&p, &SystemTime.wYear)) 640 return FALSE; 641 break; 642 643 case 2: /* yymmdd */ 644 if (!ReadNumber(&p, &SystemTime.wYear)) 645 return FALSE; 646 if (!ReadSeparator(&p)) 647 return FALSE; 648 if (!ReadNumber(&p, &SystemTime.wMonth)) 649 return FALSE; 650 if (!ReadSeparator(&p)) 651 return FALSE; 652 if (!ReadNumber(&p, &SystemTime.wDay)) 653 return FALSE; 654 break; 655 } 656 657 /* if only entered two digits: */ 658 /* assume 2000's if value less than 80 */ 659 /* assume 1900's if value greater or equal 80 */ 660 if (SystemTime.wYear <= 99) 661 { 662 if (SystemTime.wYear >= 80) 663 SystemTime.wYear += 1900; 664 else 665 SystemTime.wYear += 2000; 666 } 667 668 if (!SystemTimeToFileTime(&SystemTime, &LocalFileTime)) 669 return FALSE; 670 671 if (!LocalFileTimeToFileTime(&LocalFileTime, &FileTime)) 672 return FALSE; 673 674 Time.u.LowPart = FileTime.dwLowDateTime; 675 Time.u.HighPart = FileTime.dwHighDateTime; 676 677 if (!RtlTimeToSecondsSince1970(&Time, pSeconds)) 678 return FALSE; 679 680 return TRUE; 681 } 682 683 684 INT 685 cmdUser( 686 INT argc, 687 WCHAR **argv) 688 { 689 INT i, j; 690 INT result = 0; 691 BOOL bAdd = FALSE; 692 BOOL bDelete = FALSE; 693 #if 0 694 BOOL bDomain = FALSE; 695 #endif 696 BOOL bRandomPassword = FALSE; 697 LPWSTR lpUserName = NULL; 698 LPWSTR lpPassword = NULL; 699 PUSER_INFO_4 pUserInfo = NULL; 700 USER_INFO_4 UserInfo; 701 LPWSTR pWorkstations = NULL; 702 LPWSTR p; 703 LPWSTR endptr; 704 DWORD value; 705 BOOL bPasswordAllocated = FALSE; 706 NET_API_STATUS Status; 707 708 i = 2; 709 if ((i < argc) && (argv[i][0] != L'/')) 710 { 711 lpUserName = argv[i]; 712 // ConPrintf(StdOut, L"User: %s\n", lpUserName); 713 i++; 714 } 715 716 if ((i < argc) && (argv[i][0] != L'/')) 717 { 718 lpPassword = argv[i]; 719 // ConPrintf(StdOut, L"Password: %s\n", lpPassword); 720 i++; 721 } 722 723 for (j = i; j < argc; j++) 724 { 725 if (_wcsicmp(argv[j], L"/help") == 0) 726 { 727 PrintNetMessage(MSG_USER_HELP); 728 return 0; 729 } 730 else if (_wcsicmp(argv[j], L"/add") == 0) 731 { 732 bAdd = TRUE; 733 } 734 else if (_wcsicmp(argv[j], L"/delete") == 0) 735 { 736 bDelete = TRUE; 737 } 738 else if (_wcsicmp(argv[j], L"/domain") == 0) 739 { 740 ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/DOMAIN"); 741 #if 0 742 bDomain = TRUE; 743 #endif 744 } 745 else if (_wcsicmp(argv[j], L"/random") == 0) 746 { 747 bRandomPassword = TRUE; 748 GenerateRandomPassword(&lpPassword, 749 &bPasswordAllocated); 750 } 751 } 752 753 if (lpUserName == NULL && lpPassword == NULL) 754 { 755 Status = EnumerateUsers(); 756 ConPrintf(StdOut, L"Status: %lu\n", Status); 757 return 0; 758 } 759 else if (lpUserName != NULL && lpPassword == NULL) 760 { 761 Status = DisplayUser(lpUserName); 762 ConPrintf(StdOut, L"Status: %lu\n", Status); 763 return 0; 764 } 765 766 if (bAdd && bDelete) 767 { 768 result = 1; 769 goto done; 770 } 771 772 /* Interactive password input */ 773 if (lpPassword != NULL && wcscmp(lpPassword, L"*") == 0) 774 { 775 ReadPassword(&lpPassword, 776 &bPasswordAllocated); 777 } 778 779 if (!bAdd && !bDelete) 780 { 781 /* Modify the user */ 782 Status = NetUserGetInfo(NULL, 783 lpUserName, 784 4, 785 (LPBYTE*)&pUserInfo); 786 if (Status != NERR_Success) 787 { 788 ConPrintf(StdOut, L"Status: %lu\n", Status); 789 result = 1; 790 goto done; 791 } 792 } 793 else if (bAdd && !bDelete) 794 { 795 /* Add the user */ 796 ZeroMemory(&UserInfo, sizeof(USER_INFO_4)); 797 798 UserInfo.usri4_name = lpUserName; 799 UserInfo.usri4_password = lpPassword; 800 UserInfo.usri4_flags = UF_SCRIPT | UF_NORMAL_ACCOUNT; 801 UserInfo.usri4_acct_expires = TIMEQ_FOREVER; 802 UserInfo.usri4_primary_group_id = DOMAIN_GROUP_RID_USERS; 803 804 pUserInfo = &UserInfo; 805 } 806 807 for (j = i; j < argc; j++) 808 { 809 if (_wcsnicmp(argv[j], L"/active:", 8) == 0) 810 { 811 p = &argv[i][8]; 812 if (_wcsicmp(p, L"yes") == 0) 813 { 814 pUserInfo->usri4_flags &= ~UF_ACCOUNTDISABLE; 815 } 816 else if (_wcsicmp(p, L"no") == 0) 817 { 818 pUserInfo->usri4_flags |= UF_ACCOUNTDISABLE; 819 } 820 else 821 { 822 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/ACTIVE"); 823 result = 1; 824 goto done; 825 } 826 } 827 else if (_wcsnicmp(argv[j], L"/comment:", 9) == 0) 828 { 829 pUserInfo->usri4_comment = &argv[j][9]; 830 } 831 else if (_wcsnicmp(argv[j], L"/countrycode:", 13) == 0) 832 { 833 p = &argv[i][13]; 834 value = wcstoul(p, &endptr, 10); 835 if (*endptr != 0) 836 { 837 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/COUNTRYCODE"); 838 result = 1; 839 goto done; 840 } 841 842 /* Verify the country code */ 843 if (GetCountryFromCountryCode(value, 0, NULL)) 844 pUserInfo->usri4_country_code = value; 845 } 846 else if (_wcsnicmp(argv[j], L"/expires:", 9) == 0) 847 { 848 p = &argv[i][9]; 849 if (_wcsicmp(p, L"never") == 0) 850 { 851 pUserInfo->usri4_acct_expires = TIMEQ_FOREVER; 852 } 853 else if (!ParseDate(p, &pUserInfo->usri4_acct_expires)) 854 { 855 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/EXPIRES"); 856 result = 1; 857 goto done; 858 } 859 } 860 else if (_wcsnicmp(argv[j], L"/fullname:", 10) == 0) 861 { 862 pUserInfo->usri4_full_name = &argv[j][10]; 863 } 864 else if (_wcsnicmp(argv[j], L"/homedir:", 9) == 0) 865 { 866 pUserInfo->usri4_home_dir = &argv[j][9]; 867 } 868 else if (_wcsnicmp(argv[j], L"/passwordchg:", 13) == 0) 869 { 870 p = &argv[i][13]; 871 if (_wcsicmp(p, L"yes") == 0) 872 { 873 pUserInfo->usri4_flags &= ~UF_PASSWD_CANT_CHANGE; 874 } 875 else if (_wcsicmp(p, L"no") == 0) 876 { 877 pUserInfo->usri4_flags |= UF_PASSWD_CANT_CHANGE; 878 } 879 else 880 { 881 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/PASSWORDCHG"); 882 result = 1; 883 goto done; 884 } 885 } 886 else if (_wcsnicmp(argv[j], L"/passwordreq:", 13) == 0) 887 { 888 p = &argv[i][13]; 889 if (_wcsicmp(p, L"yes") == 0) 890 { 891 pUserInfo->usri4_flags &= ~UF_PASSWD_NOTREQD; 892 } 893 else if (_wcsicmp(p, L"no") == 0) 894 { 895 pUserInfo->usri4_flags |= UF_PASSWD_NOTREQD; 896 } 897 else 898 { 899 ConResPrintf(StdErr, IDS_ERROR_INVALID_OPTION_VALUE, L"/PASSWORDREQ"); 900 result = 1; 901 goto done; 902 } 903 } 904 else if (_wcsnicmp(argv[j], L"/profilepath:", 13) == 0) 905 { 906 pUserInfo->usri4_profile = &argv[j][13]; 907 } 908 else if (_wcsnicmp(argv[j], L"/scriptpath:", 12) == 0) 909 { 910 pUserInfo->usri4_script_path = &argv[j][12]; 911 } 912 else if (_wcsnicmp(argv[j], L"/times:", 7) == 0) 913 { 914 /* FIXME */ 915 ConResPrintf(StdErr, IDS_ERROR_OPTION_NOT_SUPPORTED, L"/TIMES"); 916 } 917 else if (_wcsnicmp(argv[j], L"/usercomment:", 13) == 0) 918 { 919 pUserInfo->usri4_usr_comment = &argv[j][13]; 920 } 921 else if (_wcsnicmp(argv[j], L"/workstations:", 14) == 0) 922 { 923 p = &argv[i][14]; 924 if (wcscmp(p, L"*") == 0 || wcscmp(p, L"") == 0) 925 { 926 pUserInfo->usri4_workstations = NULL; 927 } 928 else 929 { 930 Status = BuildWorkstationsList(&pWorkstations, p); 931 if (Status == NERR_Success) 932 { 933 pUserInfo->usri4_workstations = pWorkstations; 934 } 935 else 936 { 937 ConPrintf(StdOut, L"Status %lu\n\n", Status); 938 result = 1; 939 goto done; 940 } 941 } 942 } 943 } 944 945 if (!bAdd && !bDelete) 946 { 947 /* Modify the user */ 948 Status = NetUserSetInfo(NULL, 949 lpUserName, 950 4, 951 (LPBYTE)pUserInfo, 952 NULL); 953 ConPrintf(StdOut, L"Status: %lu\n", Status); 954 } 955 else if (bAdd && !bDelete) 956 { 957 /* Add the user */ 958 Status = NetUserAdd(NULL, 959 4, 960 (LPBYTE)pUserInfo, 961 NULL); 962 ConPrintf(StdOut, L"Status: %lu\n", Status); 963 } 964 else if (!bAdd && bDelete) 965 { 966 /* Delete the user */ 967 Status = NetUserDel(NULL, 968 lpUserName); 969 ConPrintf(StdOut, L"Status: %lu\n", Status); 970 } 971 972 if (Status == NERR_Success && 973 lpPassword != NULL && 974 bRandomPassword == TRUE) 975 { 976 ConPrintf(StdOut, L"The password for %s is: %s\n", lpUserName, lpPassword); 977 } 978 979 done: 980 if (pWorkstations != NULL) 981 HeapFree(GetProcessHeap(), 0, pWorkstations); 982 983 if ((bPasswordAllocated == TRUE) && (lpPassword != NULL)) 984 HeapFree(GetProcessHeap(), 0, lpPassword); 985 986 if (!bAdd && !bDelete && pUserInfo != NULL) 987 NetApiBufferFree(pUserInfo); 988 989 if (result != 0) 990 { 991 ConResPuts(StdOut, IDS_GENERIC_SYNTAX); 992 PrintNetMessage(MSG_USER_SYNTAX); 993 } 994 995 return result; 996 } 997 998 /* EOF */ 999