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)
18 #define wprintf(...) ConPrintf(StdOut, ##__VA_ARGS__)
20 BOOL NoHeader
= FALSE
;
21 UINT NoHeaderArgCount
= 0;
22 UINT PrintFormatArgCount
= 0;
30 } PrintFormat
= undefined
;
33 BOOL
GetArgument(WCHAR
* arg
, int argc
, WCHAR
* argv
[])
40 for (i
= 1; i
< argc
; i
++)
42 if (wcsicmp(argv
[i
], arg
) == 0)
49 /* blanking out the accepted modifiers will make filtering easier later on */
50 void BlankArgument(int argc
, WCHAR
* argv
[])
55 /* helper functions; let's keep it tidy to avoid redundancies */
57 LPWSTR
WhoamiGetUser(EXTENDED_NAME_FORMAT NameFormat
)
59 LPWSTR UsrBuf
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, MAX_PATH
);
60 ULONG UsrSiz
= MAX_PATH
;
65 if (GetUserNameExW(NameFormat
, UsrBuf
, &UsrSiz
))
71 HeapFree(GetProcessHeap(), 0, UsrBuf
);
75 BOOL
WhoamiFree(VOID
* Buffer
)
77 return HeapFree(GetProcessHeap(), 0, Buffer
);
81 VOID
* WhoamiGetTokenInfo(TOKEN_INFORMATION_CLASS TokenType
)
87 if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ
, &hToken
))
89 GetTokenInformation(hToken
,
95 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
97 pTokenInfo
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwLength
);
98 if (pTokenInfo
== NULL
)
100 wprintf(L
"ERROR: not enough memory to allocate the token structure.\r\n");
105 if (!GetTokenInformation(hToken
, TokenType
,
110 wprintf(L
"ERROR 0x%x: could not get token information.\r\n", GetLastError());
111 WhoamiFree(pTokenInfo
);
121 LPWSTR
WhoamiLoadRcString(INT ResId
)
123 #define RC_STRING_MAX_SIZE 850
124 static WCHAR TmpBuffer
[RC_STRING_MAX_SIZE
];
126 LoadStringW(GetModuleHandleW(NULL
), ResId
, TmpBuffer
, RC_STRING_MAX_SIZE
);
131 void WhoamiPrintHeader(int HeaderId
)
133 PWSTR Header
= WhoamiLoadRcString(HeaderId
);
134 DWORD Length
= wcslen(Header
);
136 if (NoHeader
|| PrintFormat
== csv
)
139 wprintf(L
"\n%s\n", Header
);
154 /* create and prepare a new table for printing */
155 WhoamiTable
*WhoamiAllocTable(UINT Rows
, UINT Cols
)
157 WhoamiTable
*pTable
= HeapAlloc(GetProcessHeap(),
159 sizeof(WhoamiTable
) + sizeof(LPWSTR
) * Rows
* Cols
);
161 // wprintf(L"DEBUG: Allocating %dx%d elem table for printing.\r\n\r\n", Rows, Cols);
165 wprintf(L
"ERROR: Not enough memory for displaying the table.");
175 /* allocate and fill a new entry in the table */
176 void WhoamiSetTable(WhoamiTable
*pTable
, WCHAR
*Entry
, UINT Row
, UINT Col
)
178 LPWSTR Target
= HeapAlloc(GetProcessHeap(),
180 1 + wcslen(Entry
) * sizeof(Entry
[0]));
182 // wprintf(L"DEBUG: Setting table value '%lp' '%ls' for %lu %lu.\n", entry, entry, row, col);
187 wcscpy(Target
, Entry
);
189 pTable
->Content
[Row
* pTable
->Cols
+ Col
] = Target
;
192 /* fill a new entry in the table */
193 void WhoamiSetTableDyn(WhoamiTable
*pTable
, WCHAR
*Entry
, UINT Row
, UINT Col
)
195 pTable
->Content
[Row
* pTable
->Cols
+ Col
] = Entry
;
198 /* print and deallocate the table */
199 void WhoamiPrintTable(WhoamiTable
*pTable
)
208 wprintf(L
"ERROR: The table passed for display is empty.");
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 */
216 if (PrintFormat
!= csv
)
218 ColLength
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(UINT
) * pTable
->Cols
);
220 if (PrintFormat
== list
)
222 for (j
= 0; j
< pTable
->Cols
; j
++)
223 if (pTable
->Content
[j
])
225 UINT ThisLength
= wcslen(pTable
->Content
[j
]);
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
;
231 ColLength
[0] = max(ThisLength
, ColLength
[0]);
236 for (j
= 0; j
< pTable
->Cols
; j
++)
237 for (i
= 0; i
< pTable
->Rows
; i
++)
238 if (pTable
->Content
[i
* pTable
->Cols
+ j
])
240 UINT ThisLength
= wcslen(pTable
->Content
[i
* pTable
->Cols
+ j
]);
241 ColLength
[j
] = max(ThisLength
, ColLength
[j
]);
250 for (i
= 0; i
< pTable
->Rows
; i
++)
252 if (!pTable
->Content
[i
* pTable
->Cols
])
255 /* if the user especified /nh then skip the column labels */
256 if (NoHeader
&& i
== 0)
259 for (j
= 0; j
< pTable
->Cols
; j
++)
261 if (pTable
->Content
[i
* pTable
->Cols
+ j
])
264 pTable
->Content
[i
* pTable
->Cols
+ j
],
265 (j
+1 < pTable
->Cols
? L
"," : L
""));
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
++)
282 /* if the first member of this row isn't available, then forget it */
283 if (!pTable
->Content
[CurRow
* pTable
->Cols
])
289 for (CurRow
= 1; CurRow
< pTable
->Rows
; CurRow
++)
291 /* if the first member of this row isn't available, then forget it */
292 if (!pTable
->Content
[CurRow
* pTable
->Cols
])
295 /* if the user especified /nh then skip the column labels */
296 if (NoHeader
&& i
== 0)
299 for (CurCol
= 0; CurCol
< pTable
->Cols
; CurCol
++)
301 wprintf(L
"%-*s %s\n",
303 pTable
->Content
[CurCol
],
304 pTable
->Content
[CurRow
* pTable
->Cols
+ CurCol
]);
307 /* don't add two carriage returns at the very end */
308 if (CurRow
!= FinalRow
)
319 for (i
= 0; i
< pTable
->Rows
; i
++)
321 /* if the first member of this row isn't available, then forget it */
322 if (!pTable
->Content
[i
* pTable
->Cols
])
325 /* if the user especified /nh then skip the column labels too */
326 if (NoHeader
&& i
== 0)
329 for (j
= 0; j
< pTable
->Cols
; j
++)
331 if (pTable
->Content
[i
* pTable
->Cols
+ j
])
333 wprintf(L
"%-*s ", ColLength
[j
], pTable
->Content
[i
* pTable
->Cols
+ j
]);
338 /* add the cute underline thingie for the table header */
341 for (j
= 0; j
< pTable
->Cols
; j
++)
343 DWORD Length
= ColLength
[j
];
348 /* a spacing between all the columns except for the last one */
349 if (pTable
->Cols
!= (i
+ 1))
360 /* fixme: when many tables are displayed in a single run we
361 have to sandwich carriage returns in between. */
365 for (i
= 0; i
< pTable
->Rows
; i
++)
366 for (j
= 0; j
< pTable
->Cols
; j
++)
367 WhoamiFree(pTable
->Content
[i
* pTable
->Cols
+ j
]);
371 if (PrintFormat
!= csv
)
372 HeapFree(GetProcessHeap(), 0, ColLength
);
375 int WhoamiLogonId(void)
377 PTOKEN_GROUPS pGroupInfo
= (PTOKEN_GROUPS
) WhoamiGetTokenInfo(TokenGroups
);
382 if (pGroupInfo
== NULL
)
385 /* lets see if we can find the logon SID in that list, should be there */
386 for (dwIndex
= 0; dwIndex
< pGroupInfo
->GroupCount
; dwIndex
++)
388 if ((pGroupInfo
->Groups
[dwIndex
].Attributes
& SE_GROUP_LOGON_ID
) == SE_GROUP_LOGON_ID
)
390 pSid
= pGroupInfo
->Groups
[dwIndex
].Sid
;
396 WhoamiFree(pGroupInfo
);
397 wprintf(L
"ERROR: Couldn't find the logon SID.\n");
400 if (!ConvertSidToStringSidW(pSid
, &pSidStr
))
402 WhoamiFree(pGroupInfo
);
403 wprintf(L
"ERROR: Couldn't convert the logon SID to a string.\n");
408 /* let's show our converted logon SID */
409 wprintf(L
"%s\n", pSidStr
);
412 /* cleanup our allocations */
414 WhoamiFree(pGroupInfo
);
421 PTOKEN_USER pUserInfo
= (PTOKEN_USER
) WhoamiGetTokenInfo(TokenUser
);
422 LPWSTR pUserStr
= NULL
;
423 LPWSTR pSidStr
= NULL
;
424 WhoamiTable
*UserTable
= NULL
;
426 if (pUserInfo
== NULL
)
431 pUserStr
= WhoamiGetUser(NameSamCompatible
);
432 if (pUserStr
== NULL
)
434 WhoamiFree(pUserInfo
);
438 UserTable
= WhoamiAllocTable(2, 2);
440 WhoamiPrintHeader(IDS_USER_HEADER
);
442 /* set the column labels */
443 WhoamiSetTable(UserTable
, WhoamiLoadRcString(IDS_COL_USER_NAME
), 0, 0);
444 WhoamiSetTable(UserTable
, WhoamiLoadRcString(IDS_COL_SID
), 0, 1);
446 ConvertSidToStringSidW(pUserInfo
->User
.Sid
, &pSidStr
);
448 /* set the values for our single row of data */
449 WhoamiSetTable(UserTable
, pUserStr
, 1, 0);
450 WhoamiSetTable(UserTable
, pSidStr
, 1, 1);
452 WhoamiPrintTable(UserTable
);
454 /* cleanup our allocations */
456 WhoamiFree(pUserInfo
);
457 WhoamiFree(pUserStr
);
462 int WhoamiGroups(void)
467 static WCHAR szGroupName
[255] = {0};
468 static WCHAR szDomainName
[255] = {0};
470 DWORD cchGroupName
= _countof(szGroupName
);
471 DWORD cchDomainName
= _countof(szGroupName
);
473 SID_NAME_USE Use
= 0;
474 BYTE SidNameUseStr
[12] =
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
489 PTOKEN_GROUPS pGroupInfo
= (PTOKEN_GROUPS
)WhoamiGetTokenInfo(TokenGroups
);
491 WhoamiTable
*GroupTable
= NULL
;
493 if (pGroupInfo
== NULL
)
498 /* the header is the first (0) row, so we start in the second one (1) */
501 GroupTable
= WhoamiAllocTable(pGroupInfo
->GroupCount
+ 1, 4);
503 WhoamiPrintHeader(IDS_GROU_HEADER
);
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);
510 for (dwIndex
= 0; dwIndex
< pGroupInfo
->GroupCount
; dwIndex
++)
512 LookupAccountSidW(NULL
,
513 pGroupInfo
->Groups
[dwIndex
].Sid
,
514 (LPWSTR
)&szGroupName
,
516 (LPWSTR
)&szDomainName
,
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
))
524 wchar_t tmpBuffer
[666];
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 */
530 if (pGroupInfo
->Groups
[dwIndex
].Attributes
== 0x60)
531 pGroupInfo
->Groups
[dwIndex
].Attributes
= 0x07;
533 /* 1- format it as DOMAIN\GROUP if the domain exists, or just GROUP if not */
534 _snwprintf((LPWSTR
)&tmpBuffer
,
538 cchDomainName
? L
"\\" : L
"",
541 WhoamiSetTable(GroupTable
, tmpBuffer
, PrintingRow
, 0);
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);
546 /* 3- turn that SID into text-form */
547 ConvertSidToStringSidW(pGroupInfo
->Groups
[dwIndex
].Sid
, &pSidStr
);
549 WhoamiSetTable(GroupTable
, pSidStr
, PrintingRow
, 2);
553 /* 4- reuse that buffer for appending the attributes in text-form at the very end */
554 ZeroMemory(tmpBuffer
, sizeof(tmpBuffer
));
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
));
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
;
568 WhoamiSetTable(GroupTable
, tmpBuffer
, PrintingRow
, 3);
573 /* reset the buffers so that we can reuse them */
574 ZeroMemory(szGroupName
, sizeof(szGroupName
));
575 ZeroMemory(szDomainName
, sizeof(szDomainName
));
581 WhoamiPrintTable(GroupTable
);
583 /* cleanup our allocations */
584 WhoamiFree((LPVOID
)pGroupInfo
);
591 PTOKEN_PRIVILEGES pPrivInfo
= (PTOKEN_PRIVILEGES
) WhoamiGetTokenInfo(TokenPrivileges
);
592 DWORD dwResult
= 0, dwIndex
= 0;
593 WhoamiTable
*PrivTable
= NULL
;
595 if (pPrivInfo
== NULL
)
600 PrivTable
= WhoamiAllocTable(pPrivInfo
->PrivilegeCount
+ 1, 3);
602 WhoamiPrintHeader(IDS_PRIV_HEADER
);
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);
608 for (dwIndex
= 0; dwIndex
< pPrivInfo
->PrivilegeCount
; dwIndex
++)
610 PWSTR PrivName
= NULL
, DispName
= NULL
;
611 DWORD PrivNameSize
= 0, DispNameSize
= 0;
614 ret
= LookupPrivilegeNameW(NULL
,
615 &pPrivInfo
->Privileges
[dwIndex
].Luid
,
619 PrivName
= HeapAlloc(GetProcessHeap(), 0, ++PrivNameSize
*sizeof(WCHAR
));
621 LookupPrivilegeNameW(NULL
,
622 &pPrivInfo
->Privileges
[dwIndex
].Luid
,
626 WhoamiSetTableDyn(PrivTable
, PrivName
, dwIndex
+ 1, 0);
629 /* try to grab the size of the string, also, beware, as this call is
630 unimplemented in ReactOS/Wine at the moment */
632 LookupPrivilegeDisplayNameW(NULL
, PrivName
, NULL
, &DispNameSize
, &dwResult
);
634 DispName
= HeapAlloc(GetProcessHeap(), 0, ++DispNameSize
* sizeof(WCHAR
));
636 ret
= LookupPrivilegeDisplayNameW(NULL
, PrivName
, DispName
, &DispNameSize
, &dwResult
);
640 // wprintf(L"DispName: %d %x '%s'\n", DispNameSize, GetLastError(), DispName);
641 WhoamiSetTableDyn(PrivTable
, DispName
, dwIndex
+ 1, 1);
645 WhoamiSetTable(PrivTable
, WhoamiLoadRcString(IDS_UNKNOWN_DESCRIPTION
), dwIndex
+ 1, 1);
647 if (DispName
!= NULL
)
648 WhoamiFree(DispName
);
651 if (pPrivInfo
->Privileges
[dwIndex
].Attributes
& SE_PRIVILEGE_ENABLED
)
652 WhoamiSetTable(PrivTable
, WhoamiLoadRcString(IDS_STATE_ENABLED
), dwIndex
+ 1, 2);
654 WhoamiSetTable(PrivTable
, WhoamiLoadRcString(IDS_STATE_DISABLED
), dwIndex
+ 1, 2);
657 WhoamiPrintTable(PrivTable
);
659 /* cleanup our allocations */
660 WhoamiFree(pPrivInfo
);
665 int wmain(int argc
, WCHAR
* argv
[])
667 #define WAM_USER 1<<0
668 #define WAM_GROUPS 1<<1
669 #define WAM_PRIV 1<<2
674 /* Initialize the Console Standard Streams */
678 /* * * * * * * * * * * * * * * *
679 * A: no parameters whatsoever */
683 /* if there's no arguments just choose the simple path and display the user's identity in lowercase */
684 LPWSTR UserBuffer
= WhoamiGetUser(NameSamCompatible
);
688 wprintf(L
"%s\n", UserBuffer
);
689 WhoamiFree(UserBuffer
);
698 /* first things first-- let's detect and manage both printing modifiers (/fo and /nh) */
699 for (i
= 1; i
< argc
; i
++)
701 if (wcsicmp(argv
[i
], L
"/nh") == 0)
705 if (NoHeader
== FALSE
)
708 // wprintf(L"Headers disabled!\n");
709 BlankArgument(i
, argv
);
714 for (i
= 1; i
< argc
; i
++)
716 if (wcsicmp(argv
[i
], L
"/fo") == 0)
720 // wprintf(L"exists another param after /fo\n");
722 PrintFormatArgCount
++;
724 if (wcsicmp(argv
[i
+ 1], L
"table") == 0 && PrintFormat
!= table
)
727 // wprintf(L"Changed to table format\n");
728 BlankArgument(i
, argv
);
729 BlankArgument(i
+ 1, argv
);
731 else if (wcsicmp(argv
[i
+ 1], L
"list") == 0 && PrintFormat
!= list
)
734 // wprintf(L"Changed to list format\n");
735 BlankArgument(i
, argv
);
736 BlankArgument(i
+ 1, argv
);
738 /* looks like you can't use the "/fo list /nh" options together
739 for some stupid reason */
740 if (PrintFormat
== list
&& NoHeader
!= FALSE
)
742 wprintf(WhoamiLoadRcString(IDS_ERROR_NH_LIST
));
746 else if (wcsicmp(argv
[i
+ 1], L
"csv") == 0 && PrintFormat
!= csv
)
749 // wprintf(L"Changed to csv format\n");
750 BlankArgument(i
, argv
);
751 BlankArgument(i
+ 1, argv
);
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
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)
763 goto FoValueExpected
;
767 wprintf(WhoamiLoadRcString(IDS_ERROR_VALUENOTALLOWED
), argv
[i
+ 1]);
775 wprintf(WhoamiLoadRcString(IDS_ERROR_VALUEXPECTED
));
781 if (NoHeaderArgCount
>= 2)
783 wprintf(WhoamiLoadRcString(IDS_ERROR_1TIMES
), L
"/nh");
786 /* special case when there's just a /nh as argument; it outputs nothing */
787 else if (NoHeaderArgCount
== 1 && argc
== 2)
792 if (PrintFormatArgCount
>= 2)
794 wprintf(WhoamiLoadRcString(IDS_ERROR_1TIMES
), L
"/fo");
797 /* if there's just /fo <format>... call it invalid */
798 else if (PrintFormatArgCount
== 1 && argc
== 3)
803 /* * * * * * * * * * * * * *
804 * B: one single parameter */
808 /* now let's try to parse the triumvirate of simpler, single (1) arguments... plus help */
809 if (wcsicmp(argv
[1], L
"/?") == 0)
811 wprintf(WhoamiLoadRcString(IDS_HELP
));
815 else if (wcsicmp(argv
[1], L
"/upn") == 0)
817 LPWSTR UserBuffer
= WhoamiGetUser(NameUserPrincipal
);
821 wprintf(L
"%s\n", UserBuffer
);
822 WhoamiFree(UserBuffer
);
827 wprintf(WhoamiLoadRcString(IDS_ERROR_UPN
));
832 else if (wcsicmp(argv
[1], L
"/fqdn") == 0)
834 LPWSTR UserBuffer
= WhoamiGetUser(NameFullyQualifiedDN
);
838 wprintf(L
"%s\n", UserBuffer
);
839 WhoamiFree(UserBuffer
);
844 wprintf(WhoamiLoadRcString(IDS_ERROR_FQDN
));
849 else if (wcsicmp(argv
[1], L
"/logonid") == 0)
851 return WhoamiLogonId();
855 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
856 * C: One main parameter with extra tasty modifiers to play with */
858 /* sometimes is just easier to whitelist for lack of a better method */
859 for (i
=1; i
<argc
; i
++)
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))
867 wprintf(WhoamiLoadRcString(IDS_ERROR_INVALIDARG
), argv
[i
]);
872 if (GetArgument(L
"/user", argc
, argv
))
877 if (GetArgument(L
"/groups", argc
, argv
))
879 WamBit
|= WAM_GROUPS
;
882 if (GetArgument(L
"/priv", argc
, argv
))
887 if (GetArgument(L
"/all", argc
, argv
))
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)
892 WamBit
|= (WAM_USER
| WAM_GROUPS
| WAM_PRIV
);
900 if (WamBit
& WAM_USER
)
904 if (WamBit
& WAM_GROUPS
)
908 if (WamBit
& WAM_PRIV
)
916 wprintf(WhoamiLoadRcString(IDS_ERROR_INVALIDSYNTAX
));