Particularly it implements '/logonid' and '/user' options, as well as adds stubs for '/upn' and '/fqdn'.
-- v7: whoami: Refactor and add more commands.
From: Maxim Karasev mxkrsv@etersoft.ru
--- dlls/secur32/secur32.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c index 46a80c9a76c..bb723e90004 100644 --- a/dlls/secur32/secur32.c +++ b/dlls/secur32/secur32.c @@ -1140,6 +1140,7 @@ BOOLEAN WINAPI GetUserNameExW( case NameCanonicalEx: case NameServicePrincipal: case NameDnsDomain: + FIXME("NameFormat %d not implemented\n", NameFormat); SetLastError(ERROR_NONE_MAPPED); return FALSE;
From: Maxim Karasev mxkrsv@etersoft.ru
Particularly it implements '/logonid' and '/user' options, as well as adds stubs for '/upn' and '/fqdn'. --- programs/whoami/Makefile.in | 2 +- programs/whoami/main.c | 267 ++++++++++++++++++++++++++++++++---- 2 files changed, 239 insertions(+), 30 deletions(-)
diff --git a/programs/whoami/Makefile.in b/programs/whoami/Makefile.in index 4898a96f456..5be08c702a8 100644 --- a/programs/whoami/Makefile.in +++ b/programs/whoami/Makefile.in @@ -1,5 +1,5 @@ MODULE = whoami.exe -IMPORTS = secur32 +IMPORTS = secur32 advapi32
EXTRADLLFLAGS = -mconsole -municode
diff --git a/programs/whoami/main.c b/programs/whoami/main.c index 7e93de998ef..c98a553d32d 100644 --- a/programs/whoami/main.c +++ b/programs/whoami/main.c @@ -1,5 +1,6 @@ /* * Copyright 2020 Brendan Shanks for CodeWeavers + * Copyright 2023 Maxim Karasev mxkrsv@etersoft.ru * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,9 +17,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#define WIN32_LEAN_AND_MEAN #define SECURITY_WIN32 #include <windows.h> #include <security.h> +#include <sddl.h> +#include <stdarg.h>
#include "wine/debug.h"
@@ -27,67 +31,272 @@ WINE_DEFAULT_DEBUG_CHANNEL(whoami); static int output_write(const WCHAR* str, int len) { DWORD count; + + if (len < 0) + len = wcslen(str); + if (!WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, len, &count, NULL)) { DWORD lenA; - char* strA; + char *strA;
/* On Windows WriteConsoleW() fails if the output is redirected. So fall * back to WriteFile() with OEM code page. */ - lenA = WideCharToMultiByte(GetOEMCP(), 0, str, len, - NULL, 0, NULL, NULL); - strA = HeapAlloc(GetProcessHeap(), 0, lenA); + lenA = WideCharToMultiByte(GetOEMCP(), 0, str, len, NULL, 0, NULL, NULL); + strA = malloc(lenA); if (!strA) return 0;
- WideCharToMultiByte(GetOEMCP(), 0, str, len, strA, lenA, - NULL, NULL); + WideCharToMultiByte(GetOEMCP(), 0, str, len, strA, lenA, NULL, NULL); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), strA, lenA, &count, FALSE); - HeapFree(GetProcessHeap(), 0, strA); + free(strA); } return count; }
-int __cdecl wmain(int argc, WCHAR *argv[]) +static WCHAR *get_user_name(EXTENDED_NAME_FORMAT name_format) { - WCHAR *buf = NULL; ULONG size = 0; - BOOL result; + WCHAR *ret;
- if (argc > 1) + if (GetUserNameExW(name_format, NULL, &size) || GetLastError() != ERROR_MORE_DATA) + return NULL; + + ret = malloc(size * sizeof(WCHAR)); + if (!ret) + return NULL; + + if (!GetUserNameExW(name_format, ret, &size)) { - int i; + free(ret); + return NULL; + } + + return ret; +} + +static void *get_token(TOKEN_INFORMATION_CLASS token_type) +{ + HANDLE token_handle; + void *ret; + /* GetTokenInformation wants a dword-aligned buffer */ + ULONG ret_size = sizeof(DWORD) * 256; + ULONG token_size; + + ret = malloc(ret_size); + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_handle)) + return NULL;
- WINE_FIXME("unsupported arguments:"); - for (i = 0; i < argc; i++) - WINE_FIXME(" %s", wine_dbgstr_w(argv[i])); - WINE_FIXME("\n"); + if (!GetTokenInformation(token_handle, token_type, ret, ret_size, &token_size)) + { + CloseHandle(token_handle); + return NULL; + } + + CloseHandle(token_handle); + return ret; +} + +static SID *get_process_sid(void) +{ + ULONG user_sid_len; + TOKEN_USER *token_user; + SID *ret; + + token_user = get_token(TokenUser); + if (!token_user) + return NULL; + + user_sid_len = GetLengthSid(token_user->User.Sid); + ret = malloc(user_sid_len); + if (!ret) + { + free(token_user); + return NULL; }
- result = GetUserNameExW(NameSamCompatible, NULL, &size); - if (result || GetLastError() != ERROR_MORE_DATA) + if (!CopySid(user_sid_len, ret, token_user->User.Sid)) { - WINE_ERR("GetUserNameExW failed, result %d, error %ld\n", result, GetLastError()); + free(token_user); + free(ret); + return NULL; + } + + free(token_user); + return ret; +} + +static SID *get_logon_sid(void) +{ + TOKEN_GROUPS *token_groups; + DWORD group_token_len; + DWORD i; + SID *ret; + + token_groups = get_token(TokenGroups); + if (!token_groups) + return NULL; + + for (i = 0; i < token_groups->GroupCount; i++) + { + if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == SE_GROUP_LOGON_ID) + { + group_token_len = GetLengthSid(token_groups->Groups[i].Sid); + ret = malloc(group_token_len); + if (!ret) + { + free(token_groups); + return NULL; + } + + if (!CopySid(group_token_len, ret, token_groups->Groups[i].Sid)) + { + free(token_groups); + free(ret); + return NULL; + } + + free(token_groups); + return ret; + } + } + + free(token_groups); + return NULL; +} + +static int simple(EXTENDED_NAME_FORMAT name_format) +{ + WCHAR *name; + + name = get_user_name(name_format); + if (!name) + { + ERR("get_user_name failed\n"); return 1; }
- buf = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); - if (!buf) + output_write(name, -1); + output_write(L"\n", 1); + + free(name); + + return 0; +} + +static int logon_id(void) +{ + PSID sid; + WCHAR *sid_string; + + sid = get_logon_sid(); + if (!sid) { - WINE_ERR("Memory allocation failed\n"); + ERR("get_logon_sid failed\n"); return 1; }
- result = GetUserNameExW(NameSamCompatible, buf, &size); - if (result) + if (!ConvertSidToStringSidW(sid, &sid_string)) { - output_write(buf, size); - output_write(L"\r\n", 2); + ERR("ConvertSidToStringSidW failed, error %ld\n", GetLastError()); + return 1; + } + + output_write(sid_string, -1); + output_write(L"\n", 1); + + free(sid); + LocalFree(sid_string); + + return 0; +} + +static int user(void) +{ + PSID sid; + WCHAR *name; + WCHAR *sid_string; + ULONG i; + + name = get_user_name(NameSamCompatible); + if (!name) + { + ERR("get_user_name failed\n"); + return 1; + } + + sid = get_process_sid(); + if (!sid) + { + ERR("get_process_sid failed\n"); + return 1; } - else - WINE_ERR("GetUserNameExW failed, error %ld\n", GetLastError());
- HeapFree(GetProcessHeap(), 0, buf); + if (!ConvertSidToStringSidW(sid, &sid_string)) + { + ERR("ConvertSidToStringSidW failed, error %ld\n", GetLastError()); + return 1; + } + + output_write(L"\nUSER INFORMATION\n----------------\n\n", -1); + output_write(L"User Name", -1); + for (i = 0; i <= max(wcslen(name), wcslen(L"User Name")) - wcslen(L"User Name"); i++) + output_write(L" ", 1); + output_write(L"SID\n", -1); + + for (i = 0; i < wcslen(name); i++) + output_write(L"=", 1); + output_write(L" ", 1); + for (i = 0; i < wcslen(sid_string); i++) + output_write(L"=", 1); + output_write(L"\n", 1); + + output_write(name, -1); + output_write(L" ", 1); + output_write(sid_string, -1); + output_write(L"\n", 1); + + free(name); + free(sid); + LocalFree(sid_string); + return 0; } + +int __cdecl wmain(int argc, WCHAR *argv[]) +{ + if (argv[1] == NULL) + { + + return simple(NameSamCompatible); + } + else + { + wcslwr(argv[1]); + + if (!wcscmp(argv[1], L"/upn")) + { + /* Not implemented as of now, therefore fails */ + return simple(NameUserPrincipal); + } + else if (!wcscmp(argv[1], L"/fqdn")) + { + /* Not implemented as of now, therefore fails */ + return simple(NameFullyQualifiedDN); + } + else if (!wcscmp(argv[1], L"/logonid")) + { + return logon_id(); + } + else if (!wcscmp(argv[1], L"/user")) + { + return user(); + } + else + { + FIXME("stub\n"); + return 0; + } + } +}
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=135823
Your paranoid android.
=== debian11b (64 bit WoW report) ===
wldap32: parse.c:411: Test failed: ldap_connect failed 0x51
This merge request was approved by Hans Leidekker.