Help! - Reading playlist files from winamp through Windows & Winamp APIs & .NET - Decoding memory co

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. Through digging and asking around, I managed to read the
memory contents that winamp points to, but I can't seem to be able to
decode them!

In the attached code below that contains all you need to recreate my
problem. The function always returns the following giberish:
"UVßwXjÝw

======================================================================

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

Private Const PROCESS_VM_READ As Long = &H10
Private Const IPC_GETPLAYLISTFILE = 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 As IntPtr, 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 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(1000) As Byte
Dim bytesWritten As Integer

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

fileName = System.Text.Encoding.Default.GetString(buffer)
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
 
S

Stefan De Schepper

The error lies in the fact that the lpBase argument of the ReadProcessMemory
declaration should be declared ByVal, not ByRef.

Hope this helps,
Stefan


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. Through digging and asking around, I managed to read the
memory contents that winamp points to, but I can't seem to be able to
decode them!

In the attached code below that contains all you need to recreate my
problem. The function always returns the following giberish:
"UVßwXjÝw

======================================================================

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

Private Const PROCESS_VM_READ As Long = &H10
Private Const IPC_GETPLAYLISTFILE = 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 As IntPtr, 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 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(1000) As Byte
Dim bytesWritten As Integer

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

fileName = System.Text.Encoding.Default.GetString(buffer)
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
 

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