ReactOS 0.4.16-dev-2613-g9533ad7
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 MAX_PASSWORD_LENGTH 64
24
25static
26VOID
28{
29 int i;
30 for (i = IDS_USAGE01; i <= IDS_USAGE_MAX; i++)
32}
33
34
35static
36VOID
38 _In_ PWSTR pInput,
40{
41 DWORD dwOldMode;
42 DWORD dwRead = 0;
44 PWSTR p;
45 PCHAR pBuf;
46
47 pBuf = (PCHAR)HeapAlloc(GetProcessHeap(), 0, dwLength - 1);
48 ZeroMemory(pInput, dwLength * sizeof(WCHAR));
50 GetConsoleMode(hFile, &dwOldMode);
51
52 SetConsoleMode(hFile, ENABLE_LINE_INPUT /*| ENABLE_ECHO_INPUT*/);
53
54 ReadFile(hFile, (PVOID)pBuf, dwLength - 1, &dwRead, NULL);
55
56 MultiByteToWideChar(GetConsoleCP(), 0, pBuf, dwRead, pInput, dwLength - 1);
57 HeapFree(GetProcessHeap(), 0, pBuf);
58
59 for (p = pInput; *p; p++)
60 {
61 if (*p == L'\x0d')
62 {
63 *p = UNICODE_NULL;
64 break;
65 }
66 }
67
68 SetConsoleMode(hFile, dwOldMode);
69}
70
71
72int
74 int argc,
75 LPCWSTR argv[])
76{
77 LPCWSTR pszArg;
78 int i, result = 0;
79 BOOL bProfile = FALSE, bNoProfile = FALSE;
80 BOOL bEnv = FALSE, bNetOnly = FALSE;
81 PWSTR pszUserName = NULL;
82 PWSTR pszDomain = NULL;
83 PWSTR pszCommandLine = NULL;
84 PWSTR pszPassword = NULL;
85 PWSTR pszCurrentDirectory = NULL;
87 PWSTR ptr;
88 STARTUPINFOW StartupInfo;
89 PROCESS_INFORMATION ProcessInfo;
90 DWORD dwLogonFlags = LOGON_WITH_PROFILE;
91 DWORD dwCreateFlags = 0;
92 BOOL rc;
93
94 /* Initialize the Console Standard Streams */
96
97 if (argc == 1)
98 {
99 Usage();
100 return 0;
101 }
102
103 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
104 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
105
106 for (i = 1; i < argc; i++)
107 {
108 pszArg = argv[i];
109 if (*pszArg == L'-' || *pszArg == L'/')
110 {
111 pszArg++;
112 if (wcscmp(pszArg, L"?") == 0)
113 {
114 Usage();
115 result = 0;
116 goto done;
117 }
118 else if (_wcsicmp(pszArg, L"profile") == 0)
119 {
120 bProfile = TRUE;
121 }
122 else if (_wcsicmp(pszArg, L"netonly") == 0)
123 {
124 bNetOnly = TRUE;
125 }
126 else if (_wcsicmp(pszArg, L"noprofile") == 0)
127 {
128 bNoProfile = TRUE;
129 }
130 else if (_wcsicmp(pszArg, L"env") == 0)
131 {
132 bEnv = TRUE;
133 }
134 else if (_wcsnicmp(pszArg, L"user:", 5) == 0)
135 {
136 pszArg += 5;
137 ptr = wcschr(pszArg, L'@');
138 if (ptr != NULL)
139 {
140 /* User@Domain */
141 pszUserName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((ptr - pszArg) + 1) * sizeof(WCHAR));
142 if (pszUserName == NULL)
143 {
145 result = -1;
146 goto done;
147 }
148
149 wcsncpy(pszUserName, pszArg, (ptr - pszArg));
150
151 ptr++;
152 pszDomain = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(ptr) + 1) * sizeof(WCHAR));
153 if (pszDomain == NULL)
154 {
156 result = -1;
157 goto done;
158 }
159
160 wcscpy(pszDomain, ptr);
161 }
162 else
163 {
164 ptr = wcschr(pszArg, L'\\');
165 if (ptr != NULL)
166 {
167 /* Domain\User */
168 pszUserName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(ptr + 1) + 1)* sizeof(WCHAR));
169 if (pszUserName == NULL)
170 {
172 result = -1;
173 goto done;
174 }
175
176 wcscpy(pszUserName, (ptr + 1));
177
178 pszDomain = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((ptr - pszArg) + 1) * sizeof(WCHAR));
179 if (pszDomain == NULL)
180 {
182 result = -1;
183 goto done;
184 }
185
186 wcsncpy(pszDomain, pszArg, (ptr - pszArg));
187 }
188 else
189 {
190 /* User */
191 pszUserName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(pszArg) + 1) * sizeof(WCHAR));
192 if (pszUserName == NULL)
193 {
195 result = -1;
196 goto done;
197 }
198
199 wcscpy(pszUserName, pszArg);
200 }
201 }
202 }
203 else
204 {
205 Usage();
206 result = -1;
207 goto done;
208 }
209 }
210 else
211 {
212 if (pszCommandLine == NULL)
213 {
214 pszCommandLine = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(pszArg) + 1) * sizeof(WCHAR));
215 if (pszCommandLine == NULL)
216 {
218 result = -1;
219 goto done;
220 }
221
222 wcscpy(pszCommandLine, pszArg);
223 break;
224 }
225 }
226 }
227
228 /* Check for incompatible options */
229 if ((bProfile && bNoProfile) ||
230 (bProfile && bNetOnly))
231 {
232 Usage();
233 result = -1;
234 goto done;
235 }
236
237 /* Check for existing command line and user name */
238 if (pszCommandLine == NULL || pszUserName == NULL)
239 {
240 Usage();
241 result = -1;
242 goto done;
243 }
244
245 if (bProfile)
246 dwLogonFlags |= LOGON_WITH_PROFILE;
247
248 if (bNoProfile)
249 dwLogonFlags &= ~LOGON_WITH_PROFILE;
250
251 if (bNetOnly)
252 {
253 dwLogonFlags |= LOGON_NETCREDENTIALS_ONLY;
254 dwLogonFlags &= ~LOGON_WITH_PROFILE;
255 }
256
257 if (pszDomain == NULL)
258 {
260 pszDomain = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength * sizeof(WCHAR));
261 if (pszDomain == NULL)
262 {
264 result = -1;
265 goto done;
266 }
267
268 GetComputerNameW(pszDomain, &dwLength);
269 }
270
271 if (bEnv)
272 {
274 pszCurrentDirectory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (MAX_PATH + 1) * sizeof(WCHAR));
275 if (pszCurrentDirectory == NULL)
276 {
278 result = -1;
279 goto done;
280 }
281
282 GetCurrentDirectory(MAX_PATH + 1, pszCurrentDirectory);
283 dwCreateFlags |= CREATE_UNICODE_ENVIRONMENT;
284 }
285
286 pszPassword = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (MAX_PASSWORD_LENGTH + 1) * sizeof(WCHAR));
287 if (pszPassword == NULL)
288 {
290 result = -1;
291 goto done;
292 }
293
294 /* Query the password */
295 ConResPrintf(StdOut, IDS_PASSWORD, pszDomain, pszUserName);
296 ConInString(pszPassword, MAX_PASSWORD_LENGTH + 1);
297 ConPuts(StdOut, L"\n");
298
299 ConResPrintf(StdOut, IDS_START, pszCommandLine, pszDomain, pszUserName);
300
301 rc = CreateProcessWithLogonW(pszUserName,
302 pszDomain,
303 pszPassword,
304 dwLogonFlags,
305 NULL,
306 pszCommandLine,
307 dwCreateFlags,
309 pszCurrentDirectory,
310 &StartupInfo,
311 &ProcessInfo);
312 if (rc == FALSE)
313 {
314 ConResPrintf(StdOut, IDS_RUN_ERROR, pszCommandLine);
315 ConPrintf(StdOut, L"%lu\n", GetLastError());
316 }
317
318done:
319 if (ProcessInfo.hThread)
320 CloseHandle(ProcessInfo.hThread);
321
322 if (ProcessInfo.hProcess)
323 CloseHandle(ProcessInfo.hProcess);
324
325 if (pszPassword)
326 HeapFree(GetProcessHeap(), 0, pszPassword);
327
328 /* NOTE: Do NOT free pszEnvironment */
329
330 if (pszCurrentDirectory)
331 HeapFree(GetProcessHeap(), 0, pszCurrentDirectory);
332
333 if (pszCommandLine)
334 HeapFree(GetProcessHeap(), 0, pszCommandLine);
335
336 if (pszUserName)
337 HeapFree(GetProcessHeap(), 0, pszUserName);
338
339 if (pszDomain)
340 HeapFree(GetProcessHeap(), 0, pszDomain);
341
342 return result;
343}
#define IDS_USAGE_MAX
Definition: resource.h:23
#define IDS_RUN_ERROR
Definition: resource.h:26
#define IDS_PASSWORD
Definition: resource.h:28
#define IDS_START
Definition: resource.h:25
#define IDS_USAGE01
Definition: resource.h:3
#define IDS_INTERNAL_ERROR
Definition: resource.h:27
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:203
BOOL WINAPI GetComputerNameW(LPWSTR lpBuffer, LPDWORD lpnSize)
Definition: compname.c:446
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: conutils_noros.h:8
#define ConInitStdStreams()
Definition: conutils_noros.h:5
void ConPrintf(FILE *fp, LPCWSTR psz,...)
#define StdOut
Definition: conutils_noros.h:6
void ConResPrintf(FILE *fp, UINT nID,...)
void ConResPuts(FILE *fp, UINT nID)
#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:3728
#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
static DWORD DWORD * dwLength
Definition: fusion.c:86
BOOL WINAPI GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode)
Definition: console.c:1571
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1608
UINT WINAPI DECLSPEC_HOTPATCH GetConsoleCP(void)
Definition: console.c:821
LPWSTR WINAPI DECLSPEC_HOTPATCH GetEnvironmentStringsW(void)
Definition: process.c:1538
MonoAssembly int argc
Definition: metahost.c:107
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:159
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:195
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
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
#define ZeroMemory
Definition: minwinbase.h:31
#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
_In_ HANDLE hFile
Definition: mswsock.h:90
#define _In_
Definition: no_sal2.h:158
#define UNICODE_NULL
short WCHAR
Definition: pedump.c:58
int wmain()
#define MAX_PASSWORD_LENGTH
Definition: runas.c:23
static VOID ConInString(_In_ PWSTR pInput, _In_ DWORD dwLength)
Definition: runas.c:37
wcsncpy
wcscpy
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * LPCWSTR
Definition: typedefs.h:57
char * PCHAR
Definition: typedefs.h:51
#define LOGON_WITH_PROFILE
Definition: winbase.h:598
#define STD_INPUT_HANDLE
Definition: winbase.h:291
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CREATE_UNICODE_ENVIRONMENT
Definition: winbase.h:190
#define LOGON_NETCREDENTIALS_ONLY
Definition: winbase.h:599
#define GetCurrentDirectory
Definition: winbase.h:3554
#define MAX_COMPUTERNAME_LENGTH
Definition: winbase.h:267
#define ENABLE_LINE_INPUT
Definition: wincon.h:108