Home Download Screenshots Wiki Plugins Translations Developers Donate Forums/Help Contact Us |
StrokeIt
WinAmp + Lua + SendMessage to get filename/title currently playingPosted by gemisigo
There is this little piece of lua code:
require [[alien]] --require [[clipboard]] --define local WM_USER = 0x400 local WM_COMMAND = 0x0 local PROCESS_ALL_ACCESS = 0x1F0FFF local PROCESS_VM_READ = 0x0010 local PROCESS_VM_WRITE = 0x0020 local PROCESS_VM_OPERATION = 0x0008 local FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 local PAGE_EXECUTE = 0x10 local PAGE_EXECUTE_READ = 0X20 local PAGE_EXECUTE_READWRITE = 0x40 local WA_GET_PLAYLIST_INDEX = 125 local WA_GET_FILENAME = 211 local WA_GET_FILENAMEW = 214 local WA_GET_TITLE = 212 local WA_GET_TITLEW = 213 local FindWindow = alien.User32.FindWindowA FindWindow:types{ret = 'long', abi = 'stdcall', 'string', 'string'} local SendMessage = alien.User32.SendMessageA SendMessage:types{ret = 'long', abi = 'stdcall', 'long', 'long', 'long', 'long'} local GetWindowThreadProcessId = alien.User32.GetWindowThreadProcessId GetWindowThreadProcessId:types{ret = 'long', abi = 'stdcall', 'long', 'pointer'} local OpenProcess = alien.kernel32.OpenProcess OpenProcess:types{ret = 'long', abi = 'stdcall', 'long', 'byte', 'long'} local VirtualProtectEx = alien.kernel32.VirtualProtectEx VirtualProtectEx:types{ret = 'long', abi = 'stdcall', 'long', 'long', 'long', 'long', 'pointer'} local ReadProcessMemory = alien.kernel32.ReadProcessMemory ReadProcessMemory:types{ret = 'int', abi = 'stdcall', 'long', 'long', 'pointer', 'long', 'pointer'} local CloseHandle = alien.kernel32.CloseHandle CloseHandle:types{ret = 'int', abi = 'stdcall', 'long'} local GetLastError = alien.kernel32.GetLastError GetLastError:types{ret = 'long', abi = 'stdcall'} --implement local hwnd_winamp = FindWindow('Winamp v1.x',NULL) --print('hwnd_winamp : ' .. hwnd_winamp) local index = SendMessage(hwnd_winamp, WM_USER, 0, WA_GET_PLAYLIST_INDEX) --print('index : ' .. index) local lp_filename = SendMessage(hwnd_winamp, WM_USER, index, WA_GET_FILENAME) --print('lp_filename : ' .. lp_filename) local lp_songtitle = SendMessage(hwnd_winamp, WM_USER, index, WA_GET_TITLE) --print('lp_songtitle : ' .. lp_songtitle) local temp_handle = alien.buffer(4) local process_id = GetWindowThreadProcessId(hwnd_winamp, temp_handle) temp_handle = temp_handle:get(1, 'long') --print('process_id : ' .. process_id) --print('temp_handle : ' .. temp_handle) local h_winamp = OpenProcess(PROCESS_ALL_ACCESS, false, temp_handle) --print('h_winamp : ' .. h_winamp) local read_bytes = alien.buffer(4) local buf = alien.buffer(255) local buf2 = alien.buffer(255) local oldprotect = alien.buffer(4) local newprotect = alien.buffer(4) newprotect[1] = PAGE_EXECUTE_READ local vpe = VirtualProtectEx(h_winamp, lp_filename, 256, newprotect:get(1, 'long'), oldprotect) --print('vpe alter success : ' ..vpe) --print(' oldprotect : ' .. oldprotect:get(1, 'long')) --print(' newprotect : ' .. newprotect:get(1, 'long')) local rr = ReadProcessMemory(h_winamp, lp_filename, buf, 256, read_bytes) local last_error = GetLastError() --print('last error : ' .. last_error) --print('read success : ' .. rr) local rr = ReadProcessMemory(h_winamp, lp_songtitle, buf2, 256, read_bytes) local last_error = GetLastError() --print('last error : ' .. last_error) --print('read success : ' .. rr) vpe = VirtualProtectEx(h_winamp, lp_filename, 256, oldprotect:get(1,'long'), newprotect) --print('vpe rest success : ' ..vpe) --print(' oldprotect : ' .. newprotect:get(1, 'long')) --print(' newprotect : ' .. oldprotect:get(1, 'long')) --print('read bytes read : ' .. read_bytes:get(1, 'long')) --print('buffer contents : ' .. "'" .. tostring(buf) .. "'") --print('buffer2 contents : ' .. "'" .. tostring(buf2) .. "'") local rv = CloseHandle(h_winamp) --print('close success : ' .. rv) --clipboard.set(tostring(buf)) According to WinAmp SDK + google, sending those three messages to WinAmp will retrieve the playlist index, and two pointers pointing to the filename and the title of the song currently playing/selected. Those two pointer refer to memory locations in WinAmp's memory area but that does not matter, I can read them with ReadProcessMemory. Now the problem is: I can get the index and either of the filename or the title but not both. If I send the message to get the title, the returned pointer will point exactly to the same place where the filename pointer does. But when I try to read from that memory area, a very weird thing happens. It's not the filename that I get. It's the title. I would like to ask those of you out there using WinAmp and Lua to try and see if you get the correct results from the code above, please. Or if you spot it, cast light on where I failed. EDIT: I left the 'print'-s in the code (though commented them). It's easier to 'debug' in a lua environment than using StrokeIt. Edited 2 time(s). Last edit at 01/29/2010 06:25PM by gemisigo.
HWND hwndWinamp = FindWindow("Winamp v1.x",NULL);
char this_title[2048],*p; GetWindowText(hwndWinamp,this_title,sizeof(this_title)); p = this_title+strlen(this_title)-8; while (p >= this_title) { if (!strnicmp(p,"- Winamp",8)) break; p--; } if (p >= this_title) p--; while (p >= this_title && *p == ' ') p--; *++p=0;
local TempHandle = 0
hwndWinamp = FindWindow("Winamp v1.x", NULL) TrackPos = SendMessage(hwndWinamp, WM_USER, 0, 125) MPointer = SendMessage(hwndWinamp, WM_USER, TrackPos, 211)--212 is Title temp = GetWindowThreadProcessId(hwndWinamp, TempHandle) hwndWinampP = OpenProcess(PROCESS_VM_READ, False, TempHandle) local Data = alien.buffer(256) nTemp = ReadProcessMemory(hwndWinampP, MPointer, Data, 256, temp) pTemp = CloseHandle(hwndWinampP) ShowFile = Data should work but read a little google :) http://forums.winamp.com/showthread.php?threadid=85389 Edited 4 time(s). Last edit at 02/02/2010 12:48PM by Leo.
Thanks, Leo, but I think you misunderstood :) What you posted was exactly the way I was doing it. Meanwhile I solved it, I'll post it here so it might help others if they try the same.
WinAmp SDK states that message id 211 (with index in data) returns a pointer to the char* where a playlist item's filename is located and message id 212 returns a similar pointer to its title. My presumption was (and I had no reason to doubt that I'm right - reason later :) ) that it points to two different locations. I should have smelled a rat when I saw that indexing another playlist entry it still returned the same value and the solution was within my grasp when it returned the same value for title message, too. I was just too dumb to recognize that my presumption was false (and that WinAmp SDK description is a bit misleading if you read it sloppily, as I did). The pointer does point to a string containing filename/title. It does point to a string. The contents of these strings (which are exactly at the same address) depend on the message id. WinAmp does search for the playlist entry data in the memory but does not return a pointer to that address. It collects the data and copies to a certain address. Issuing id 211 WinAmp placed the filename at that position and issuing 212 right after the first message (and prior reading it) resulted in WinAmp overwriting the string already placed there. That was the reason it did not work. The order of sending message/reading address was incorrect. The lesson today : be careful when presuming. Check if you're not sure :) |