Getting WM_COPYDATA in Python

I am trying to read the WM_COPYDATA message with Python, some applications (I'm trying with Spotify) to send to WindowsLiveMessenger to update the phrase "What I'm listening to ...".

From what I was able to find, COPYDATASTRUCT messages are included in COPYDATASTRUCT with the following structure:

  • dwData in our case 0x547 to access the listening function now
  • cbData with accepted string length
  • lpData with a pointer to the actual string, may include Unicode characters

The string should have the following format: \0Music\0status\0format\0song\0artist\0album\0 , as indicated by ListeningNowTracker

What we get in the WM_COPYDATA event is a pointer to lParam that contains COPYDATASTRUCT .

I started messing around with pywin32 functions, and I remembered that they did not accept Unicode characters from past experience, then I switched to ctypes. Despite the fact that for me it was almost a new world for Python, I tried using POINTER() , and all that I had was an object unknown to me or access to violations.

I think the code should create COPYDATASTRUCT :

 class CopyDataStruct(Structure): _fields_ = [('dwData', c_int), ('cbData', c_int), ('lpData', c_void_p)] 

Then make lParam pointer to this structure, get the line pointer from lpData and finally get the line with ctypes.string_at(lpData,cbData) .

Any tips?

UPDATE 1

The WM_COPYDATA event was received by a hidden window built with win32gui just for this purpose. The copydata event is associated with a function called OnCopyData , and this is its title:
def OnCopyData(self, hwnd, msg, wparam, lparam):
The values ​​that the function executes are correct compared to the values ​​from the Spy ++ message log.

UPDATE 2

This should be close to what I want, but gives a NULL pointer error.

 class CopyDataStruct(ctypes.Structure): _fields_ = [('dwData', c_int), ('cbData', c_int), ('lpData', c_wchar_p)] PCOPYDATASTRUCT = ctypes.POINTER(CopyDataStruct) pCDS = ctypes.cast(lparam, PCOPYDATASTRUCT) print ctypes.wstring_at(pCDS.contents.lpData) 
+4
source share
1 answer

I wrote the following trivial win32gui application:

 import win32con, win32api, win32gui, ctypes, ctypes.wintypes class COPYDATASTRUCT(ctypes.Structure): _fields_ = [ ('dwData', ctypes.wintypes.LPARAM), ('cbData', ctypes.wintypes.DWORD), ('lpData', ctypes.c_void_p) ] PCOPYDATASTRUCT = ctypes.POINTER(COPYDATASTRUCT) class Listener: def __init__(self): message_map = { win32con.WM_COPYDATA: self.OnCopyData } wc = win32gui.WNDCLASS() wc.lpfnWndProc = message_map wc.lpszClassName = 'MyWindowClass' hinst = wc.hInstance = win32api.GetModuleHandle(None) classAtom = win32gui.RegisterClass(wc) self.hwnd = win32gui.CreateWindow ( classAtom, "win32gui test", 0, 0, 0, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, hinst, None ) print self.hwnd def OnCopyData(self, hwnd, msg, wparam, lparam): print hwnd print msg print wparam print lparam pCDS = ctypes.cast(lparam, PCOPYDATASTRUCT) print pCDS.contents.dwData print pCDS.contents.cbData print ctypes.wstring_at(pCDS.contents.lpData) return 1 l = Listener() win32gui.PumpMessages() 

Then I sent a window a WM_COPYDATA message from another application (written in Delphi):

 Text := 'greetings!'; CopyData.cbData := (Length(Text)+1)*StringElementSize(Text); CopyData.lpData := PWideChar(Text); SendMessage(hwnd, WM_COPYDATA, Handle, NativeInt(@CopyData)); 

The output was:

 461584 461584 74 658190 2620592 42 22 greetings! 

So it seems that it works trivially, to a large extent, as you encoded it.

The only thing I can think of is that the text in Spotify COPYDATASTRUCT does not end with zero. You should be able to verify this quite easily by reading the data. Use the cbData element.

+5
source

Source: https://habr.com/ru/post/1343046/


All Articles