1 /* 2 * PROJECT: ReactOS Whoami 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/applications/cmdutils/whoami/whoami.c 5 * PURPOSE: Displays information about the current local user, groups and privileges. 6 * PROGRAMMERS: Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com) 7 */ 8 9 #define SECURITY_WIN32 10 #include <security.h> 11 #include <sddl.h> 12 #include <strsafe.h> 13 14 #include <conutils.h> 15 16 #include "resource.h" 17 18 #define wprintf(...) ConPrintf(StdOut, ##__VA_ARGS__) 19 20 BOOL NoHeader = FALSE; 21 UINT NoHeaderArgCount = 0; 22 UINT PrintFormatArgCount = 0; 23 24 enum 25 { 26 undefined, 27 table, 28 list, 29 csv 30 } PrintFormat = undefined; 31 32 33 BOOL GetArgument(WCHAR* arg, int argc, WCHAR* argv[]) 34 { 35 int i; 36 37 if (!arg) 38 return FALSE; 39 40 for (i = 1; i < argc; i++) 41 { 42 if (wcsicmp(argv[i], arg) == 0) 43 return TRUE; 44 } 45 46 return FALSE; 47 } 48 49 /* blanking out the accepted modifiers will make filtering easier later on */ 50 void BlankArgument(int argc, WCHAR* argv[]) 51 { 52 argv[argc] = L""; 53 } 54 55 /* helper functions; let's keep it tidy to avoid redundancies */ 56 57 LPWSTR WhoamiGetUser(EXTENDED_NAME_FORMAT NameFormat) 58 { 59 LPWSTR UsrBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH); 60 ULONG UsrSiz = MAX_PATH; 61 62 if (UsrBuf == NULL) 63 return NULL; 64 65 if (GetUserNameExW(NameFormat, UsrBuf, &UsrSiz)) 66 { 67 CharLowerW(UsrBuf); 68 return UsrBuf; 69 } 70 71 HeapFree(GetProcessHeap(), 0, UsrBuf); 72 return NULL; 73 } 74 75 BOOL WhoamiFree(VOID* Buffer) 76 { 77 return HeapFree(GetProcessHeap(), 0, Buffer); 78 } 79 80 81 VOID* WhoamiGetTokenInfo(TOKEN_INFORMATION_CLASS TokenType) 82 { 83 HANDLE hToken = 0; 84 DWORD dwLength = 0; 85 VOID* pTokenInfo = 0; 86 87 if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken)) 88 { 89 GetTokenInformation(hToken, 90 TokenType, 91 NULL, 92 dwLength, 93 &dwLength); 94 95 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 96 { 97 pTokenInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); 98 if (pTokenInfo == NULL) 99 { 100 wprintf(L"ERROR: not enough memory to allocate the token structure.\r\n"); 101 exit(1); 102 } 103 } 104 105 if (!GetTokenInformation(hToken, TokenType, 106 (LPVOID)pTokenInfo, 107 dwLength, 108 &dwLength)) 109 { 110 wprintf(L"ERROR 0x%x: could not get token information.\r\n", GetLastError()); 111 WhoamiFree(pTokenInfo); 112 exit(1); 113 } 114 115 CloseHandle(hToken); 116 } 117 118 return pTokenInfo; 119 } 120 121 LPWSTR WhoamiLoadRcString(INT ResId) 122 { 123 #define RC_STRING_MAX_SIZE 850 124 static WCHAR TmpBuffer[RC_STRING_MAX_SIZE]; 125 126 LoadStringW(GetModuleHandleW(NULL), ResId, TmpBuffer, RC_STRING_MAX_SIZE); 127 128 return TmpBuffer; 129 } 130 131 void WhoamiPrintHeader(int HeaderId) 132 { 133 PWSTR Header = WhoamiLoadRcString(HeaderId); 134 DWORD Length = wcslen(Header); 135 136 if (NoHeader || PrintFormat == csv) 137 return; 138 139 wprintf(L"\n%s\n", Header); 140 141 while (Length--) 142 wprintf(L"-"); 143 144 wprintf(L"\n\n"); 145 } 146 147 typedef struct 148 { 149 UINT Rows; 150 UINT Cols; 151 LPWSTR Content[1]; 152 } WhoamiTable; 153 154 /* create and prepare a new table for printing */ 155 WhoamiTable *WhoamiAllocTable(UINT Rows, UINT Cols) 156 { 157 WhoamiTable *pTable = HeapAlloc(GetProcessHeap(), 158 HEAP_ZERO_MEMORY, 159 sizeof(WhoamiTable) + sizeof(LPWSTR) * Rows * Cols); 160 161 // wprintf(L"DEBUG: Allocating %dx%d elem table for printing.\r\n\r\n", Rows, Cols); 162 163 if (!pTable) 164 { 165 wprintf(L"ERROR: Not enough memory for displaying the table."); 166 exit(1); 167 } 168 169 pTable->Rows = Rows; 170 pTable->Cols = Cols; 171 172 return pTable; 173 } 174 175 /* allocate and fill a new entry in the table */ 176 void WhoamiSetTable(WhoamiTable *pTable, WCHAR *Entry, UINT Row, UINT Col) 177 { 178 LPWSTR Target = HeapAlloc(GetProcessHeap(), 179 HEAP_ZERO_MEMORY, 180 1 + wcslen(Entry) * sizeof(Entry[0])); 181 182 // wprintf(L"DEBUG: Setting table value '%lp' '%ls' for %lu %lu.\n", entry, entry, row, col); 183 184 if (!Target) 185 exit(1); 186 187 wcscpy(Target, Entry); 188 189 pTable->Content[Row * pTable->Cols + Col] = Target; 190 } 191 192 /* fill a new entry in the table */ 193 void WhoamiSetTableDyn(WhoamiTable *pTable, WCHAR *Entry, UINT Row, UINT Col) 194 { 195 pTable->Content[Row * pTable->Cols + Col] = Entry; 196 } 197 198 /* print and deallocate the table */ 199 void WhoamiPrintTable(WhoamiTable *pTable) 200 { 201 UINT i, j; 202 UINT CurRow, CurCol; 203 UINT *ColLength; 204 205 206 if (!pTable) 207 { 208 wprintf(L"ERROR: The table passed for display is empty."); 209 exit(1); 210 } 211 212 /* if we are going to print a *list* or *table*; take note of the total 213 column size, as we will need it later on when printing them in a tabular 214 fashion, according to their windows counterparts */ 215 216 if (PrintFormat != csv) 217 { 218 ColLength = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UINT) * pTable->Cols); 219 220 if (PrintFormat == list) 221 { 222 for (j = 0; j < pTable->Cols; j++) 223 if (pTable->Content[j]) 224 { 225 UINT ThisLength = wcslen(pTable->Content[j]); 226 227 /* now that we're here, seize the opportunity and add those pesky ":" */ 228 pTable->Content[j][ThisLength++] = L':'; 229 pTable->Content[j][ThisLength] = UNICODE_NULL; 230 231 ColLength[0] = max(ThisLength, ColLength[0]); 232 } 233 } 234 else 235 { 236 for (j = 0; j < pTable->Cols; j++) 237 for (i = 0; i < pTable->Rows; i++) 238 if (pTable->Content[i * pTable->Cols + j]) 239 { 240 UINT ThisLength = wcslen(pTable->Content[i * pTable->Cols + j]); 241 ColLength[j] = max(ThisLength, ColLength[j]); 242 } 243 } 244 } 245 246 switch (PrintFormat) 247 { 248 case csv: 249 { 250 for (i = 0; i < pTable->Rows; i++) 251 { 252 if (!pTable->Content[i * pTable->Cols]) 253 continue; 254 255 /* if the user especified /nh then skip the column labels */ 256 if (NoHeader && i == 0) 257 continue; 258 259 for (j = 0; j < pTable->Cols; j++) 260 { 261 if (pTable->Content[i * pTable->Cols + j]) 262 { 263 wprintf(L"\"%s\"%s", 264 pTable->Content[i * pTable->Cols + j], 265 (j+1 < pTable->Cols ? L"," : L"")); 266 } 267 } 268 wprintf(L"\n"); 269 } 270 271 break; 272 273 } 274 275 case list: 276 { 277 UINT FinalRow = 0; 278 279 /* fixme: we need to do two passes to find out which entry is the last one shown, or not null this is not exactly optimal */ 280 for (CurRow = 1; CurRow < pTable->Rows; CurRow++) 281 { 282 /* if the first member of this row isn't available, then forget it */ 283 if (!pTable->Content[CurRow * pTable->Cols]) 284 continue; 285 286 FinalRow = CurRow; 287 } 288 289 for (CurRow = 1; CurRow < pTable->Rows; CurRow++) 290 { 291 /* if the first member of this row isn't available, then forget it */ 292 if (!pTable->Content[CurRow * pTable->Cols]) 293 continue; 294 295 /* if the user especified /nh then skip the column labels */ 296 if (NoHeader && i == 0) 297 continue; 298 299 for (CurCol = 0; CurCol < pTable->Cols; CurCol++) 300 { 301 wprintf(L"%-*s %s\n", 302 ColLength[0], 303 pTable->Content[CurCol], 304 pTable->Content[CurRow * pTable->Cols + CurCol]); 305 } 306 307 /* don't add two carriage returns at the very end */ 308 if (CurRow != FinalRow) 309 wprintf(L"\n"); 310 } 311 312 break; 313 } 314 315 316 case table: 317 default: 318 { 319 for (i = 0; i < pTable->Rows; i++) 320 { 321 /* if the first member of this row isn't available, then forget it */ 322 if (!pTable->Content[i * pTable->Cols]) 323 continue; 324 325 /* if the user especified /nh then skip the column labels too */ 326 if (NoHeader && i == 0) 327 continue; 328 329 for (j = 0; j < pTable->Cols; j++) 330 { 331 if (pTable->Content[i * pTable->Cols + j]) 332 { 333 wprintf(L"%-*s ", ColLength[j], pTable->Content[i * pTable->Cols + j]); 334 } 335 } 336 wprintf(L"\n"); 337 338 /* add the cute underline thingie for the table header */ 339 if (i == 0) 340 { 341 for (j = 0; j < pTable->Cols; j++) 342 { 343 DWORD Length = ColLength[j]; 344 345 while (Length--) 346 wprintf(L"="); 347 348 /* a spacing between all the columns except for the last one */ 349 if (pTable->Cols != (i + 1)) 350 wprintf(L" "); 351 } 352 353 wprintf(L"\n"); 354 } 355 } 356 357 } 358 } 359 360 /* fixme: when many tables are displayed in a single run we 361 have to sandwich carriage returns in between. */ 362 // if (!final_entry) 363 wprintf(L"\n"); 364 365 for (i = 0; i < pTable->Rows; i++) 366 for (j = 0; j < pTable->Cols; j++) 367 WhoamiFree(pTable->Content[i * pTable->Cols + j]); 368 369 WhoamiFree(pTable); 370 371 if (PrintFormat != csv) 372 HeapFree(GetProcessHeap(), 0, ColLength); 373 } 374 375 int WhoamiLogonId(void) 376 { 377 PTOKEN_GROUPS pGroupInfo = (PTOKEN_GROUPS) WhoamiGetTokenInfo(TokenGroups); 378 DWORD dwIndex = 0; 379 LPWSTR pSidStr = 0; 380 PSID pSid = 0; 381 382 if (pGroupInfo == NULL) 383 return 0; 384 385 /* lets see if we can find the logon SID in that list, should be there */ 386 for (dwIndex = 0; dwIndex < pGroupInfo->GroupCount; dwIndex++) 387 { 388 if ((pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) 389 { 390 pSid = pGroupInfo->Groups[dwIndex].Sid; 391 } 392 } 393 394 if (pSid == 0) 395 { 396 WhoamiFree(pGroupInfo); 397 wprintf(L"ERROR: Couldn't find the logon SID.\n"); 398 return 1; 399 } 400 if (!ConvertSidToStringSidW(pSid, &pSidStr)) 401 { 402 WhoamiFree(pGroupInfo); 403 wprintf(L"ERROR: Couldn't convert the logon SID to a string.\n"); 404 return 1; 405 } 406 else 407 { 408 /* let's show our converted logon SID */ 409 wprintf(L"%s\n", pSidStr); 410 } 411 412 /* cleanup our allocations */ 413 LocalFree(pSidStr); 414 WhoamiFree(pGroupInfo); 415 416 return 0; 417 } 418 419 int WhoamiUser(void) 420 { 421 PTOKEN_USER pUserInfo = (PTOKEN_USER) WhoamiGetTokenInfo(TokenUser); 422 LPWSTR pUserStr = NULL; 423 LPWSTR pSidStr = NULL; 424 WhoamiTable *UserTable = NULL; 425 426 if (pUserInfo == NULL) 427 { 428 return 1; 429 } 430 431 pUserStr = WhoamiGetUser(NameSamCompatible); 432 if (pUserStr == NULL) 433 { 434 WhoamiFree(pUserInfo); 435 return 1; 436 } 437 438 UserTable = WhoamiAllocTable(2, 2); 439 440 WhoamiPrintHeader(IDS_USER_HEADER); 441 442 /* set the column labels */ 443 WhoamiSetTable(UserTable, WhoamiLoadRcString(IDS_COL_USER_NAME), 0, 0); 444 WhoamiSetTable(UserTable, WhoamiLoadRcString(IDS_COL_SID), 0, 1); 445 446 ConvertSidToStringSidW(pUserInfo->User.Sid, &pSidStr); 447 448 /* set the values for our single row of data */ 449 WhoamiSetTable(UserTable, pUserStr, 1, 0); 450 WhoamiSetTable(UserTable, pSidStr, 1, 1); 451 452 WhoamiPrintTable(UserTable); 453 454 /* cleanup our allocations */ 455 LocalFree(pSidStr); 456 WhoamiFree(pUserInfo); 457 WhoamiFree(pUserStr); 458 459 return 0; 460 } 461 462 int WhoamiGroups(void) 463 { 464 DWORD dwIndex = 0; 465 LPWSTR pSidStr = 0; 466 467 static WCHAR szGroupName[255] = {0}; 468 static WCHAR szDomainName[255] = {0}; 469 470 DWORD cchGroupName = _countof(szGroupName); 471 DWORD cchDomainName = _countof(szGroupName); 472 473 SID_NAME_USE Use = 0; 474 BYTE SidNameUseStr[12] = 475 { 476 /* SidTypeUser */ -1, 477 /* SidTypeGroup */ -1, 478 /* SidTypeDomain */ -1, 479 /* SidTypeUser */ -1, 480 /* SidTypeAlias */ IDS_TP_ALIAS, 481 /* SidTypeWellKnownGroup */ IDS_TP_WELL_KNOWN_GROUP, 482 /* SidTypeDeletedAccount */ -1, 483 /* SidTypeInvalid */ -1, 484 /* SidTypeUnknown */ -1, 485 /* SidTypeComputer */ -1, 486 /* SidTypeLabel */ IDS_TP_LABEL 487 }; 488 489 PTOKEN_GROUPS pGroupInfo = (PTOKEN_GROUPS)WhoamiGetTokenInfo(TokenGroups); 490 UINT PrintingRow; 491 WhoamiTable *GroupTable = NULL; 492 493 if (pGroupInfo == NULL) 494 { 495 return 1; 496 } 497 498 /* the header is the first (0) row, so we start in the second one (1) */ 499 PrintingRow = 1; 500 501 GroupTable = WhoamiAllocTable(pGroupInfo->GroupCount + 1, 4); 502 503 WhoamiPrintHeader(IDS_GROU_HEADER); 504 505 WhoamiSetTable(GroupTable, WhoamiLoadRcString(IDS_COL_GROUP_NAME), 0, 0); 506 WhoamiSetTable(GroupTable, WhoamiLoadRcString(IDS_COL_TYPE), 0, 1); 507 WhoamiSetTable(GroupTable, WhoamiLoadRcString(IDS_COL_SID), 0, 2); 508 WhoamiSetTable(GroupTable, WhoamiLoadRcString(IDS_COL_ATTRIB), 0, 3); 509 510 for (dwIndex = 0; dwIndex < pGroupInfo->GroupCount; dwIndex++) 511 { 512 LookupAccountSidW(NULL, 513 pGroupInfo->Groups[dwIndex].Sid, 514 (LPWSTR)&szGroupName, 515 &cchGroupName, 516 (LPWSTR)&szDomainName, 517 &cchDomainName, 518 &Use); 519 520 /* the original tool seems to limit the list to these kind of SID items */ 521 if ((Use == SidTypeWellKnownGroup || Use == SidTypeAlias || 522 Use == SidTypeLabel) && !(pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID)) 523 { 524 wchar_t tmpBuffer[666]; 525 526 /* looks like windows treats 0x60 as 0x7 for some reason, let's just nod and call it a day: 527 0x60 is SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED 528 0x07 is SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED */ 529 530 if (pGroupInfo->Groups[dwIndex].Attributes == 0x60) 531 pGroupInfo->Groups[dwIndex].Attributes = 0x07; 532 533 /* 1- format it as DOMAIN\GROUP if the domain exists, or just GROUP if not */ 534 _snwprintf((LPWSTR)&tmpBuffer, 535 _countof(tmpBuffer), 536 L"%s%s%s", 537 szDomainName, 538 cchDomainName ? L"\\" : L"", 539 szGroupName); 540 541 WhoamiSetTable(GroupTable, tmpBuffer, PrintingRow, 0); 542 543 /* 2- let's find out the group type by using a simple lookup table for lack of a better method */ 544 WhoamiSetTable(GroupTable, WhoamiLoadRcString(SidNameUseStr[Use]), PrintingRow, 1); 545 546 /* 3- turn that SID into text-form */ 547 ConvertSidToStringSidW(pGroupInfo->Groups[dwIndex].Sid, &pSidStr); 548 549 WhoamiSetTable(GroupTable, pSidStr, PrintingRow, 2); 550 551 LocalFree(pSidStr); 552 553 /* 4- reuse that buffer for appending the attributes in text-form at the very end */ 554 ZeroMemory(tmpBuffer, sizeof(tmpBuffer)); 555 556 if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_MANDATORY) 557 StringCchCat(tmpBuffer, _countof(tmpBuffer), WhoamiLoadRcString(IDS_ATTR_GROUP_MANDATORY)); 558 if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_ENABLED_BY_DEFAULT) 559 StringCchCat(tmpBuffer, _countof(tmpBuffer), WhoamiLoadRcString(IDS_ATTR_GROUP_ENABLED_BY_DEFAULT)); 560 if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_ENABLED) 561 StringCchCat(tmpBuffer, _countof(tmpBuffer), WhoamiLoadRcString(IDS_ATTR_GROUP_ENABLED)); 562 if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_OWNER) 563 StringCchCat(tmpBuffer, _countof(tmpBuffer), WhoamiLoadRcString(IDS_ATTR_GROUP_OWNER)); 564 565 /* remove the last comma (', ' which is 2 wchars) of the buffer, let's keep it simple */ 566 tmpBuffer[max(wcslen(tmpBuffer) - 2, 0)] = UNICODE_NULL; 567 568 WhoamiSetTable(GroupTable, tmpBuffer, PrintingRow, 3); 569 570 PrintingRow++; 571 } 572 573 /* reset the buffers so that we can reuse them */ 574 ZeroMemory(szGroupName, sizeof(szGroupName)); 575 ZeroMemory(szDomainName, sizeof(szDomainName)); 576 577 cchGroupName = 255; 578 cchDomainName = 255; 579 } 580 581 WhoamiPrintTable(GroupTable); 582 583 /* cleanup our allocations */ 584 WhoamiFree((LPVOID)pGroupInfo); 585 586 return 0; 587 } 588 589 int WhoamiPriv(void) 590 { 591 PTOKEN_PRIVILEGES pPrivInfo = (PTOKEN_PRIVILEGES) WhoamiGetTokenInfo(TokenPrivileges); 592 DWORD dwResult = 0, dwIndex = 0; 593 WhoamiTable *PrivTable = NULL; 594 595 if (pPrivInfo == NULL) 596 { 597 return 1; 598 } 599 600 PrivTable = WhoamiAllocTable(pPrivInfo->PrivilegeCount + 1, 3); 601 602 WhoamiPrintHeader(IDS_PRIV_HEADER); 603 604 WhoamiSetTable(PrivTable, WhoamiLoadRcString(IDS_COL_PRIV_NAME), 0, 0); 605 WhoamiSetTable(PrivTable, WhoamiLoadRcString(IDS_COL_DESCRIPTION), 0, 1); 606 WhoamiSetTable(PrivTable, WhoamiLoadRcString(IDS_COL_STATE), 0, 2); 607 608 for (dwIndex = 0; dwIndex < pPrivInfo->PrivilegeCount; dwIndex++) 609 { 610 PWSTR PrivName = NULL, DispName = NULL; 611 DWORD PrivNameSize = 0, DispNameSize = 0; 612 BOOL ret = FALSE; 613 614 ret = LookupPrivilegeNameW(NULL, 615 &pPrivInfo->Privileges[dwIndex].Luid, 616 NULL, 617 &PrivNameSize); 618 619 PrivName = HeapAlloc(GetProcessHeap(), 0, ++PrivNameSize*sizeof(WCHAR)); 620 621 LookupPrivilegeNameW(NULL, 622 &pPrivInfo->Privileges[dwIndex].Luid, 623 PrivName, 624 &PrivNameSize); 625 626 WhoamiSetTableDyn(PrivTable, PrivName, dwIndex + 1, 0); 627 628 629 /* try to grab the size of the string, also, beware, as this call is 630 unimplemented in ReactOS/Wine at the moment */ 631 632 LookupPrivilegeDisplayNameW(NULL, PrivName, NULL, &DispNameSize, &dwResult); 633 634 DispName = HeapAlloc(GetProcessHeap(), 0, ++DispNameSize * sizeof(WCHAR)); 635 636 ret = LookupPrivilegeDisplayNameW(NULL, PrivName, DispName, &DispNameSize, &dwResult); 637 638 if (ret && DispName) 639 { 640 // wprintf(L"DispName: %d %x '%s'\n", DispNameSize, GetLastError(), DispName); 641 WhoamiSetTableDyn(PrivTable, DispName, dwIndex + 1, 1); 642 } 643 else 644 { 645 WhoamiSetTable(PrivTable, WhoamiLoadRcString(IDS_UNKNOWN_DESCRIPTION), dwIndex + 1, 1); 646 647 if (DispName != NULL) 648 WhoamiFree(DispName); 649 } 650 651 if (pPrivInfo->Privileges[dwIndex].Attributes & SE_PRIVILEGE_ENABLED) 652 WhoamiSetTable(PrivTable, WhoamiLoadRcString(IDS_STATE_ENABLED), dwIndex + 1, 2); 653 else 654 WhoamiSetTable(PrivTable, WhoamiLoadRcString(IDS_STATE_DISABLED), dwIndex + 1, 2); 655 } 656 657 WhoamiPrintTable(PrivTable); 658 659 /* cleanup our allocations */ 660 WhoamiFree(pPrivInfo); 661 662 return 0; 663 } 664 665 int wmain(int argc, WCHAR* argv[]) 666 { 667 #define WAM_USER 1<<0 668 #define WAM_GROUPS 1<<1 669 #define WAM_PRIV 1<<2 670 671 INT i; 672 BYTE WamBit = 0; 673 674 /* Initialize the Console Standard Streams */ 675 ConInitStdStreams(); 676 677 678 /* * * * * * * * * * * * * * * * 679 * A: no parameters whatsoever */ 680 681 if (argc == 1) 682 { 683 /* if there's no arguments just choose the simple path and display the user's identity in lowercase */ 684 LPWSTR UserBuffer = WhoamiGetUser(NameSamCompatible); 685 686 if (UserBuffer) 687 { 688 wprintf(L"%s\n", UserBuffer); 689 WhoamiFree(UserBuffer); 690 return 0; 691 } 692 else 693 { 694 return 1; 695 } 696 } 697 698 /* first things first-- let's detect and manage both printing modifiers (/fo and /nh) */ 699 for (i = 1; i < argc; i++) 700 { 701 if (wcsicmp(argv[i], L"/nh") == 0) 702 { 703 NoHeaderArgCount++; 704 705 if (NoHeader == FALSE) 706 { 707 NoHeader = TRUE; 708 // wprintf(L"Headers disabled!\n"); 709 BlankArgument(i, argv); 710 } 711 } 712 } 713 714 for (i = 1; i < argc; i++) 715 { 716 if (wcsicmp(argv[i], L"/fo") == 0) 717 { 718 if ((i + 1) < argc) 719 { 720 // wprintf(L"exists another param after /fo\n"); 721 722 PrintFormatArgCount++; 723 724 if (wcsicmp(argv[i + 1], L"table") == 0 && PrintFormat != table) 725 { 726 PrintFormat = table; 727 // wprintf(L"Changed to table format\n"); 728 BlankArgument(i, argv); 729 BlankArgument(i + 1, argv); 730 } 731 else if (wcsicmp(argv[i + 1], L"list") == 0 && PrintFormat != list) 732 { 733 PrintFormat = list; 734 // wprintf(L"Changed to list format\n"); 735 BlankArgument(i, argv); 736 BlankArgument(i + 1, argv); 737 738 /* looks like you can't use the "/fo list /nh" options together 739 for some stupid reason */ 740 if (PrintFormat == list && NoHeader != FALSE) 741 { 742 wprintf(WhoamiLoadRcString(IDS_ERROR_NH_LIST)); 743 return 1; 744 } 745 } 746 else if (wcsicmp(argv[i + 1], L"csv") == 0 && PrintFormat != csv) 747 { 748 PrintFormat = csv; 749 // wprintf(L"Changed to csv format\n"); 750 BlankArgument(i, argv); 751 BlankArgument(i + 1, argv); 752 } 753 /* /nh or /fo after /fo isn't parsed as a value */ 754 else if (wcsicmp(argv[i + 1], L"/nh") == 0 || wcsicmp(argv[i + 1], L"/fo") == 0 755 756 /* same goes for the other named options, not ideal, but works */ 757 || wcsicmp(argv[i + 1], L"/priv") == 0 758 || wcsicmp(argv[i + 1], L"/groups") == 0 759 || wcsicmp(argv[i + 1], L"/user") == 0 760 || wcsicmp(argv[i + 1], L"/all") == 0 761 || wcsicmp(argv[i + 1], L"") == 0) 762 { 763 goto FoValueExpected; 764 } 765 else 766 { 767 wprintf(WhoamiLoadRcString(IDS_ERROR_VALUENOTALLOWED), argv[i + 1]); 768 return 1; 769 } 770 } 771 else 772 { 773 FoValueExpected: 774 775 wprintf(WhoamiLoadRcString(IDS_ERROR_VALUEXPECTED)); 776 return 1; 777 } 778 } 779 } 780 781 if (NoHeaderArgCount >= 2) 782 { 783 wprintf(WhoamiLoadRcString(IDS_ERROR_1TIMES), L"/nh"); 784 return 1; 785 } 786 /* special case when there's just a /nh as argument; it outputs nothing */ 787 else if (NoHeaderArgCount == 1 && argc == 2) 788 { 789 return 0; 790 } 791 792 if (PrintFormatArgCount >= 2) 793 { 794 wprintf(WhoamiLoadRcString(IDS_ERROR_1TIMES), L"/fo"); 795 return 1; 796 } 797 /* if there's just /fo <format>... call it invalid */ 798 else if (PrintFormatArgCount == 1 && argc == 3) 799 { 800 goto InvalidSyntax; 801 } 802 803 /* * * * * * * * * * * * * * 804 * B: one single parameter */ 805 806 if (argc == 2) 807 { 808 /* now let's try to parse the triumvirate of simpler, single (1) arguments... plus help */ 809 if (wcsicmp(argv[1], L"/?") == 0) 810 { 811 wprintf(WhoamiLoadRcString(IDS_HELP)); 812 return 0; 813 } 814 815 else if (wcsicmp(argv[1], L"/upn") == 0) 816 { 817 LPWSTR UserBuffer = WhoamiGetUser(NameUserPrincipal); 818 819 if (UserBuffer) 820 { 821 wprintf(L"%s\n", UserBuffer); 822 WhoamiFree(UserBuffer); 823 return 0; 824 } 825 else 826 { 827 wprintf(WhoamiLoadRcString(IDS_ERROR_UPN)); 828 return 1; 829 } 830 } 831 832 else if (wcsicmp(argv[1], L"/fqdn") == 0) 833 { 834 LPWSTR UserBuffer = WhoamiGetUser(NameFullyQualifiedDN); 835 836 if (UserBuffer) 837 { 838 wprintf(L"%s\n", UserBuffer); 839 WhoamiFree(UserBuffer); 840 return 0; 841 } 842 else 843 { 844 wprintf(WhoamiLoadRcString(IDS_ERROR_FQDN)); 845 return 1; 846 } 847 } 848 849 else if (wcsicmp(argv[1], L"/logonid") == 0) 850 { 851 return WhoamiLogonId(); 852 } 853 } 854 855 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 856 * C: One main parameter with extra tasty modifiers to play with */ 857 858 /* sometimes is just easier to whitelist for lack of a better method */ 859 for (i=1; i<argc; i++) 860 { 861 if ((wcsicmp(argv[i], L"/user") != 0) && 862 (wcsicmp(argv[i], L"/groups") != 0) && 863 (wcsicmp(argv[i], L"/priv") != 0) && 864 (wcsicmp(argv[i], L"/all") != 0) && 865 (wcsicmp(argv[i], L"") != 0)) 866 { 867 wprintf(WhoamiLoadRcString(IDS_ERROR_INVALIDARG), argv[i]); 868 return 1; 869 } 870 } 871 872 if (GetArgument(L"/user", argc, argv)) 873 { 874 WamBit |= WAM_USER; 875 } 876 877 if (GetArgument(L"/groups", argc, argv)) 878 { 879 WamBit |= WAM_GROUPS; 880 } 881 882 if (GetArgument(L"/priv", argc, argv)) 883 { 884 WamBit |= WAM_PRIV; 885 } 886 887 if (GetArgument(L"/all", argc, argv)) 888 { 889 /* one can't have it /all and any of the other options at the same time */ 890 if ((WamBit & (WAM_USER | WAM_GROUPS | WAM_PRIV)) == 0) 891 { 892 WamBit |= (WAM_USER | WAM_GROUPS | WAM_PRIV); 893 } 894 else 895 { 896 goto InvalidSyntax; 897 } 898 } 899 900 if (WamBit & WAM_USER) 901 { 902 WhoamiUser(); 903 } 904 if (WamBit & WAM_GROUPS) 905 { 906 WhoamiGroups(); 907 } 908 if (WamBit & WAM_PRIV) 909 { 910 WhoamiPriv(); 911 } 912 913 return 0; 914 915 InvalidSyntax: 916 wprintf(WhoamiLoadRcString(IDS_ERROR_INVALIDSYNTAX)); 917 return 1; 918 } 919