def Main(pipeName, debugLevel): if debugLevel: def Debug(msg): sys.stdout.write(msg + "\n") else: def Debug(msg): pass if not WaitNamedPipe(pipeName, 5000): raise WinError() hPipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, 0, None) if hPipe == INVALID_HANDLE_VALUE: raise WinError() try: # The pipe connected; change to message-read mode. dwMode = DWORD(PIPE_READMODE_MESSAGE) if not SetNamedPipeHandleState(hPipe, byref(dwMode), None, None): raise WinError() sys.stderr = PipeStream(hPipe, MESSAGE_STDERR) sys.stdout = PipeStream(hPipe, MESSAGE_STDOUT) Debug("reading startup message") code, (scriptPath, funcName, args, kwargs) = ReadPipeMessage(hPipe) Debug("got startup message:\n" " path: %r\n" " funcName: %r\n" " args: %r\n" " kwargs: %r" % (scriptPath, funcName, args, kwargs)) if code != MESSAGE_ARGS: raise Exception("Unexpected message type") try: moduleName = splitext(basename(scriptPath))[0] try: moduleInfo = imp.find_module(moduleName, [dirname(scriptPath)]) except ImportError: import zipimport for entry in sys.path: if entry.endswith('.zip'): zipImporter = zipimport.zipimporter(entry) try: module = zipImporter.load_module(moduleName) except zipimport.ZipImportError: continue else: module = imp.load_module(moduleName, *moduleInfo) func = getattr(module, funcName) result = func(*args, **kwargs) Debug("result: %r" % result) except: WritePipeMessage(hPipe, MESSAGE_EXCEPTION, FormatException(sys.exc_info())) else: WritePipeMessage(hPipe, MESSAGE_RESULT, result) finally: CloseHandle(hPipe)
def PyGetWindowThreadProcessId(hWnd): """ Retrieves the identifier of the thread and process that created the specified window. int threadId, int processId = GetWindowThreadProcessId(hWnd) """ dwProcessId = DWORD() threadId = GetWindowThreadProcessId(hWnd, byref(dwProcessId)) return threadId, dwProcessId.value
def GetStatus(self): dwBytesNeeded = DWORD() result = QueryServiceStatusEx( self.schService, # handle to service SC_STATUS_PROCESS_INFO, # information level cast(byref(self.ssStatus), LPBYTE), # address of structure sizeof(self.ssStatus), # size of structure byref(dwBytesNeeded) # size needed if buffer is too small ) if not result: raise WinError() return self.ssStatus
def PySendMessageTimeout(hWnd, msg, wParam=0, lParam=0, flags=SMTO_BLOCK | SMTO_ABORTIFHUNG, timeout=2000): resultData = DWORD() res = SendMessageTimeout(hWnd, msg, wParam, lParam, flags, timeout, byref(resultData)) if not res: raise WinError() return resultData.value
def WritePipeMessage(hPipe, code, data): message = dumps((code, data)) cbWritten = DWORD(0) fSuccess = WriteFile( hPipe, message, len(message), byref(cbWritten), None ) if (not fSuccess) or (len(message) != cbWritten.value): raise Exception("WritePipeMessage failed")
def GetUncPathOf(filePath): buf = create_string_buffer(1024) dwBufSize = DWORD(1024) err = WNetGetUniversalName(filePath, UNIVERSAL_NAME_INFO_LEVEL, buf, byref(dwBufSize)) if err == 0: return cast(buf, POINTER(UNIVERSAL_NAME_INFO)).contents.lpUniversalName elif err == ERROR_NOT_CONNECTED: pass else: print "GetUncPathOf Error:", err, FormatError(err) return filePath
def GetHwndIcon(hWnd): """ Get a wx.Icon from a window through its hwnd window handle """ hIcon = DWORD() res = SendMessageTimeout(hWnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, byref(hIcon)) if res == 0: hIcon.value = 0 if hIcon.value < 10: hIcon.value = GetClassLong(hWnd, GCL_HICONSM) if hIcon.value == 0: res = SendMessageTimeout(hWnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, byref(hIcon)) if res == 0: hIcon.value = 0 if hIcon.value < 10: hIcon.value = GetClassLong(hWnd, GCL_HICON) if hIcon.value != 0: icon = wx.NullIcon value = hIcon.value # ugly fix for "OverflowError: long int too large to convert to int" if value & 0x80000000: value = -((value ^ 0xffffffff) + 1) icon.SetHandle(value) icon.SetSize((16, 16)) return icon else: return None
def PyEnumProcesses(): size = 1024 pBytesReturned = DWORD() while True: data = (DWORD * size)() dataSize = size * sizeof(DWORD) res = EnumProcesses(data, dataSize, byref(pBytesReturned)) if res == 0: raise WinError() if pBytesReturned.value != dataSize: break size *= 10 return data[:pBytesReturned.value / sizeof(DWORD)]
def GetHwndIcon(hWnd): """ Get a wx.Icon from a window through its hwnd window handle """ hIcon = DWORD() res = SendMessageTimeout( hWnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, byref(hIcon) ) if res == 0: hIcon.value = 0 if hIcon.value < 10: hIcon.value = GetClassLong(hWnd, GCL_HICONSM) if hIcon.value == 0: res = SendMessageTimeout( hWnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, byref(hIcon) ) if res == 0: hIcon.value = 0 if hIcon.value < 10: hIcon.value = GetClassLong(hWnd, GCL_HICON) if hIcon.value != 0: icon = wx.NullIcon value = hIcon.value # ugly fix for "OverflowError: long int too large to convert to int" if value & 0x80000000: value = -((value ^ 0xffffffff) + 1) icon.SetHandle(value) icon.SetSize((16, 16)) return icon else: return None
def ReadPipeMessage(hPipe): data = "" fSuccess = 0 chBuf = create_string_buffer(BUFSIZE) cbRead = DWORD(0) while not fSuccess: # repeat loop if ERROR_MORE_DATA fSuccess = ReadFile(hPipe, chBuf, BUFSIZE, byref(cbRead), None) if fSuccess == 1: data += chBuf.value break elif GetLastError() != ERROR_MORE_DATA: break data += chBuf.value return loads(data)
def GetWindowProcessName(hWnd): dwProcessId = DWORD() GetWindowThreadProcessId(hWnd, byref(dwProcessId)) return GetProcessName(dwProcessId.value)
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 IsAdmin(): """ Find out if the user (the owner of the current process) is a member of the administrators group on the local computer (not on the domain!). """ # First we must open a handle to the access token for this thread. hThread = HANDLE() if not OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, 0, byref(hThread)): err = GetLastError() if err == ERROR_NO_TOKEN: # If the thread does not have an access token, we'll examine the # access token associated with the process. if not OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, byref(hThread)): raise WinError() else: raise WinError(err) # Then we must query the size of the group information associated with # the token. Note that we expect a FALSE result from GetTokenInformation # because we've given it a NULL buffer. On exit cbTokenGroups will tell # the size of the group information. cbTokenGroups = DWORD() if GetTokenInformation(hThread, TokenGroups, None, 0, byref(cbTokenGroups)): raise WinError() # Here we verify that GetTokenInformation failed for lack of a large # enough buffer. err = GetLastError() if err != ERROR_INSUFFICIENT_BUFFER: raise WinError(err) # Now we allocate a buffer for the group information. ptg = create_string_buffer(cbTokenGroups.value) # Now we ask for the group information again. # This may fail if an administrator has added this account to an additional # group between our first call to GetTokenInformation and this one. if not GetTokenInformation(hThread, TokenGroups, ptg, cbTokenGroups, byref(cbTokenGroups)): raise WinError() # Now we must create a System Identifier for the Admin group. systemSidAuthority = SID_IDENTIFIER_AUTHORITY() systemSidAuthority.Value[5] = SECURITY_NT_AUTHORITY psidAdmin = PSID() if not AllocateAndInitializeSid( byref(systemSidAuthority), 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, byref(psidAdmin)): raise WinError() # Finally we'll iterate through the list of groups for this access # token looking for a match against the SID we created above. ptg = cast(ptg, POINTER(TOKEN_GROUPS)) groups = cast(ptg.contents.Groups, POINTER(SID_AND_ATTRIBUTES)) isAdmin = False for i in range(ptg.contents.GroupCount): if EqualSid(groups[i].Sid, psidAdmin.value): isAdmin = True break # Before we exit we must explicitly deallocate the SID we created. FreeSid(psidAdmin) return isAdmin
def GetComPorts(availableOnly=True): """ Scans the registry for serial ports and return a list of (port, desc, hwid) tuples. If availableOnly is true only return currently existing ports. """ result = [] stringBuffer = create_unicode_buffer(256) flags = DIGCF_DEVICEINTERFACE if availableOnly: flags |= DIGCF_PRESENT hdi = SetupDiGetClassDevs(byref(GUID_CLASS_COMPORT), None, 0, flags) if hdi == INVALID_HANDLE_VALUE: raise WinError() dwRequiredSize = DWORD() dwIndex = 0 while True: did = SP_DEVICE_INTERFACE_DATA() did.cbSize = sizeof(did) if not SetupDiEnumDeviceInterfaces( hdi, None, byref(GUID_CLASS_COMPORT), dwIndex, byref(did)): err = GetLastError() if err != ERROR_NO_MORE_ITEMS: raise WinError(err) break # get the size if not SetupDiGetDeviceInterfaceDetail(hdi, byref(did), None, 0, byref(dwRequiredSize), None): # Ignore ERROR_INSUFFICIENT_BUFFER err = GetLastError() if err != ERROR_INSUFFICIENT_BUFFER: raise WinError(err) # allocate buffer class _SP_DEVICE_INTERFACE_DETAIL_DATA(Structure): _fields_ = [ ('cbSize', DWORD), ('DevicePath', TCHAR * (dwRequiredSize.value - sizeof(DWORD))), ] idd = _SP_DEVICE_INTERFACE_DETAIL_DATA() idd.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) devinfo = SP_DEVINFO_DATA() devinfo.cbSize = sizeof(devinfo) if not SetupDiGetDeviceInterfaceDetail( hdi, byref(did), cast(byref(idd), PSP_DEVICE_INTERFACE_DETAIL_DATA), dwRequiredSize, None, byref(devinfo)): raise WinError() # hardware ID if not SetupDiGetDeviceRegistryProperty( hdi, byref(devinfo), SPDRP_HARDWAREID, None, cast(stringBuffer, PBYTE), sizeof(stringBuffer) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER err = GetLastError() if err != ERROR_INSUFFICIENT_BUFFER: raise WinError(err) szHardwareID = stringBuffer.value # friendly name if not SetupDiGetDeviceRegistryProperty( hdi, byref(devinfo), SPDRP_FRIENDLYNAME, None, cast(stringBuffer, PBYTE), sizeof(stringBuffer) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER err = GetLastError() if err != ERROR_INSUFFICIENT_BUFFER: raise WinError(err) szFriendlyName = stringBuffer.value portName = re.search(r"\((.*)\)", szFriendlyName).group(1) result.append((portName, szFriendlyName, szHardwareID)) dwIndex += 1 SetupDiDestroyDeviceInfoList(hdi) return result