ReactOS  0.4.12-dev-57-g7050ac4
whoami.c
Go to the documentation of this file.
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 
23 
24 enum
25 {
31 
32 
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 */
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 {
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 
76 {
77  return HeapFree(GetProcessHeap(), 0, Buffer);
78 }
79 
80 
82 {
83  HANDLE hToken = 0;
84  DWORD dwLength = 0;
85  VOID* pTokenInfo = 0;
86 
88  {
89  GetTokenInformation(hToken,
90  TokenType,
91  NULL,
92  dwLength,
93  &dwLength);
94 
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 
122 {
123  #define RC_STRING_MAX_SIZE 850
124  static WCHAR TmpBuffer[RC_STRING_MAX_SIZE];
125 
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 {
151  LPWSTR Content[1];
152 } WhoamiTable;
153 
154 /* create and prepare a new table for printing */
156 {
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 */
177 {
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 */
194 {
195  pTable->Content[Row * pTable->Cols + Col] = Entry;
196 }
197 
198 /* print and deallocate the table */
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 {
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 {
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 
441 
442  /* set the column labels */
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 
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 
504 
506  WhoamiSetTable(GroupTable, WhoamiLoadRcString(IDS_COL_TYPE), 0, 1);
507  WhoamiSetTable(GroupTable, WhoamiLoadRcString(IDS_COL_SID), 0, 2);
509 
510  for (dwIndex = 0; dwIndex < pGroupInfo->GroupCount; dwIndex++)
511  {
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)
558  if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_ENABLED_BY_DEFAULT)
560  if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_ENABLED)
562  if (pGroupInfo->Groups[dwIndex].Attributes & SE_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 {
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 
603 
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 
615  &pPrivInfo->Privileges[dwIndex].Luid,
616  NULL,
617  &PrivNameSize);
618 
619  PrivName = HeapAlloc(GetProcessHeap(), 0, ++PrivNameSize*sizeof(WCHAR));
620 
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 */
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  {
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 
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  {
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  {
768  return 1;
769  }
770  }
771  else
772  {
773  FoValueExpected:
774 
776  return 1;
777  }
778  }
779  }
780 
781  if (NoHeaderArgCount >= 2)
782  {
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  {
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  {
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  {
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  {
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  {
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 
917  return 1;
918 }
void WhoamiSetTable(WhoamiTable *pTable, WCHAR *Entry, UINT Row, UINT Col)
Definition: whoami.c:176
static int argc
Definition: ServiceArgs.c:12
#define max(a, b)
Definition: svc.c:63
#define IDS_ERROR_VALUENOTALLOWED
Definition: resource.h:33
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
int WhoamiLogonId(void)
Definition: whoami.c:375
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
LPWSTR Content[1]
Definition: whoami.c:151
#define WAM_PRIV
enum _SID_NAME_USE SID_NAME_USE
struct _Entry Entry
Definition: kefuncs.h:640
BOOL NoHeader
Definition: whoami.c:20
__wchar_t WCHAR
Definition: xmlstorage.h:180
UINT NoHeaderArgCount
Definition: whoami.c:21
uint16_t * PWSTR
Definition: typedefs.h:54
#define _countof(array)
Definition: fontsub.cpp:30
#define IDS_ATTR_GROUP_MANDATORY
Definition: resource.h:20
LPWSTR WINAPI CharLowerW(_Inout_ LPWSTR)
BOOL WINAPI LookupPrivilegeNameW(LPCWSTR lpSystemName, PLUID lpLuid, LPWSTR lpName, LPDWORD cchName)
Definition: misc.c:832
#define IDS_ERROR_FQDN
Definition: resource.h:31
$ULONG PrivilegeCount
Definition: setypes.h:969
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
#define StringCchCat
Definition: strsafe.h:317
LPWSTR WhoamiLoadRcString(INT ResId)
Definition: whoami.c:121
#define wprintf(...)
Definition: whoami.c:18
Definition: whoami.c:29
BOOL WINAPI ConvertSidToStringSidW(PSID Sid, LPWSTR *StringSid)
Definition: security.c:3255
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int32_t INT
Definition: typedefs.h:56
static char ** argv
Definition: ServiceArgs.c:11
BOOL WhoamiFree(VOID *Buffer)
Definition: whoami.c:75
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
GLenum GLclampf GLint i
Definition: glfuncs.h:14
Definition: whoami.c:27
#define IDS_ATTR_GROUP_OWNER
Definition: resource.h:23
#define ConInitStdStreams()
Definition: stream.h:122
#define SE_GROUP_OWNER
Definition: setypes.h:93
#define UNICODE_NULL
Definition: Header.h:8
#define IDS_COL_GROUP_NAME
Definition: resource.h:8
LPWSTR WhoamiGetUser(EXTENDED_NAME_FORMAT NameFormat)
Definition: whoami.c:57
#define IDS_TP_LABEL
Definition: resource.h:18
void BlankArgument(int argc, WCHAR *argv[])
Definition: whoami.c:50
#define IDS_ERROR_UPN
Definition: resource.h:30
Definition: whoami.c:28
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
smooth NULL
Definition: ftsmooth.c:416
_In_ ULONG Rows
Definition: haltypes.h:7
#define SE_GROUP_ENABLED_BY_DEFAULT
Definition: setypes.h:91
void WhoamiPrintHeader(int HeaderId)
Definition: whoami.c:131
#define IDS_STATE_DISABLED
Definition: resource.h:28
Definition: bufpool.h:45
#define IDS_TP_WELL_KNOWN_GROUP
Definition: resource.h:16
#define IDS_STATE_ENABLED
Definition: resource.h:27
#define IDS_COL_ATTRIB
Definition: resource.h:11
struct _TOKEN_GROUPS * PTOKEN_GROUPS
int WhoamiUser(void)
Definition: whoami.c:419
#define IDS_COL_SID
Definition: resource.h:10
BOOL WINAPI LookupAccountSidW(LPCWSTR pSystemName, PSID pSid, LPWSTR pAccountName, LPDWORD pdwAccountName, LPWSTR pDomainName, LPDWORD pdwDomainName, PSID_NAME_USE peUse)
Definition: misc.c:537
#define IDS_ATTR_GROUP_ENABLED
Definition: resource.h:22
unsigned int BOOL
Definition: ntddk_ex.h:94
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
void WhoamiSetTableDyn(WhoamiTable *pTable, WCHAR *Entry, UINT Row, UINT Col)
Definition: whoami.c:193
static DWORD DWORD * dwLength
Definition: fusion.c:83
#define IDS_USER_HEADER
Definition: resource.h:3
#define SE_GROUP_ENABLED
Definition: setypes.h:92
#define IDS_ATTR_GROUP_ENABLED_BY_DEFAULT
Definition: resource.h:21
HANDLE WINAPI GetCurrentProcess(VOID)
Definition: proc.c:1168
BOOL GetArgument(WCHAR *arg, int argc, WCHAR *argv[])
Definition: whoami.c:33
#define MAX_PATH
Definition: compat.h:26
unsigned int UINT
Definition: ndis.h:50
void WhoamiPrintTable(WhoamiTable *pTable)
Definition: whoami.c:199
#define RC_STRING_MAX_SIZE
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define SE_GROUP_MANDATORY
Definition: setypes.h:90
enum _TOKEN_INFORMATION_CLASS TOKEN_INFORMATION_CLASS
_Must_inspect_result_ typedef _In_ ULONG _In_ BOOLEAN Target
Definition: iotypes.h:1067
int ret
#define IDS_PRIV_HEADER
Definition: resource.h:5
struct _TOKEN_PRIVILEGES * PTOKEN_PRIVILEGES
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1087
#define TOKEN_READ
Definition: setypes.h:897
#define IDS_COL_DESCRIPTION
Definition: resource.h:13
#define WAM_USER
Definition: _list.h:228
#define IDS_ERROR_INVALIDARG
Definition: resource.h:36
#define wcsicmp
Definition: string.h:1152
unsigned char BYTE
Definition: ntddk_ex.h:96
#define SE_GROUP_LOGON_ID
Definition: setypes.h:98
#define IDS_TP_ALIAS
Definition: resource.h:17
#define IDS_COL_USER_NAME
Definition: resource.h:7
BOOL WINAPI LookupPrivilegeDisplayNameW(LPCWSTR lpSystemName, LPCWSTR lpName, LPWSTR lpDisplayName, LPDWORD cchDisplayName, LPDWORD lpLanguageId)
Definition: misc.c:901
#define IDS_GROU_HEADER
Definition: resource.h:4
#define WAM_GROUPS
#define IDS_ERROR_INVALIDSYNTAX
Definition: resource.h:35
#define IDS_ERROR_VALUEXPECTED
Definition: resource.h:32
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
#define IDS_COL_STATE
Definition: resource.h:14
SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]
Definition: setypes.h:964
#define IDS_HELP
Definition: resource.h:3
UINT Rows
Definition: whoami.c:149
#define IDS_ERROR_1TIMES
Definition: resource.h:34
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:292
#define IDS_COL_TYPE
Definition: resource.h:9
static PSID pSid
Definition: security.c:74
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
int wmain(int argc, WCHAR *argv[])
Definition: whoami.c:665
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]
Definition: setypes.h:970
BOOLEAN WINAPI GetUserNameExW(EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
Definition: sspi.c:1079
UINT Cols
Definition: whoami.c:150
#define IDS_COL_PRIV_NAME
Definition: resource.h:12
$ULONG GroupCount
Definition: setypes.h:960
#define IDS_UNKNOWN_DESCRIPTION
Definition: resource.h:25
unsigned int ULONG
Definition: retypes.h:1
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:409
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:845
struct _TOKEN_USER * PTOKEN_USER
SID_AND_ATTRIBUTES User
Definition: setypes.h:956
static const EHCI_PERIOD pTable[]
Definition: usbehci.c:29
int WhoamiPriv(void)
Definition: whoami.c:589
VOID * WhoamiGetTokenInfo(TOKEN_INFORMATION_CLASS TokenType)
Definition: whoami.c:81
void exit(int exitcode)
Definition: _exit.c:33
WCHAR * LPWSTR
Definition: xmlstorage.h:184
int WhoamiGroups(void)
Definition: whoami.c:462
enum @4 PrintFormat
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:394
base of all file and directory entries
Definition: entries.h:82
WhoamiTable * WhoamiAllocTable(UINT Rows, UINT Cols)
Definition: whoami.c:155
#define IDS_ERROR_NH_LIST
Definition: resource.h:37
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ BOOLEAN _In_ TOKEN_TYPE TokenType
Definition: sefuncs.h:417
UINT PrintFormatArgCount
Definition: whoami.c:22
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10