ReactOS 0.4.15-dev-5669-g09dde2c
runas.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS runas utility
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/runas/runas.c
5 * COPYRIGHT: Copyright 2022 Eric Kohl <eric.kohl@reactos.org>
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <limits.h>
11#include <stdarg.h>
12
13#define WIN32_NO_STATUS
14#include <windef.h>
15#include <winbase.h>
16#include <winnls.h>
17#include <wincon.h>
18#include <winsvc.h>
19#include <conutils.h>
20
21#include "resource.h"
22
23#define NDEBUG
24#include <debug.h>
25
26#define MAX_PASSWORD_LENGTH 64
27
28static
29VOID
31{
32 int i;
33 for (i = IDS_USAGE01; i <= IDS_USAGE_MAX; i++)
35}
36
37
38static
39VOID
41 _In_ PWSTR pInput,
43{
44 DWORD dwOldMode;
45 DWORD dwRead = 0;
47 PWSTR p;
48 PCHAR pBuf;
49
50 pBuf = (PCHAR)HeapAlloc(GetProcessHeap(), 0, dwLength - 1);
51 ZeroMemory(pInput, dwLength * sizeof(WCHAR));
53 GetConsoleMode(hFile, &dwOldMode);
54
55 SetConsoleMode(hFile, ENABLE_LINE_INPUT /*| ENABLE_ECHO_INPUT*/);
56
57 ReadFile(hFile, (PVOID)pBuf, dwLength - 1, &dwRead, NULL);
58
59 MultiByteToWideChar(GetConsoleCP(), 0, pBuf, dwRead, pInput, dwLength - 1);
60 HeapFree(GetProcessHeap(), 0, pBuf);
61
62 for (p = pInput; *p; p++)
63 {
64 if (*p == L'\x0d')
65 {
66 *p = UNICODE_NULL;
67 break;
68 }
69 }
70
71 SetConsoleMode(hFile, dwOldMode);
72}
73
74
75int
77 int argc,
78 LPCWSTR argv[])
79{
80 LPCWSTR pszArg;
81 int i, result = 0;
82 BOOL bProfile = FALSE, bNoProfile = FALSE;
83 BOOL bEnv = FALSE, bNetOnly = FALSE;
84 PWSTR pszUserName = NULL;
85 PWSTR pszDomain = NULL;
86 PWSTR pszCommandLine = NULL;
87 PWSTR pszPassword = NULL;
88 PWSTR pszCurrentDirectory = NULL;
90 PWSTR ptr;
91 STARTUPINFOW StartupInfo;
92 PROCESS_INFORMATION ProcessInfo;
93 DWORD dwLogonFlags = LOGON_WITH_PROFILE;
94 DWORD dwCreateFlags = 0;
95 BOOL rc;
96
97 /* Initialize the Console Standard Streams */
99
100 if (argc == 1)
101 {
102 Usage();
103 return 0;
104 }
105
106 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
107 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
108
109 for (i = 1; i < argc; i++)
110 {
111 pszArg = argv[i];
112 if (*pszArg == L'-' || *pszArg == L'/')
113 {
114 pszArg++;
115 if (wcscmp(pszArg, L"?") == 0)
116 {
117 Usage();
118 result = 0;
119 goto done;
120 }
121 else if (wcsicmp(pszArg, L"profile") == 0)
122 {
123 bProfile = TRUE;
124 }
125 else if (wcsicmp(pszArg, L"netonly") == 0)
126 {
127 bNetOnly = TRUE;
128 }
129 else if (wcsicmp(pszArg, L"noprofile") == 0)
130 {
131 bNoProfile = TRUE;
132 }
133 else if (wcsicmp(pszArg, L"env") == 0)
134 {
135 bEnv = TRUE;
136 }
137 else if (_wcsnicmp(pszArg, L"user:", 5) == 0)
138 {
139 pszArg += 5;
140 ptr = wcschr(pszArg, L'@');
141 if (ptr != NULL)
142 {
143 /* User@Domain */
144 pszUserName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((ptr - pszArg) + 1) * sizeof(WCHAR));
145 if (pszUserName == NULL)
146 {
148 result = -1;
149 goto done;
150 }
151
152 wcsncpy(pszUserName, pszArg, (ptr - pszArg));
153
154 ptr++;
155 pszDomain = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(ptr) + 1) * sizeof(WCHAR));
156 if (pszDomain == NULL)
157 {
159 result = -1;
160 goto done;
161 }
162
163 wcscpy(pszDomain, ptr);
164 }
165 else
166 {
167 ptr = wcschr(pszArg, L'\\');
168 if (ptr != NULL)
169 {
170 /* Domain\User */
171 pszUserName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(ptr + 1) + 1)* sizeof(WCHAR));
172 if (pszUserName == NULL)
173 {
175 result = -1;
176 goto done;
177 }
178
179 wcscpy(pszUserName, (ptr + 1));
180
181 pszDomain = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((ptr - pszArg) + 1) * sizeof(WCHAR));
182 if (pszDomain == NULL)
183 {
185 result = -1;
186 goto done;
187 }
188
189 wcsncpy(pszDomain, pszArg, (ptr - pszArg));
190 }
191 else
192 {
193 /* User */
194 pszUserName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(pszArg) + 1) * sizeof(WCHAR));
195 if (pszUserName == NULL)
196 {
198 result = -1;
199 goto done;
200 }
201
202 wcscpy(pszUserName, pszArg);
203 }
204 }
205 }
206 else
207 {
208 Usage();
209 result = -1;
210 goto done;
211 }
212 }
213 else
214 {
215 if (pszCommandLine == NULL)
216 {
217 pszCommandLine = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(pszArg) + 1) * sizeof(WCHAR));
218 if (pszCommandLine == NULL)
219 {
221 result = -1;
222 goto done;
223 }
224
225 wcscpy(pszCommandLine, pszArg);
226 break;
227 }
228 }
229 }
230
231 /* Check for incompatible options */
232 if ((bProfile && bNoProfile) ||
233 (bProfile && bNetOnly))
234 {
235 Usage();
236 result = -1;
237 goto done;
238 }
239
240 /* Check for existing command line and user name */
241 if (pszCommandLine == NULL || pszUserName == NULL)
242 {
243 Usage();
244 result = -1;
245 goto done;
246 }
247
248 if (bProfile)
249 dwLogonFlags |= LOGON_WITH_PROFILE;
250
251 if (bNoProfile)
252 dwLogonFlags &= ~LOGON_WITH_PROFILE;
253
254 if (bNetOnly)
255 {
256 dwLogonFlags |= LOGON_NETCREDENTIALS_ONLY;
257 dwLogonFlags &= ~LOGON_WITH_PROFILE;
258 }
259
260 DPRINT("User: %S\n", pszUserName);
261 DPRINT("Domain: %S\n", pszDomain);
262 DPRINT("CommandLine: %S\n", pszCommandLine);
263
264 if (pszDomain == NULL)
265 {
267 pszDomain = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength * sizeof(WCHAR));
268 if (pszDomain == NULL)
269 {
271 result = -1;
272 goto done;
273 }
274
275 GetComputerNameW(pszDomain, &dwLength);
276 }
277
278 if (bEnv)
279 {
281 pszCurrentDirectory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (MAX_PATH + 1) * sizeof(WCHAR));
282 if (pszCurrentDirectory == NULL)
283 {
285 result = -1;
286 goto done;
287 }
288
289 GetCurrentDirectory(MAX_PATH + 1, pszCurrentDirectory);
290 dwCreateFlags |= CREATE_UNICODE_ENVIRONMENT;
291 }
292
293 pszPassword = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (MAX_PASSWORD_LENGTH + 1) * sizeof(WCHAR));
294 if (pszPassword == NULL)
295 {
297 result = -1;
298 goto done;
299 }
300
301 /* Query the password */
302 ConResPrintf(StdOut, IDS_PASSWORD, pszDomain, pszUserName);
303 ConInString(pszPassword, MAX_PASSWORD_LENGTH + 1);
304 ConPuts(StdOut, L"\n");
305
306 ConResPrintf(StdOut, IDS_START, pszCommandLine, pszDomain, pszUserName);
307
308 rc = CreateProcessWithLogonW(pszUserName,
309 pszDomain,
310 pszPassword,
311 dwLogonFlags,
312 NULL,
313 pszCommandLine,
314 dwCreateFlags,
316 pszCurrentDirectory,
317 &StartupInfo,
318 &ProcessInfo);
319 if (rc == FALSE)
320 {
321 ConResPrintf(StdOut, IDS_RUN_ERROR, pszCommandLine);
322 ConPrintf(StdOut, L"%lu\n", GetLastError());
323 }
324
325done:
326 if (ProcessInfo.hThread)
327 CloseHandle(ProcessInfo.hThread);
328
329 if (ProcessInfo.hProcess)
330 CloseHandle(ProcessInfo.hProcess);
331
332 if (pszPassword)
333 HeapFree(GetProcessHeap(), 0, pszPassword);
334
335 /* NOTE: Do NOT free pszEnvironment */
336
337 if (pszCurrentDirectory)
338 HeapFree(GetProcessHeap(), 0, pszCurrentDirectory);
339
340 if (pszCommandLine)
341 HeapFree(GetProcessHeap(), 0, pszCommandLine);
342
343 if (pszUserName)
344 HeapFree(GetProcessHeap(), 0, pszUserName);
345
346 if (pszDomain)
347 HeapFree(GetProcessHeap(), 0, pszDomain);
348
349 return result;
350}
static int argc
Definition: ServiceArgs.c:12
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: fc.c:16
#define ConInitStdStreams()
Definition: fc.c:13
void ConPrintf(FILE *fp, LPCWSTR psz,...)
Definition: fc.c:20
#define StdOut
Definition: fc.c:14
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
void ConResPuts(FILE *fp, UINT nID)
Definition: fc.c:27
#define IDS_USAGE_MAX
Definition: resource.h:21
#define IDS_RUN_ERROR
Definition: resource.h:24
#define IDS_PASSWORD
Definition: resource.h:26
#define IDS_START
Definition: resource.h:23
#define IDS_USAGE01
Definition: resource.h:1
#define IDS_INTERNAL_ERROR
Definition: resource.h:25
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:446
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI CreateProcessWithLogonW(_In_ LPCWSTR lpUsername, _In_opt_ LPCWSTR lpDomain, _In_ LPCWSTR lpPassword, _In_ DWORD dwLogonFlags, _In_opt_ LPCWSTR lpApplicationName, _Inout_opt_ LPWSTR lpCommandLine, _In_ DWORD dwCreationFlags, _In_opt_ LPVOID lpEnvironment, _In_opt_ LPCWSTR lpCurrentDirectory, _In_ LPSTARTUPINFOW lpStartupInfo, _Out_ LPPROCESS_INFORMATION lpProcessInformation)
Definition: security.c:3480
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define MultiByteToWideChar
Definition: compat.h:110
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define wcsicmp
Definition: compat.h:15
static DWORD DWORD * dwLength
Definition: fusion.c:86
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1569
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1606
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(VOID)
Definition: console.c:2391
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLfloat GLfloat p
Definition: glext.h:8902
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum 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 const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Must_inspect_result_ _In_ USAGE _In_ USHORT _In_ USAGE Usage
Definition: hidpi.h:384
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define PCHAR
Definition: match.c:90
LPCWSTR LPCWSTR LPCWSTR pszEnvironment
Definition: env.c:37
static PVOID ptr
Definition: dispmode.c:27
#define argv
Definition: mplay32.c:18
#define _In_
Definition: ms_sal.h:308
_In_ HANDLE hFile
Definition: mswsock.h:90
#define UNICODE_NULL
#define L(x)
Definition: ntvdm.h:50
int wmain()
#define MAX_PASSWORD_LENGTH
Definition: runas.c:26
static VOID ConInString(_In_ PWSTR pInput, _In_ DWORD dwLength)
Definition: runas.c:40
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
#define DPRINT
Definition: sndvol32.h:71
uint16_t * PWSTR
Definition: typedefs.h:56
char * PCHAR
Definition: typedefs.h:51
#define ZeroMemory
Definition: winbase.h:1670
#define LOGON_WITH_PROFILE
Definition: winbase.h:619
#define STD_INPUT_HANDLE
Definition: winbase.h:267
DWORD WINAPI GetLastError(void)
Definition: except.c:1040
#define CREATE_UNICODE_ENVIRONMENT
Definition: winbase.h:186
LPWSTR WINAPI GetEnvironmentStringsW(void)
Definition: environ.c:344
#define LOGON_NETCREDENTIALS_ONLY
Definition: winbase.h:620
#define GetCurrentDirectory
Definition: winbase.h:3676
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:243
#define ENABLE_LINE_INPUT
Definition: wincon.h:79
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185