def ExecAs(scriptPath, asAdministrator, funcName, *args, **kwargs): pipeName = "\\\\.\\pipe\\" + str(GUID.create_new()) Msg("creating named pipe") hPipe = CreateNamedPipe( pipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, None ) if hPipe == INVALID_HANDLE_VALUE: raise Exception("Error in creating Named Pipe") overlapped = OVERLAPPED() overlapped.hEvent = CreateEvent(None, 1, 0, None) try: Msg("calling ConnectNamedPipe") ConnectNamedPipe(hPipe, byref(overlapped)) localPath = dirname(__file__.decode('mbcs')) Msg("starting subprocess") hProcess = RunAs( abspath(join(localPath, "..", "..", "EventGhost.exe")), asAdministrator, "-execfile", GetUncPathOf(join(localPath, "PipedProcessClient.py")), pipeName, str(eg.debugLevel) ) Msg("waiting for subprocess to connect") pHandles = (HANDLE * 2)(overlapped.hEvent, hProcess) ret = WaitForMultipleObjects(2, pHandles, 0, 25000) if ret == WAIT_OBJECT_0: # connect event Msg("got connect event") elif ret == WAIT_OBJECT_0 + 1: raise Exception("Unexpected end of subprocess.") elif ret == WAIT_TIMEOUT: raise Exception("Timeout in waiting for subprocess.") else: raise Exception("Unknown return value") Msg("sending startup message") WritePipeMessage( hPipe, MESSAGE_ARGS, (GetUncPathOf(scriptPath), funcName, args, kwargs) ) chBuf = create_string_buffer(BUFSIZE) cbRead = DWORD(0) while True: fSuccess = ReadFile(hPipe, chBuf, BUFSIZE, byref(cbRead), None) if ((fSuccess == 1) or (cbRead.value != 0)): code, data = loads(chBuf.value) if code == MESSAGE_STDERR: sys.stderr.write(data) elif code == MESSAGE_STDOUT: sys.stdout.write(data) elif code == MESSAGE_RESULT: result = data break elif code == MESSAGE_EXCEPTION: break else: raise Exception("Unknown message type %r" % code) FlushFileBuffers(hPipe) DisconnectNamedPipe(hPipe) finally: CloseHandle(hPipe) CloseHandle(overlapped.hEvent) if code == MESSAGE_EXCEPTION: raise Exception("Child process raised an exception\n" + data) return result
def ExecAsAdministrator(scriptPath, funcName, *args, **kwargs): """ Execute some Python code in a process with elevated privileges. This call will only return, after the subprocess has terminated. The sys.stdout and sys.stderr streams of the subprocess will be directed to the calling process through a named pipe. All parameters for the function to call and its return value must be picklable. :param scriptPath: Path to the Python file to load. :param funcName: Name of the function to call inside the Python file :param args: Positional parameters for the function :param kwargs: Keyword parameters for the function :returns: The return value of the function """ Msg("creating named pipe") hPipe = CreateNamedPipe( szPipename, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, 0, None ) if (hPipe == INVALID_HANDLE_VALUE): raise Exception("Error in creating Named Pipe") overlapped = OVERLAPPED() overlapped.hEvent = CreateEvent(None, 1, 0, None) try: Msg("calling ConnectNamedPipe") ConnectNamedPipe(hPipe, byref(overlapped)) executable = abspath(join( dirname(__file__.decode(sys.getfilesystemencoding())), "..", "..", "EventGhost.exe" )) Msg("starting subprocess") hProcess = RunAsAdministrator( executable, "-execscript", __file__.decode(sys.getfilesystemencoding()), "-client", szPipename, ) Msg("waiting for subprocess to connect") pHandles = (HANDLE * 2)(overlapped.hEvent, hProcess) ret = WaitForMultipleObjects(2, pHandles, 0, 20000) if ret == WAIT_OBJECT_0: # connect event Msg("got connect event") elif ret == WAIT_OBJECT_0 + 1: raise Exception("Unexpected end of subprocess.") elif ret == WAIT_TIMEOUT: raise Exception("Timeout in waiting for subprocess.") else: raise Exception("Unknown return value") # if fConnected == 0 and GetLastError() == ERROR_PIPE_CONNECTED: # fConnected = 1 # if fConnected != 1: # raise Exception("Could not connect to the Named Pipe") # Msg("sending startup message") WritePipeMessage( hPipe, MESSAGE_ARGS, (scriptPath, funcName, args, kwargs) ) chBuf = create_string_buffer(BUFSIZE) cbRead = DWORD(0) while True: fSuccess = ReadFile(hPipe, chBuf, BUFSIZE, byref(cbRead), None) if ((fSuccess == 1) or (cbRead.value != 0)): code, data = loads(chBuf.value) if code == MESSAGE_STDERR: sys.stderr.write(data) elif code == MESSAGE_STDOUT: sys.stdout.write(data) elif code == MESSAGE_RESULT: result = data break elif code == MESSAGE_EXCEPTION: break else: raise Exception("Unknown message type %r" % code) FlushFileBuffers(hPipe) DisconnectNamedPipe(hPipe) finally: CloseHandle(hPipe) CloseHandle(overlapped.hEvent) if code == MESSAGE_EXCEPTION: raise Exception("Child process raised an exception\n" + data) return result