Selaa lähdekoodia

fix: playlist title encoding via MultiByteToWideChar

Winamp IPC_GETPLAYLISTTITLE returns ANSI (char*) strings in its process
memory. Blindly casting bytes to string garbles umlauts and other non-ASCII
chars. Fix: decode via MultiByteToWideChar(CP_ACP) → UTF-16 → Go string,
using the same code page Windows uses for the title.

Also check ReadProcessMemory return value — failures now return empty
string instead of garbage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
master
Jan Svabenik 1 kuukausi sitten
vanhempi
commit
45ab86425f
1 muutettua tiedostoa jossa 38 lisäystä ja 5 poistoa
  1. +38
    -5
      internal/winamp/winamp.go

+ 38
- 5
internal/winamp/winamp.go Näytä tiedosto

@@ -21,6 +21,7 @@ var (
getWindowThreadProcessId = user32.NewProc("GetWindowThreadProcessId")
openProcess = kernel32.NewProc("OpenProcess")
readProcessMemory = kernel32.NewProc("ReadProcessMemory")
multiByteToWideChar = kernel32.NewProc("MultiByteToWideChar")
)

const (
@@ -238,26 +239,58 @@ type TrackInfo struct {
Title string `json:"title"`
}

// readRemoteString reads a null-terminated ANSI string from another process.
// readRemoteString reads a null-terminated ANSI string from another process
// and converts it to UTF-8 via MultiByteToWideChar (CP_ACP = 0) so that
// umlauts and other non-ASCII characters are handled correctly regardless of
// the active Windows code page.
func readRemoteString(proc syscall.Handle, ptr uintptr) string {
if ptr == 0 {
return ""
}
buf := make([]byte, 512)
var read uintptr
readProcessMemory.Call(
ok, _, _ := readProcessMemory.Call(
uintptr(proc),
ptr,
uintptr(unsafe.Pointer(&buf[0])),
uintptr(len(buf)),
uintptr(unsafe.Pointer(&read)),
)
for i, b := range buf {
if ok == 0 || read == 0 {
return ""
}

// Trim to null terminator.
ansi := buf[:read]
for i, b := range ansi {
if b == 0 {
return string(buf[:i])
ansi = ansi[:i]
break
}
}
return string(buf)
if len(ansi) == 0 {
return ""
}

// First call: query required UTF-16 buffer size.
const cpACP = 0
n, _, _ := multiByteToWideChar.Call(
cpACP, 0,
uintptr(unsafe.Pointer(&ansi[0])), uintptr(len(ansi)),
0, 0,
)
if n == 0 {
return string(ansi) // fallback: treat as latin-1
}

// Second call: do the conversion.
wide := make([]uint16, n)
multiByteToWideChar.Call(
cpACP, 0,
uintptr(unsafe.Pointer(&ansi[0])), uintptr(len(ansi)),
uintptr(unsafe.Pointer(&wide[0])), n,
)
return syscall.UTF16ToString(wide)
}

// GetPlaylist returns all titles in the current Winamp playlist.


Loading…
Peruuta
Tallenna