Use of ReadProcessMemory API function for getting song paths from winamp's playlist

P

pangel83

I've been trying for days to write a piece of VB.NET code that will
read from winamp's memory space the paths of the files from the current
winamp playlist.

The GETPLAYLISTFILE command of the winamp API will only return a
pointer to the position of the asked path. An article available on
http://msmvps.com/ch21st/archive/2004/02/26.aspx provides a VB6
implementation of this, using the ReadProcessMemory Windows API
command, but something goes wrong when I transcribe the code to VB.NET!

In the attached code below that contains all you need to recreate my
problem, when the program reaches the "ReadProcessMemory(lpWinamp, lp,
Buffer(0), 260, dwRead)" line it will just exit!!! Can anybody help? I
am annoyed because I know that it will just be due to some stupid
declaration blunder

----------------------------------------------------------------
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
MsgBox(Me.GetPlaylistFile(0))
End Sub

Dim WinampWindow As Integer


Public Declare Function FindWindow Lib "user32" Alias "FindWindowA"
(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Public Declare Function SendMessage Lib "user32" Alias
"SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal
wParam As Integer, ByVal lParam As Integer) As Integer
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd
As Integer, ByRef lpdwProcessId As Integer) As Integer
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess
As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As
Integer) As Integer
Private Const PROCESS_VM_READ As Long = &H10
Public Const IPC_GETPLAYLISTFILE = 211
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject
As Long) As Long
Declare Function ReadProcessMemory Lib "kernel32" Alias
"ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As
Integer, ByRef lpBuffer As Byte(), ByVal nSize As Integer, ByRef
lpNumberOfBytesWritten As Integer) As Integer


Public Function FindWinamp() As Boolean

WinampWindow = FindWindow("Winamp v1.x", vbNullString)
If WinampWindow <> 0 Then
Return True
End If
Return False
End Function
Public Function GetPlaylistFile(ByVal TrackNo As Integer) As String
Dim strFileName As String
Dim lp As Integer
Dim lpWinamp As Integer
Dim PID As Integer

Dim Buffer(260) As Byte
Dim Temp As String

Dim dwRead As Long

FindWinamp()

lp = SendMessage(WinampWindow, &H400, TrackNo,
IPC_GETPLAYLISTFILE)
If lp = 0 Then
Return ""
Exit Function
End If
GetWindowThreadProcessId(WinampWindow, PID)
lpWinamp = OpenProcess(PROCESS_VM_READ, 0, PID)
If lpWinamp = 0 Then
Return ""
Exit Function
End If

Dim tmpString As String
ReadProcessMemory(lpWinamp, lp, Buffer(0), 260, dwRead)

Call CloseHandle(lpWinamp)

'don't yet have a clue what to do from here!
'Temp = StrConv(Buffer, vbUnicode)
'strFileName = Left$(Temp, InStr(Temp, Chr$(0)) - 1)

Return strFileName
End Function
 
T

Tom Shelton

I've been trying for days to write a piece of VB.NET code that will
read from winamp's memory space the paths of the files from the current
winamp playlist.

The GETPLAYLISTFILE command of the winamp API will only return a
pointer to the position of the asked path. An article available on
http://msmvps.com/ch21st/archive/2004/02/26.aspx provides a VB6
implementation of this, using the ReadProcessMemory Windows API
command, but something goes wrong when I transcribe the code to VB.NET!

In the attached code below that contains all you need to recreate my
problem, when the program reaches the "ReadProcessMemory(lpWinamp, lp,
Buffer(0), 260, dwRead)" line it will just exit!!! Can anybody help? I
am annoyed because I know that it will just be due to some stupid
declaration blunder

----------------------------------------------------------------
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
MsgBox(Me.GetPlaylistFile(0))
End Sub

Dim WinampWindow As Integer


Public Declare Function FindWindow Lib "user32" Alias "FindWindowA"
(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Public Declare Function SendMessage Lib "user32" Alias
"SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal
wParam As Integer, ByVal lParam As Integer) As Integer
Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd
As Integer, ByRef lpdwProcessId As Integer) As Integer
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess
As Integer, ByVal bInheritHandle As Integer, ByVal dwProcessId As
Integer) As Integer
Private Const PROCESS_VM_READ As Long = &H10
Public Const IPC_GETPLAYLISTFILE = 211
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject
As Long) As Long
Declare Function ReadProcessMemory Lib "kernel32" Alias
"ReadProcessMemory" (ByVal hProcess As Integer, ByVal lpBaseAddress As
Integer, ByRef lpBuffer As Byte(), ByVal nSize As Integer, ByRef
lpNumberOfBytesWritten As Integer) As Integer


Public Function FindWinamp() As Boolean

WinampWindow = FindWindow("Winamp v1.x", vbNullString)
If WinampWindow <> 0 Then
Return True
End If
Return False
End Function
Public Function GetPlaylistFile(ByVal TrackNo As Integer) As String
Dim strFileName As String
Dim lp As Integer
Dim lpWinamp As Integer
Dim PID As Integer

Dim Buffer(260) As Byte
Dim Temp As String

Dim dwRead As Long

FindWinamp()

lp = SendMessage(WinampWindow, &H400, TrackNo,
IPC_GETPLAYLISTFILE)
If lp = 0 Then
Return ""
Exit Function
End If
GetWindowThreadProcessId(WinampWindow, PID)
lpWinamp = OpenProcess(PROCESS_VM_READ, 0, PID)
If lpWinamp = 0 Then
Return ""
Exit Function
End If

Dim tmpString As String
ReadProcessMemory(lpWinamp, lp, Buffer(0), 260, dwRead)

Call CloseHandle(lpWinamp)

'don't yet have a clue what to do from here!
'Temp = StrConv(Buffer, vbUnicode)
'strFileName = Left$(Temp, InStr(Temp, Chr$(0)) - 1)

Return strFileName
End Function
WARNING: Untested, off the cuff conversion...

Private Const PROCESS_VM_READ As Long = &H10
Private Const IPC_GETPLAYLIST = 211

Private Declare Auto Function FindWindow Lib "user32" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr

Private Declare Auto Function SendMessage Lib "user32" _
(ByVal hwnd As IntPtr, _
ByVal wMsg As Integer, _
ByVal wParam As Integer, _
ByVal lParam As Integer) As IntPtr

Private Declare Function GetWindowThreadProcessId Lib "user32" _
(ByVal hwnd, _
ByRef lpdwProcessId As IntPtr) As IntPtr

Private Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Integer, _
ByVal bIneritHandle As Boolean, _
ByVal dwProcessId As IntPtr) As IntPtr

Private Declare Function ReadProcessMemory Lib "kernel32" _
(ByVal hProcess As IntPtr, _
ByRef lpBase Address As IntPtr, _
ByVal lpBuffer() As Byte, _
ByVal nSize As Integer, _
ByRef lpNumberOfBytesWritten As Integer) As Boolean

Private Declare Function CloseHandle Lib "kernel32" _
(ByVal hObject As IntPtr) As Boolean

Private Function FindWinamp () As IntPtr
Return FindWindow ("Winamp v1.x", vbNullString)
End Function

Public Function GetPlaylistFile (ByVal TrackNo As Integer) As String
Dim winampWindow As IntPtr = FindWinamp ()
Dim fileName As String = String.Empty

If Not IsNullPtr (winampWindow) Then

Dim lp As IntPtr = SendMessage ( _
winampWindow, &H400, TrackNo, IPC_GETPLAYLISTFILE)

If Not IsNullPtr (lp) Then

Dim pid As IntPtr

Call GetWindowThreadProcessId (winampWindow, pid)
If Not IsNullPtr (pid) Then

Dim hWinampProcess As IntPtr = OpenProcess ( _
PROCESS_VM_READ, False, pid)

If Not IsNullPtr (hWinampProcess) Then

Dim buffer (260) As Byte
Dim bytesWritten As Integer

If ReadProcessMemory _
(hWinampProcess, _
lp, _
buffer, _
buffer.Length, _
bytesWritten) Then


' At this point, I would have
' to play a bit. But, you would use
' one of the System.Text.Encoding classes
' to convert the byte array to a string...

End If

CloseHandle (hWinampProcess)
End If

End If

End If

End If

Return fileName

End Function

Private Function IsNullPtr (ByVal ptr As IntPtr) As Boolean
Return ptr.Equals (IntPtr.Zero)
End Function

HTH
 
P

pangel83

This gets annoying... Tried most of the classes in System.Text.Encoding
to process the obtained bytes, and I keep getting the following
giberish: "UVßwXjÝw
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top