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 StopDependentServices(self): # Pass a zero-length buffer to get the required buffer size. dwBytesNeeded = DWORD() dwCount = DWORD() if EnumDependentServices( self.schService, SERVICE_ACTIVE, None, 0, byref(dwBytesNeeded), byref(dwCount) ): # If the Enum call succeeds, then there are no dependent # services, so do nothing. return True if GetLastError() != ERROR_MORE_DATA: return False # Unexpected error # Allocate a buffer for the dependencies. lpDependencies = cast( HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded ), LPENUM_SERVICE_STATUS ) if not lpDependencies: return False for i in range(dwCount): #ess = *(lpDependencies + i) # Open the service. hDepService = OpenService( self.schSCManager, ess.lpServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS ) if not hDepService: return False try: # Send a stop code. if not ControlService( hDepService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS) &ssp ): return False # Wait for the service to stop. while ssStatus.dwCurrentState != SERVICE_STOPPED: Sleep(ssStatus.dwWaitHint) ssStatus = self.GetStatus() if ssStatus.dwCurrentState == SERVICE_STOPPED: break if GetTickCount() - dwStartTime > dwTimeout: return False finally: # Always release the service handle. CloseServiceHandle(hDepService) return True
def BestWindowFromPoint(point): x, y = point foundWindow = WindowFromPoint(POINT(x, y)) hWnds = GetWindowChildsList(GetAncestor(foundWindow, GA_ROOT), True) if not hWnds: return foundWindow foundWindowArea = sys.maxint rect = RECT() clientPoint = POINT() for hWnd in hWnds: GetWindowRect(hWnd, byref(rect)) if ( x >= rect.left and x <= rect.right and y >= rect.top and y <= rect.bottom ): hdc = GetDC(hWnd) clientPoint.x, clientPoint.y = x, y ScreenToClient(hWnd, byref(clientPoint)) if PtVisible(hdc, clientPoint.x, clientPoint.y): area = (rect.right - rect.left) * (rect.bottom - rect.top) if area < foundWindowArea: foundWindow = hWnd foundWindowArea = area ReleaseDC(hWnd, hdc) return foundWindow
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 FormatError(code=None): """ A replacement for ctypes.FormtError, but always returns the string encoded in CP1252 (ANSI Code Page). """ if code is None: code = GetLastError() lpMsgBuf = LPWSTR() numChars = _kernel32.FormatMessageW( ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS ), None, code, 0, byref(lpMsgBuf), 0, None ) if numChars == 0: return "No error message available." #raise Exception("FormatMessage failed on 0x%X with 0x%X" % (code & 0xFFFFFFFF, GetLastError())) message = lpMsgBuf.value.strip() _kernel32.LocalFree(lpMsgBuf) return message.encode("CP1252", 'backslashreplace')
def GetWindowDimensions(hwnd = None): hwnd = GetBestHwnd(hwnd) windowDims = RECT() GetWindowRect(hwnd, byref(windowDims)) width = windowDims.right - windowDims.left height = windowDims.bottom - windowDims.top return wx.Rect(windowDims.left, windowDims.top, width, height)
def GetWindowDimensions(hwnd=None): hwnd = GetBestHwnd(hwnd) windowDims = RECT() GetWindowRect(hwnd, byref(windowDims)) width = windowDims.right - windowDims.left height = windowDims.bottom - windowDims.top return wx.Rect(windowDims.left, windowDims.top, width, height)
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 Client(): while 1: hPipe = CreateFile( szPipename, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None ) if hPipe != INVALID_HANDLE_VALUE: break else: print "Invalid Handle Value" if GetLastError() != ERROR_PIPE_BUSY: print "Could not open pipe" return elif WaitNamedPipe(szPipename, 20000) == 0: print "Could not open pipe" return try: dwMode = DWORD(PIPE_READMODE_MESSAGE) fSuccess = SetNamedPipeHandleState(hPipe, byref(dwMode), None, None) if not fSuccess: raise Exception("SetNamedPipeHandleState failed") sys.stderr = PipeStream(hPipe, MESSAGE_STDERR) sys.stdout = PipeStream(hPipe, MESSAGE_STDOUT) Msg("reading startup message") code, (scriptPath, funcName, args, kwargs) = ReadPipeMessage(hPipe) Msg( "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] moduleInfo = imp.find_module(moduleName, [dirname(scriptPath)]) module = imp.load_module(moduleName, *moduleInfo) func = getattr(module, funcName) result = func(*args, **kwargs) 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 SetDescription(self, description): self.GetServiceHandle() serviceDescription = SERVICE_DESCRIPTION() serviceDescription.lpDescription = description if not ChangeServiceConfig2( self.schService, # handle to service SERVICE_CONFIG_DESCRIPTION, # change: description byref(serviceDescription) # new description ): raise WinError()
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 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 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("Write File failed")
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 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 RunAs(filePath, asAdministrator, *args): sei = SHELLEXECUTEINFO() sei.cbSize = sizeof(SHELLEXECUTEINFO) sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS if asAdministrator: sei.lpVerb = u"runas" else: sei.lpVerb = u"" sei.lpFile = GetUncPathOf(filePath) sei.lpParameters = " ".join(['"%s"' % arg.replace('"', '""') for arg in args]) sei.nShow = SW_SHOWNORMAL if not ctypes.windll.shell32.ShellExecuteExW(byref(sei)): err = GetLastError() raise WindowsError(err, "ShellExecuteEx: %s" % FormatError(err)) return sei.hProcess
def RunAs(filePath, asAdministrator, *args): sei = SHELLEXECUTEINFO() sei.cbSize = sizeof(SHELLEXECUTEINFO) sei.fMask = (SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS) if asAdministrator: sei.lpVerb = u"runas" else: sei.lpVerb = u"" sei.lpFile = GetUncPathOf(filePath) sei.lpParameters = " ".join( ['"%s"' % arg.replace('"', '""') for arg in args]) sei.nShow = SW_SHOWNORMAL if not ctypes.windll.shell32.ShellExecuteExW(byref(sei)): err = GetLastError() raise WindowsError(err, "ShellExecuteEx: %s" % FormatError(err)) return sei.hProcess
def HighlightWindow(hWnd): """ Draws an inverted rectangle around a window to inform the user about the currently selected window. """ UpdateWindow(hWnd) # Retrieve location of window on-screen. rect = RECT() GetWindowRect(hWnd, byref(rect)) # Get a device context that allows us to write anywhere within the window. hdc = GetWindowDC(hWnd) # Save the original device context attributes. SaveDC(hdc) # To guarantee that the frame will be visible, tell Windows to draw the # frame using the inverse screen color. SetROP2(hdc, R2_NOT) # Create a pen that is three times the width of a nonsizeable border. The # color will not be used to draw the frame, so its value could be # anything. PS_INSIDEFRAME tells windows that the entire frame should be # enclosed within the window. hpen = CreatePen(PS_INSIDEFRAME, _H_BORDERWIDTH, _H_BORDERCOLOUR) SelectObject(hdc, hpen) # We must select a NULL brush so that the contents of the window will not # be overwritten. SelectObject(hdc, GetStockObject(NULL_BRUSH)) # Draw the frame. Because the device context is relative to the window, # the top-left corner is (0, 0) and the lower right corner is (width of # window, height of window). Rectangle(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top) # Restore the original attributes and release the device context. RestoreDC(hdc, -1) ReleaseDC(hWnd, hdc) # We can destroy the pen only AFTER we have restored the DC because the DC # must have valid objects selected into it at all times. DeleteObject(hpen)
def Stop(self): """ Stops the service. """ self.GetServiceHandle() # Make sure the service is not already stopped. ssStatus = self.GetStatus() if ssStatus.dwCurrentState == SERVICE_STOPPED: return # If a stop is pending, wait for it. dwStartTime = GetTickCount() dwTimeout = 30000 while ssStatus.dwCurrentState == SERVICE_STOP_PENDING: # Do not wait longer than the wait hint. A good interval is # one-tenth of the wait hint but not less than 1 second # and not more than 10 seconds. Sleep(min(max(1000, ssStatus.dwWaitHint / 10), 10000)) ssStatus = self.GetStatus() if ssStatus.dwCurrentState == SERVICE_STOPPED: return if GetTickCount() - dwStartTime > dwTimeout: raise TimeOutError() # If the service is running, dependencies must be stopped first. #self.StopDependentServices() # Send a stop code to the service. if not ControlService( self.schService, SERVICE_CONTROL_STOP, cast(byref(ssStatus), LPSERVICE_STATUS) ): raise WinError() # Wait for the service to stop. while ssStatus.dwCurrentState != SERVICE_STOPPED: Sleep(ssStatus.dwWaitHint) ssStatus = self.GetStatus() if ssStatus.dwCurrentState == SERVICE_STOPPED: break if GetTickCount() - dwStartTime > dwTimeout: raise TimeOutError()
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 FormatError(code=None): """ A replacement for ctypes.FormtError, but always returns a unicode string. """ if code is None: code = GetLastError() kernel32 = ctypes.windll.kernel32 lpMsgBuf = LPWSTR() numChars = kernel32.FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, None, code, 0, byref(lpMsgBuf), 0, None ) if numChars == 0: raise Exception("FormatMessage failed", GetLastError()) message = lpMsgBuf.value.strip() kernel32.LocalFree(lpMsgBuf) return message
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
def GetWindowProcessName(hWnd): dwProcessId = DWORD() GetWindowThreadProcessId(hWnd, byref(dwProcessId)) return GetProcessName(dwProcessId.value)
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
def GetComPorts(availableOnly=True): """ This generator scans the device registry for com ports and yields port, desc, hwid. If availableOnly is true only return currently existing ports. """ stringBuffer = ctypes.create_unicode_buffer(256) flags = DIGCF_DEVICEINTERFACE if availableOnly: flags |= DIGCF_PRESENT hdi = SetupDiGetClassDevs(byref(GUID_CLASS_COMPORT), None, NULL, flags) #~ for i in range(256): for dwIndex in range(256): did = SP_DEVICE_INTERFACE_DATA() did.cbSize = sizeof(did) if not SetupDiEnumDeviceInterfaces( hdi, None, byref(GUID_CLASS_COMPORT), dwIndex, byref(did) ): if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: raise ctypes.WinError() break dwNeeded = DWORD() # get the size if not SetupDiGetDeviceInterfaceDetail( hdi, byref(did), None, 0, byref(dwNeeded), None ): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # allocate buffer class _SP_DEVICE_INTERFACE_DETAIL_DATA(ctypes.Structure): _fields_ = [ ('cbSize', DWORD), ('DevicePath', TCHAR*(dwNeeded.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), dwNeeded, None, byref(devinfo) ): raise ctypes.WinError() #print idd.DevicePath, sizeof(idd) # hardware ID if not SetupDiGetDeviceRegistryProperty( hdi, byref(devinfo), SPDRP_HARDWAREID, None, cast(stringBuffer, PBYTE), sizeof(stringBuffer) - 1, None ): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() szHardwareID = stringBuffer.value # friendly name #szFriendlyName = ctypes.create_string_buffer('\0' * 250) if not SetupDiGetDeviceRegistryProperty( hdi, byref(devinfo), SPDRP_FRIENDLYNAME, None, cast(stringBuffer, PBYTE), sizeof(stringBuffer) - 1, None ): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() szFriendlyName = stringBuffer.value portName = re.search(r"\((.*)\)", szFriendlyName).group(1) yield portName, szFriendlyName, szHardwareID SetupDiDestroyDeviceInfoList(hdi)
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 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