// miniRunAs - A minimalist "run as" for Windows (a runas.exe alternative) // // Home page: www.source-code.biz/snippets/c/1.htm // License: GNU/LGPL (www.gnu.org/licenses/lgpl.html) // Copyright 2008 Christian d'Heureuse, Inventec Informatik AG, Switzerland. // This software is provided "as is" without warranty of any kind. // // Version history: // 2008-03-09 Christian d'Heureuse (chdh@inventec.ch) // Module created. // 2011-07-05 Christian d'Heureuse (chdh@inventec.ch) // lpDomain parameter of CreateProcessWithLogonW changed from L"." to NULL. #define UNICODE #define _WIN32_WINNT 0x0500 // Win2K and later #include #include static const char* programVersion = "2008-03-09"; static wchar_t user[64]; static wchar_t password[64]; static wchar_t commandLine[1024]; static void displayHelp() { printf ("\n"); printf ("miniRunAs - A minimalist \"run as\"\n"); printf ("\n"); printf ("Usage: miniRunAs \n"); printf ("Example: miniRunAs administrator sesame ping localhost\n"); printf ("Author: Christian d'Heureuse, www.source-code.biz, chdh@inventec.ch\n"); printf ("License: GNU/LGPL (www.gnu.org/licenses/lgpl.html)\n"); printf ("Version: %s\n", programVersion); } static void displayWin32ApiError (const char* routineName) { DWORD errorCode = GetLastError(); wchar_t* msg = NULL; int i = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, 0, (LPWSTR)&msg, 0, NULL); if (i == 0) { fprintf (stderr, "FormatMessage failed for error code %i.\n", errorCode); return; } fwprintf (stderr, L"Error code %i returned from %S.\n%s\n", errorCode, routineName, msg); LocalFree (msg); } static const wchar_t* skipBlanks (const wchar_t* s) { while (*s == L' ') s++; return s; } static const wchar_t* skipNonBlanks (const wchar_t* s) { while (*s != 0 && *s != L' ') s++; return s; } static const wchar_t* skipPastChar (const wchar_t* s, wchar_t c) { while (*s != 0) { if (*s == c) {s++; break; } s++; } return s; } static const wchar_t* parseNextWord (const wchar_t* s, wchar_t* wBuf, int wBufSize) { const wchar_t* s1 = skipBlanks(s); const wchar_t* s2 = skipNonBlanks(s1); wcsncpy_s (wBuf, wBufSize, s1, s2-s1); return s2; } static bool parseCommandLineParms() { const wchar_t* s = GetCommandLine(); s = skipBlanks(s); if (*s == L'"') s = skipPastChar(s+1, L'"'); // if the commandline starts with a quote, we have to skip past the next quote else s = skipNonBlanks(s); // otherwise the program path does not contain blanks and we skip to the next blank s = skipBlanks(s); if (*s == 0) { // no command-line parameters displayHelp(); return false; } s = parseNextWord(s, user, sizeof(user)/2); s = parseNextWord(s, password, sizeof(password)/2); s = skipBlanks(s); wcscpy_s (commandLine, s); if (commandLine[0] == 0) { fprintf (stderr, "Missing command-line arguments.\n"); return false; } return true; } int main() { if (!parseCommandLineParms()) return 9; STARTUPINFOW si; memset (&si, 0, sizeof(si)); si.cb = sizeof(si); PROCESS_INFORMATION pi; BOOL ok = CreateProcessWithLogonW ( user, NULL, // change to L"." to use local account database only password, LOGON_WITH_PROFILE, NULL, commandLine, 0, NULL, NULL, &si, &pi); if (ok == 0) { displayWin32ApiError ("CreateProcessWithLogonW"); return 9; } return 0; }