Skip to content

Instantly share code, notes, and snippets.

@yizhang82
Created January 8, 2017 05:23
Show Gist options
  • Save yizhang82/67fa4ecb8dfb379193cfbce2400833b9 to your computer and use it in GitHub Desktop.
Save yizhang82/67fa4ecb8dfb379193cfbce2400833b9 to your computer and use it in GitHub Desktop.
Sample go code to call COM code, using IMalloc/CoGetMalloc as an example
package main
import (
"fmt"
"log"
"syscall"
"unsafe"
)
type MallocVtbl struct {
queryInterface uintptr
addref uintptr
release uintptr
alloc uintptr
realloc uintptr
free uintptr
getSize uintptr
didAlloc uintptr
heapMinimize uintptr
}
func main() {
fmt.Printf("Loading ole32.dll...\n");
handle, err := syscall.LoadLibrary("ole32.dll")
if err != nil {
log.Fatal(err)
return
}
proc, err := syscall.GetProcAddress(handle, "CoGetMalloc")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Calling CoGetMalloc\n");
var malloc uintptr;
ret, _, err := syscall.Syscall(proc, uintptr(2), uintptr(1), uintptr(unsafe.Pointer(&malloc)), uintptr(0))
if ret < 0 {
log.Fatal(err)
}
fmt.Printf("CoGetMalloc returned %x\n\n", malloc)
mallocVtblPtr := *(*uintptr)(unsafe.Pointer(malloc))
mallocVtbl := (*MallocVtbl)(unsafe.Pointer(mallocVtblPtr))
const memSize int = 100
fmt.Printf("Calling IMalloc::Alloc(%v)\n", memSize)
memPtr, _, err := syscall.Syscall(mallocVtbl.alloc, uintptr(2), malloc, uintptr(memSize), uintptr(0))
if memPtr == 0 {
log.Fatal(err)
}
fmt.Printf("IMalloc::Alloc returned %x\n\n", memPtr)
fmt.Printf("Calling IMalloc::GetSize with %x\n", memPtr)
returnedSize, _, err := syscall.Syscall(mallocVtbl.getSize, uintptr(2), malloc, memPtr, uintptr(0))
fmt.Printf("IMalloc::GetSize returned %v\n\n", returnedSize)
fmt.Printf("Calling IMalloc::Free with %x\n", memPtr);
syscall.Syscall(mallocVtbl.free, uintptr(2), malloc, memPtr, uintptr(0))
fmt.Printf("IMalloc::Free succeeded\n\n");
fmt.Printf("Calling IMalloc::DidAlloc with %x\n", memPtr)
ret, _, err = syscall.Syscall(mallocVtbl.didAlloc, uintptr(2), malloc, memPtr, uintptr(0))
didAlloc := bool(ret != 0)
fmt.Printf("IMalloc::DidAlloc returned %v\n\n", didAlloc);
fmt.Printf("Calling IMalloc::Release\n")
ret, _, err = syscall.Syscall(mallocVtbl.release, uintptr(1), malloc, uintptr(0), uintptr(0))
fmt.Printf("IMalloc::Release returned %v\n\n", ret);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment