Module: wine Branch: master Commit: aa3beb88b346cd74568157d5c10a464a6995c7c2 URL: https://gitlab.winehq.org/wine/wine/-/commit/aa3beb88b346cd74568157d5c10a464...
Author: Maxim Karasev mxkrsv@etersoft.ru Date: Mon Jul 24 22:15:34 2023 +0300
whoami: Refactor and add more commands.
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; + } + } +}