Index: base/applications/cmdutils/CMakeLists.txt =================================================================== --- base/applications/cmdutils/CMakeLists.txt (revision 65654) +++ base/applications/cmdutils/CMakeLists.txt (working copy) @@ -12,6 +12,7 @@ add_subdirectory(sort) add_subdirectory(taskkill) add_subdirectory(tree) +add_subdirectory(whoami) add_subdirectory(wmic) add_subdirectory(wscript) add_subdirectory(xcopy) Index: base/applications/cmdutils/whoami/CMakeLists.txt =================================================================== --- base/applications/cmdutils/whoami/CMakeLists.txt (revision 0) +++ base/applications/cmdutils/whoami/CMakeLists.txt (working copy) @@ -0,0 +1,5 @@ + +add_executable(whoami whoami.c whoami.rc) +set_module_type(whoami win32cui UNICODE) +add_importlibs(whoami user32 secur32 advapi32 msvcrt kernel32) +add_cd_file(TARGET whoami DESTINATION reactos/system32 FOR all) Index: base/applications/cmdutils/whoami/lang/en-US.rc =================================================================== --- base/applications/cmdutils/whoami/lang/en-US.rc (revision 0) +++ base/applications/cmdutils/whoami/lang/en-US.rc (working copy) @@ -0,0 +1,78 @@ +/* English resource file for Whoami -- Translated by Swyter */ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_USER_HEADER "USER INFORMATION" + IDS_GROU_HEADER "GROUP INFORMATION" + IDS_PRIV_HEADER "PRIVILEGES INFORMATION" + + IDS_COL_USER_NAME "User Name" + IDS_COL_GROUP_NAME "Group Name" + IDS_COL_TYPE "Type" + IDS_COL_SID "SID" + IDS_COL_ATTRIB "Attributes" + IDS_COL_PRIV_NAME "Privilege Name" + IDS_COL_DESCRIPTION "Description" + IDS_COL_STATE "State" + + IDS_TP_WELL_KNOWN_GROUP "Well-known group" + IDS_TP_ALIAS "Alias" + IDS_TP_LABEL "Label" + + /* [!] important note from the programmer: the program tries to remove + the last ', ' after concatenating, so keep than in mind when translating. + + you can test your translation of these attributes by using 'whoami /groups' */ + + IDS_ATTR_GROUP_MANDATORY "Mandatory group, " + IDS_ATTR_GROUP_ENABLED_BY_DEFAULT "Enabled by default, " + IDS_ATTR_GROUP_ENABLED "Enabled group, " + IDS_ATTR_GROUP_OWNER "Group owner, " + + IDS_UNKNOWN_DESCRIPTION "???" + + IDS_STATE_ENABLED "Enabled" + IDS_STATE_DISABLED "Disabled" + + IDS_ERROR_UPN "ERROR: Unable to get User Principal Name (UPN) as the current logged-on user\n" + " is not a domain user.\n" + + IDS_ERROR_FQDN "ERROR: Unable to get Fully Qualified Distinguished Name (FQDN) as the current\n" + " logged-on user is not a domain user.\n" + + IDS_ERROR_VALUEXPECTED "ERROR: Invalid syntax. Value expected for '/fo'.\n" + "Type ""WHOAMI /?"" for usage.\n" + + IDS_ERROR_VALUENOTALLOWED "ERROR: Invalid syntax. '%s' value is not allowed for '/fo' option.\n" + "Type ""WHOAMI /?"" for usage.\n" + + IDS_ERROR_1TIMES "ERROR: Invalid syntax. '%s' option is not allowed more than '1' time(s).\n" + "Type ""WHOAMI /?"" for usage.\n" + + IDS_ERROR_INVALIDSYNTAX "ERROR: Invalid syntax.\n" + "Type ""WHOAMI /?"" for usage.\n" + + IDS_ERROR_INVALIDARG "ERROR: Invalid argument/option - '%s'.\n" + "Type ""WHOAMI /?"" for usage.\n" + + IDS_ERROR_NH_LIST "ERROR: /NH switch cannot be used with the LIST format.\n" + "Type ""WHOAMI /?"" for usage.\n" + + IDS_HELP "DESCRIPTION:\n" + " Display user, group and privileges information for the local logged-on user.\n" + " If no arguments are provided, displays the current domain and user name.\n" + " \n" + " Available output formats for the '/fo' option are 'csv', 'list' and 'table'.\n" + " Use '/nh' to hide headers. By default the data is displayed in a table.\n" + " \n" + "SYNTAX:\n" + " whoami [/upn | /fqdn | /logonid] \n" + " whoami {[/user] [/groups] [/priv]} [/fo ] [/nh] \n" + " whoami /all [/fo ] [/nh] \n" + " \n" + "EXAMPLES: \n" + " whoami /groups /priv /nh /fo csv \n" + " whoami /logonid \n" + " whoami \n" +END \ No newline at end of file Index: base/applications/cmdutils/whoami/lang/es-ES.rc =================================================================== --- base/applications/cmdutils/whoami/lang/es-ES.rc (revision 0) +++ base/applications/cmdutils/whoami/lang/es-ES.rc (working copy) @@ -0,0 +1,79 @@ +/* Spanish resource file for Whoami -- Translated by Swyter */ +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL + +STRINGTABLE +BEGIN + IDS_USER_HEADER "INFORMACIÓN DE USUARIO" + IDS_GROU_HEADER "INFORMACIÓN DE GRUPO" + IDS_PRIV_HEADER "INFORMACIÓN DE PRIVILEGIOS" + + IDS_COL_USER_NAME "Nombre de usuario" + IDS_COL_GROUP_NAME "Nombre de grupo" + IDS_COL_TYPE "Tipo" + IDS_COL_SID "SID" + IDS_COL_ATTRIB "Atributos" + IDS_COL_PRIV_NAME "Nombre de privilegio" + IDS_COL_DESCRIPTION "Descripción" + IDS_COL_STATE "Estado" + + IDS_TP_WELL_KNOWN_GROUP "Grupo conocido" + IDS_TP_ALIAS "Alias" + IDS_TP_LABEL "Etiqueta" + + /* [!] important note from the programmer: the program tries to remove + the last ', ' after concatenating, so keep than in mind when translating. + + you can test your translation of these attributes by using 'whoami /groups' */ + + IDS_ATTR_GROUP_MANDATORY "Grupo obligatorio, " + IDS_ATTR_GROUP_ENABLED_BY_DEFAULT "Habilitado de manera predeterminada, " + IDS_ATTR_GROUP_ENABLED "Grupo habilitado, " + IDS_ATTR_GROUP_OWNER "Propietario de grupo, " + + IDS_UNKNOWN_DESCRIPTION "¿?" + + IDS_STATE_ENABLED "Habilitada" + IDS_STATE_DISABLED "Deshabilitado" + + IDS_ERROR_UPN "ERROR: no se puede obtener el nombre principal de usuario (UPN) porque el\n" + " usuario que ha iniciado sesión no es un usuario de dominio.\n" + + IDS_ERROR_FQDN "ERROR: no se puede obtener el nombre distintivo completo (FQDN) porque el usuario\n" + " que ha iniciado sesión no es un usuario de dominio.\n" + + IDS_ERROR_VALUEXPECTED "ERROR: Sintaxis no válida. Se esperaba un valor para ""/fo"".\n" + "Escriba ""WHOAMI /?"" para su uso.\n" + + IDS_ERROR_VALUENOTALLOWED "ERROR: Sintaxis no válida. El valor ""%s"" no está permitido para la opción ""/fo"".\n" + "Escriba ""WHOAMI /?"" para su uso.\n" + + IDS_ERROR_1TIMES "ERROR: Sintaxis no válida. La opción ""%s"" no está permitida más de ""1"" veces.\n" + "Escriba ""WHOAMI /?"" para su uso.\n" + + IDS_ERROR_INVALIDSYNTAX "ERROR: sintaxis no válida.\n" + "Escriba ""WHOAMI /?"" para obtener detalles de uso.\n" + + IDS_ERROR_INVALIDARG "ERROR: Argumento u opción no válido - ""%s"".\n" + "Escriba ""WHOAMI /?"" para su uso.\n" + + IDS_ERROR_NH_LIST "ERROR: no se puede usar el modificador /NH con el formato LIST.\n" + " Escriba ""WHOAMI /?"" para obtener detalles de uso.\n" + + IDS_HELP "DESCRIPCIÓN:\n" + " Muestra información sobre el usuario local, sus privilegios y grupos.\n" + " Si no se añaden argumentos se mostrará el usuario y dominio actual.\n" + " \n" + " Los formatos disponibles para '/fo' son 'csv', 'list' y 'table'.\n" + " Por defecto los datos se muestran en una tabla (opción 'table').\n" + " Puedes utilizar '/nh' para ocultar los encabezados. \n" + " \n" + "SINTAXIS:\n" + " whoami [/upn | /fqdn | /logonid] \n" + " whoami {[/user] [/groups] [/priv]} [/fo ] [/nh] \n" + " whoami /all [/fo ] [/nh] \n" + " \n" + "EJEMPLOS: \n" + " whoami /groups /priv /nh /fo csv \n" + " whoami /logonid \n" + " whoami \n" +END \ No newline at end of file =================================================================== --- base/applications/cmdutils/whoami/lang (revision 0) +++ base/applications/cmdutils/whoami/lang (working copy) Property changes on: base/applications/cmdutils/whoami/lang ___________________________________________________________________ Added: bugtraq:url ## -0,0 +1 ## +http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID% \ No newline at end of property Added: bugtraq:message ## -0,0 +1 ## +See issue #%BUGID% for more details. \ No newline at end of property Added: tsvn:logminsize ## -0,0 +1 ## +10 \ No newline at end of property Added: bugtraq:logregex ## -0,0 +1,2 ## +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+) \ No newline at end of property Index: base/applications/cmdutils/whoami/resource.h =================================================================== --- base/applications/cmdutils/whoami/resource.h (revision 0) +++ base/applications/cmdutils/whoami/resource.h (working copy) @@ -0,0 +1,39 @@ +#pragma once + +#define IDS_USER_HEADER 0 +#define IDS_GROU_HEADER 1 +#define IDS_PRIV_HEADER 2 + +#define IDS_COL_USER_NAME 3 +#define IDS_COL_GROUP_NAME 4 +#define IDS_COL_TYPE 5 +#define IDS_COL_SID 6 +#define IDS_COL_ATTRIB 7 +#define IDS_COL_PRIV_NAME 8 +#define IDS_COL_DESCRIPTION 9 +#define IDS_COL_STATE 10 + +#define IDS_TP_WELL_KNOWN_GROUP 11 +#define IDS_TP_ALIAS 12 +#define IDS_TP_LABEL 13 + +#define IDS_ATTR_GROUP_MANDATORY 14 +#define IDS_ATTR_GROUP_ENABLED_BY_DEFAULT 15 +#define IDS_ATTR_GROUP_ENABLED 16 +#define IDS_ATTR_GROUP_OWNER 17 + +#define IDS_UNKNOWN_DESCRIPTION 18 + +#define IDS_STATE_ENABLED 19 +#define IDS_STATE_DISABLED 20 + +#define IDS_ERROR_UPN 21 +#define IDS_ERROR_FQDN 22 +#define IDS_ERROR_VALUEXPECTED 23 +#define IDS_ERROR_VALUENOTALLOWED 24 +#define IDS_ERROR_1TIMES 25 +#define IDS_ERROR_INVALIDSYNTAX 26 +#define IDS_ERROR_INVALIDARG 27 +#define IDS_ERROR_NH_LIST 28 + +#define IDS_HELP 29 \ No newline at end of file Index: base/applications/cmdutils/whoami/whoami.c =================================================================== --- base/applications/cmdutils/whoami/whoami.c (revision 0) +++ base/applications/cmdutils/whoami/whoami.c (working copy) @@ -0,0 +1,960 @@ +/* + * WHOAMI -- Compatible reimplementation for ReactOS + * Copyright (C) 2014 Ismael Ferreras Morezuelas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +/* + * COPYRIGHT : See COPYING in the top level directory + * PROJECT : ReactOS/Win32/Whoami -- Display information about the current local user, groups and privileges. + * FILE : base/applications/cmdutils/whoami/whoami.c + * PROGRAMMER: Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com) + */ + +#include + +#include +#include +#include + +#include +#include + +#define SECURITY_WIN32 +#include +#include + +#include + +#include "resource.h" + + +/* IMPORTED FUNCTIONS IN THE ORIGINAL EXECUTABLE + * + + LookupPrivilegeNameW //ADVAPI.dll + LookupPrivilegeDisplayNameW + CopySid + GetLengthSid + AdjustTokenPrivileges + LookupPrivilegeValueW + OpenProcessToken + LookupAccountSidW + GetSidSubAuthority + GetSidSubAuthorityCount + GetSidIdentifierAuthority + IsValidSid + GetTokenInformation + + CharUpperW //USER32.dll + LoadStringW + CharLowerW + + GetUserNameEx //Secur32.dll + + Ordinal 74 //WS2_32.dll + + */ + +BOOL no_header = FALSE; +UINT no_header_arg_count = 0; +UINT print_format_arg_count = 0; +enum +{ + undefined, + table, + list, + csv +} print_format = undefined; + + +BOOL get_argument(WCHAR* arg, int argc, WCHAR* argv[]) +{ + int i; + + if (!arg) + goto bail_out; + + for (i=1; irows = rows; + ptable->cols = cols; + + return ptable; +} + +/* allocate and fill a new entry in the table */ +void whoami_set_table(whoami_table *ptable, WCHAR *entry, UINT row, UINT col) +{ + LPWSTR target = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1 + wcslen(entry) * sizeof(entry[0])); + + // wprintf(L"DEBUG: Setting table value '%lp' '%ls' for %lu %lu.\n", entry, entry, row, col); + + if (!target) + exit(1); + + wcscpy(target, entry); + + ptable->content[row * ptable->cols + col] = target; +} + +/* fill a new entry in the table */ +void whoami_set_table_dyn(whoami_table *ptable, WCHAR *entry, UINT row, UINT col) +{ + ptable->content[row * ptable->cols + col] = entry; +} + +/* print and deallocate the table */ +void whoami_print_table(whoami_table *ptable) +{ + UINT i; + UINT j; + + UINT cur_row, cur_col; + + UINT *col_len; + + + if (!ptable) + { + wprintf(L"ERROR: The table passed for display is empty."); + exit(1); + } + + /* if we are going to print a *list* or *table*; take note of the total column size, as we will need it + later on when printing them in a tabular fashion, according to their windows counterparts */ + + if (print_format != csv) + { + col_len = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(UINT) * ptable->cols); + + if (print_format == list) + { + for (j = 0; j < ptable->cols; j++) + if (ptable->content[j]) + { + UINT this_len = wcslen(ptable->content[j]); + + /* now that we're here, seize the opportunity and add those pesky ":" */ + ptable->content[j][this_len++] = L':'; + ptable->content[j][this_len] = UNICODE_NULL; + + col_len[0] = max(this_len, col_len[0]); + } + } + else + { + for (j = 0; j < ptable->cols; j++) + for (i = 0; i < ptable->rows; i++) + if (ptable->content[i * ptable->cols + j]) + { + UINT this_len = wcslen(ptable->content[i * ptable->cols + j]); + col_len[j] = max(this_len, col_len[j]); + } + } + } + + switch (print_format) + { + case csv: + { + for (i = 0; i < ptable->rows; i++) + { + if (!ptable->content[i * ptable->cols]) + continue; + + /* if the user especified /nh then skip the column labels */ + if (no_header && i == 0) + continue; + + for (j = 0; j < ptable->cols; j++) + { + if (ptable->content[i * ptable->cols + j]) + { + wprintf(L"\"%s\"%s", ptable->content[i * ptable->cols + j], (j+1 < ptable->cols ? L"," : L"")); + } + } + wprintf(L"\n"); + } + + break; + + } + + case list: + { + UINT final_row = 0; + + /* 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 */ + for (cur_row = 1; cur_row < ptable->rows; cur_row++) + { + /* if the first member of this row isn't available, then forget it */ + if (!ptable->content[cur_row * ptable->cols]) + continue; + + final_row = cur_row; + } + + for (cur_row = 1; cur_row < ptable->rows; cur_row++) + { + /* if the first member of this row isn't available, then forget it */ + if (!ptable->content[cur_row * ptable->cols]) + continue; + + /* if the user especified /nh then skip the column labels */ + if (no_header && i == 0) + continue; + + for (cur_col = 0; cur_col < ptable->cols; cur_col++) + { + wprintf(L"%-*s %s\n", col_len[0], ptable->content[cur_col], ptable->content[cur_row * ptable->cols + cur_col]); + } + + /* don't add two carriage returns at the very end */ + if (cur_row != final_row) + wprintf(L"\n"); + } + + break; + } + + + case table: + default: + { + for (i = 0; i < ptable->rows; i++) + { + /* if the first member of this row isn't available, then forget it */ + if (!ptable->content[i * ptable->cols]) + continue; + + /* if the user especified /nh then skip the column labels too */ + if (no_header && i == 0) + continue; + + for (j = 0; j < ptable->cols; j++) + { + if (ptable->content[i * ptable->cols + j]) + { + wprintf(L"%-*s ", col_len[j], ptable->content[i * ptable->cols + j]); + } + } + wprintf(L"\n"); + + /* add the cute underline thingie for the table header */ + if (i == 0) + { + for (j = 0; j < ptable->cols; j++) + { + DWORD len = col_len[j]; + + while (len--) + wprintf(L"="); + + /* a spacing between all the columns except for the last one */ + if (ptable->cols != (i + 1)) + wprintf(L" "); + } + + wprintf(L"\n"); + } + } + + } + } + + /* when many tables are displayed in a single run we + have to sandwich carriage returns in between. */ + // if (!final_emtry) + wprintf(L"\n"); + + for (i = 0; i < ptable->rows; i++) + for (j = 0; j < ptable->cols; j++) + whoami_free(ptable->content[i * ptable->cols + j]); + + whoami_free(ptable); + } + + +int whoami_logonid(void) +{ + PTOKEN_GROUPS pGroupInfo = (PTOKEN_GROUPS) whoami_get_token_info(TokenGroups); + DWORD dwIndex = 0; + LPWSTR pSid = 0; + PSID ppsid = 0; + + if (pGroupInfo) + { + /* lets see if we can find the logon SID in that list, should be there */ + for (dwIndex = 0; dwIndex < pGroupInfo->GroupCount; dwIndex++) + { + if ((pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) + { + ppsid = pGroupInfo->Groups[dwIndex].Sid; + } + } + + if (!ppsid || !ConvertSidToStringSidW(ppsid, &pSid)) + { + wprintf(L"ERROR: Couldn't convert the logon SID to a string.\n"); + return 1; + } + else + { + /* let's show our converted logon SID */ + wprintf(L"%s\n", pSid); + } + } + + /* cleanup our allocations */ + if (pSid) + LocalFree(pSid); + + if (pGroupInfo) + whoami_free(pGroupInfo); + + return 0; +} + +int whoami_user(void) +{ + PTOKEN_USER pUserInfo = (PTOKEN_USER) whoami_get_token_info(TokenUser); + LPWSTR pUserStr = whoami_get_user(NameSamCompatible); + + LPWSTR pSid = NULL; + + if (pUserInfo && pUserStr) + { + whoami_table *user_table = whoami_alloc_table(2, 2); + + whoami_print_header(IDS_USER_HEADER); + + /* set the column labels */ + whoami_set_table(user_table, whoami_load_rc_string(IDS_COL_USER_NAME), 0, 0); + whoami_set_table(user_table, whoami_load_rc_string(IDS_COL_SID), 0, 1); + + ConvertSidToStringSidW(pUserInfo->User.Sid, &pSid); + + /* set the values for our single row of data */ + whoami_set_table(user_table, pUserStr, 1, 0); + whoami_set_table(user_table, pSid, 1, 1); + + whoami_print_table(user_table); + } + else + { + return 1; + } + + /* cleanup our allocations */ + if (pSid) + LocalFree(pSid); + + if (pUserInfo) + whoami_free(pUserInfo); + + if (pUserStr) + whoami_free(pUserStr); + + return 0; +} + +int whoami_groups(void) +{ + DWORD dwIndex = 0; + LPWSTR pSid = 0; + + static WCHAR szGroupName[255] = {0}; + static WCHAR szDomainName[255] = {0}; + + DWORD cchGroupName = _countof(szGroupName); + DWORD cchDomainName = _countof(szGroupName); + + SID_NAME_USE Use = 0; + BYTE sid_name_use_str[12] = + { + /* SidTypeUser */ -1, + /* SidTypeGroup */ -1, + /* SidTypeDomain */ -1, + /* SidTypeUser */ -1, + /* SidTypeAlias */ IDS_TP_ALIAS, + /* SidTypeWellKnownGroup */ IDS_TP_WELL_KNOWN_GROUP, + /* SidTypeDeletedAccount */ -1, + /* SidTypeInvalid */ -1, + /* SidTypeUnknown */ -1, + /* SidTypeComputer */ -1, + /* SidTypeLabel */ IDS_TP_LABEL + }; + + PTOKEN_GROUPS pGroupInfo = (PTOKEN_GROUPS) whoami_get_token_info(TokenGroups); + + if (pGroupInfo) + { + /* the header is the first (0) row, so we start in the second one (1) */ + UINT printing_row = 1; + + whoami_table *group_table = whoami_alloc_table(pGroupInfo->GroupCount + 1, 4); + + whoami_print_header(IDS_GROU_HEADER); + + whoami_set_table(group_table, whoami_load_rc_string(IDS_COL_GROUP_NAME), 0, 0); + whoami_set_table(group_table, whoami_load_rc_string(IDS_COL_TYPE), 0, 1); + whoami_set_table(group_table, whoami_load_rc_string(IDS_COL_SID), 0, 2); + whoami_set_table(group_table, whoami_load_rc_string(IDS_COL_ATTRIB), 0, 3); + + for (dwIndex = 0; dwIndex < pGroupInfo->GroupCount; dwIndex++) + { + LookupAccountSidW(NULL, + pGroupInfo->Groups[dwIndex].Sid, + + (LPWSTR)&szGroupName, + &cchGroupName, + + (LPWSTR)&szDomainName, + &cchDomainName, + + &Use); + + /* the original tool seems to limit the list to these kind of SID items */ + if ((Use == SidTypeWellKnownGroup || Use == SidTypeAlias || Use == SidTypeLabel) && !(pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_LOGON_ID)) + { + wchar_t tmpBuffer[666]; + + /* looks like windows treats 0x60 as 0x7 for some reason, let's just nod and call it a day: + 0x60 is SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED + 0x07 is SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED */ + + if (pGroupInfo->Groups[dwIndex].Attributes == 0x60) + pGroupInfo->Groups[dwIndex].Attributes = 0x07; + + /* 1- format it as DOMAIN\GROUP if the domain exists, or just GROUP if not */ + _snwprintf((LPWSTR)&tmpBuffer, 666, L"%s%s%s",szDomainName, + cchDomainName ? L"\\" : L"", + szGroupName); + + whoami_set_table(group_table, tmpBuffer, printing_row, 0); + + /* 2- let's find out the group type by using a simple lookup table for lack of a better method */ + whoami_set_table(group_table, whoami_load_rc_string(sid_name_use_str[Use]), printing_row, 1); + + /* 3- turn that SID into text-form */ + ConvertSidToStringSidW(pGroupInfo->Groups[dwIndex].Sid, &pSid); + + whoami_set_table(group_table, pSid, printing_row, 2); + + LocalFree(pSid); + + /* 4- reuse that buffer for appending the attributes in text-form at the very end */ + ZeroMemory(tmpBuffer, 666); + + if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_MANDATORY) + StringCchCat(tmpBuffer, 666, whoami_load_rc_string(IDS_ATTR_GROUP_MANDATORY)); + if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_ENABLED_BY_DEFAULT) + StringCchCat(tmpBuffer, 666, whoami_load_rc_string(IDS_ATTR_GROUP_ENABLED_BY_DEFAULT)); + if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_ENABLED) + StringCchCat(tmpBuffer, 666, whoami_load_rc_string(IDS_ATTR_GROUP_ENABLED)); + if (pGroupInfo->Groups[dwIndex].Attributes & SE_GROUP_OWNER) + StringCchCat(tmpBuffer, 666, whoami_load_rc_string(IDS_ATTR_GROUP_OWNER)); + + /* remove the last comma (', ' which is 2 wchars) of the buffer, let's keep it simple */ + tmpBuffer[max(wcslen(tmpBuffer) - 2, 0)] = UNICODE_NULL; + + whoami_set_table(group_table, tmpBuffer, printing_row, 3); + + printing_row++; + } + + /* reset the buffers so that we can reuse them */ + ZeroMemory(szGroupName, 255); + ZeroMemory(szDomainName, 255); + + cchGroupName = 255; + cchDomainName = 255; + } + + whoami_print_table(group_table); + } + else + { + return 1; + } + + /* cleanup our allocations */ + if (pGroupInfo) + whoami_free((LPVOID)pGroupInfo); + + return 0; +} + +int whoami_priv(void) +{ + PTOKEN_PRIVILEGES pPrivInfo = (PTOKEN_PRIVILEGES) whoami_get_token_info(TokenPrivileges); + + if (pPrivInfo) + { + DWORD dwResult = 0, dwIndex = 0; + + whoami_table *priv_table = whoami_alloc_table(pPrivInfo->PrivilegeCount+1, 3); + + whoami_print_header(IDS_PRIV_HEADER); + + whoami_set_table(priv_table, whoami_load_rc_string(IDS_COL_PRIV_NAME), 0, 0); + whoami_set_table(priv_table, whoami_load_rc_string(IDS_COL_DESCRIPTION), 0, 1); + whoami_set_table(priv_table, whoami_load_rc_string(IDS_COL_STATE), 0, 2); + + for (dwIndex = 0; dwIndex < pPrivInfo->PrivilegeCount; dwIndex++) + { + LPWSTR priv_name = NULL, disp_name = NULL; + DWORD priv_name_sz = 0, disp_name_sz = 0; + BOOL ret = FALSE; + + ret = LookupPrivilegeNameW( + NULL, + &pPrivInfo->Privileges[dwIndex].Luid, + NULL, + &priv_name_sz + ); + + priv_name = HeapAlloc(GetProcessHeap(), 0, ++priv_name_sz*sizeof(WCHAR)); + + LookupPrivilegeNameW( + NULL, + &pPrivInfo->Privileges[dwIndex].Luid, + priv_name, + &priv_name_sz + ); + + whoami_set_table_dyn(priv_table, priv_name, dwIndex+1, 0); + + ret = LookupPrivilegeDisplayNameW( + NULL, + priv_name, + NULL, + &disp_name_sz, + &dwResult + ); + + if (!ret || GetLastError() == ERROR_NO_SUCH_PRIVILEGE) + { + disp_name = HeapAlloc(GetProcessHeap(), 0, ++disp_name_sz*sizeof(WCHAR)); + + LookupPrivilegeDisplayNameW( + NULL, + priv_name, + disp_name, + &disp_name_sz, + &dwResult + ); + + //wprintf(L"disp_name: %d %x '%s'\n", disp_name_sz, GetLastError(), disp_name); + + whoami_set_table_dyn(priv_table, disp_name, dwIndex+1, 1); + } + else + { + whoami_set_table(priv_table, whoami_load_rc_string(IDS_UNKNOWN_DESCRIPTION), dwIndex+1, 1); + } + + if (pPrivInfo->Privileges[dwIndex].Attributes & SE_PRIVILEGE_ENABLED) + whoami_set_table(priv_table, whoami_load_rc_string(IDS_STATE_ENABLED), dwIndex+1, 2); + else + whoami_set_table(priv_table, whoami_load_rc_string(IDS_STATE_DISABLED), dwIndex+1, 2); + } + + whoami_print_table(priv_table); + } + else + { + return 1; + } + + /* cleanup our allocations */ + if (pPrivInfo) + whoami_free(pPrivInfo); + + return 0; +} + +int wmain(int argc, WCHAR* argv[]) +{ + UINT i; + BYTE wam_bit = 0; + + #define WAM_USER 1<<0 + #define WAM_GROUPS 1<<1 + #define WAM_PRIV 1<<2 + + + /* * * * * * * * * * * * * * * * + * A: no parameters whatsoever */ + + if (argc == 1) + { + /* if there's no arguments just choose the simple path and display the user's identity in lowercase */ + LPWSTR usr_buffer = whoami_get_user(NameSamCompatible); + + if (usr_buffer) + { + wprintf(L"%s\n", usr_buffer); + whoami_free(usr_buffer); + return 0; + } + else + { + return 1; + } + } + + /* first things first-- let's detect and manage both printing modifiers (/fo and /nh) */ + for (i=1; i= 2) + { + wprintf(whoami_load_rc_string(IDS_ERROR_1TIMES), L"/nh"); + return 1; + } + /* special case when there's just a /nh as argument; it outputs nothing */ + else if (no_header_arg_count == 1 && argc == 2) + { + return 0; + } + + if (print_format_arg_count >= 2) + { + wprintf(whoami_load_rc_string(IDS_ERROR_1TIMES), L"/fo"); + return 1; + } + /* if there's just /fo ... call it invalid */ + else if (print_format_arg_count == 1 && argc == 3) + { + goto invalid_syntax; + } + + /* * * * * * * * * * * * * * + * B: one single parameter */ + + if (argc == 2) + { + /* now let's try to parse the triumvirate of simpler, single (1) arguments... plus help */ + if (wcsicmp(argv[1], L"/?") == 0) + { + wprintf(whoami_load_rc_string(IDS_HELP)); + return 0; + } + + else if (wcsicmp(argv[1], L"/upn") == 0) + { + LPWSTR usr_buffer = whoami_get_user(NameUserPrincipal); + + if (usr_buffer) + { + wprintf(L"%s\n", usr_buffer); + whoami_free(usr_buffer); + return 0; + } + else + { + wprintf(whoami_load_rc_string(IDS_ERROR_UPN)); + return 1; + } + } + + else if (wcsicmp(argv[1], L"/fqdn") == 0) + { + LPWSTR usr_buffer = whoami_get_user(NameFullyQualifiedDN); + + if (usr_buffer) + { + wprintf(L"%s\n", usr_buffer); + whoami_free(usr_buffer); + return 0; + } + else + { + wprintf(whoami_load_rc_string(IDS_ERROR_FQDN)); + return 1; + } + } + + else if (wcsicmp(argv[1], L"/logonid") == 0) + { + return whoami_logonid(); + } + } + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * C: One main parameter with extra tasty modifiers to play with */ + + /* sometimes is just easier to whitelist for lack of a better method */ + for (i=1; i + +#include "resource.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#define REACTOS_STR_FILE_DESCRIPTION "whoami: display information about logged-on users" +#define REACTOS_STR_INTERNAL_NAME "whoami" +#define REACTOS_STR_ORIGINAL_FILENAME "whoami.exe" +#define REACTOS_STR_COMPANY_NAME "Ismael Ferreras Morezuelas" + +#include + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif +#ifdef LANGUAGE_ES_ES + #include "lang/es-ES.rc" +#endif