Call windows function (getting the font directory) - winapi

I try to find out the font folder on a windows installation. AFAICS the proposed way is to call SHGetKnownFolderPath in Shell32.dll with KNOWNFOLDERID set to FOLDERID_Fonts.
I have no idea what to pass to the Call function in the code below:
package main
import (
"syscall"
)
func main() {
// HRESULT SHGetKnownFolderPath(
// _In_ REFKNOWNFOLDERID rfid,
// _In_ DWORD dwFlags,
// _In_opt_ HANDLE hToken,
// _Out_ PWSTR *ppszPath
// );
var (
shell32 = syscall.NewLazyDLL("Shell32.dll")
shGetKnowFolderPath = shell32.NewProc("SHGetKnownFolderPath")
// Doesn't work, of course:
folderId int
flags int
handle int
retval int
)
shGetKnowFolderPath.Call(uintptr(folderId), uintptr(flags), uintptr(handle), uintptr(retval))
}
Any idea? (I guess a workaround for now would be to stick to %windir%\Fonts, but I'd like to get a proper solution).
References:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx

For example,
package main
import (
"fmt"
"syscall"
"unsafe"
)
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
var (
FOLDERID_Fonts = GUID{0xFD228CB7, 0xAE11, 0x4AE3, [8]byte{0x86, 0x4C, 0x16, 0xF3, 0x91, 0x0A, 0xB8, 0xFE}}
)
var (
modShell32 = syscall.NewLazyDLL("Shell32.dll")
modOle32 = syscall.NewLazyDLL("Ole32.dll")
procSHGetKnownFolderPath = modShell32.NewProc("SHGetKnownFolderPath")
procCoTaskMemFree = modOle32.NewProc("CoTaskMemFree")
)
func SHGetKnownFolderPath(rfid *GUID, dwFlags uint32, hToken syscall.Handle, pszPath *uintptr) (retval error) {
r0, _, _ := syscall.Syscall6(procSHGetKnownFolderPath.Addr(), 4, uintptr(unsafe.Pointer(rfid)), uintptr(dwFlags), uintptr(hToken), uintptr(unsafe.Pointer(pszPath)), 0, 0)
if r0 != 0 {
retval = syscall.Errno(r0)
}
return
}
func CoTaskMemFree(pv uintptr) {
syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(pv), 0, 0)
return
}
func FontFolder() (string, error) {
var path uintptr
err := SHGetKnownFolderPath(&FOLDERID_Fonts, 0, 0, &path)
if err != nil {
return "", err
}
defer CoTaskMemFree(path)
folder := syscall.UTF16ToString((*[1 << 16]uint16)(unsafe.Pointer(path))[:])
return folder, nil
}
func main() {
folder, err := FontFolder()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Font Folder:", folder)
}
Output:
Font Folder: C:\Windows\Fonts

golang.org/x/sys/windows now has a wrapper for SHGetKnownFolderPath, so this is much easier:
package main
import (
"fmt"
"golang.org/x/sys/windows"
)
func main() {
path, err := windows.KnownFolderPath(windows.FOLDERID_Fonts, 0)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(path)
}

Just in case someone needs the folder id for documents in golang format:
Replace this in peterSO's code example:
FOLDERID_Documents = GUID{0xFDD39AD0, 0x238F, 0x46AF, [8]byte{0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7}}
FOLDERID_PublicDocuments = GUID{0xED4824AF, 0xDCE4, 0x45A8, [8]byte{0x81, 0xE2, 0xFC, 0x79, 0x65, 0x08, 0x36, 0x34}}
see
https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx

folderId for the fonts directory is {FD228CB7-AE11-4AE3-864C-16F3910AB8FE}
flags can probably be SHGFP_TYPE_DEFAULT
handle can probably be NULL
retval I think should be a bool but I'm not sure.
All answers are from your previously linked SHGetFolderPath function.

Related

How can I make the program automatically exit after audio played over

I'm writing a small tool, it can play audio file in the command/terminal like sox. I'm using bass.dll and Golang syscall for Windows.
Here is my code, files can downloaded from comments, only run on Windows X64.
bass.go on github gist
package main
import (
"fmt"
"syscall"
"time"
"unsafe"
)
/*
基于 [bass.dll](http://us2.un4seen.com/files/bass24.zip)
和 [Golang syscall](https://github.com/golang/go/wiki/WindowsDLLs)
实现的命令行版播放器。
*/
type BassLib struct {
libBass syscall.Handle
init uintptr
free uintptr
streamCreateFile uintptr
channelPlay uintptr
channelPause uintptr
channelStop uintptr
}
func (bass *BassLib) LoadBass(bassDllPath string) bool {
bass.libBass, _ = syscall.LoadLibrary(bassDllPath)
if bass.libBass == 0 {
fmt.Println("load library result")
fmt.Println(bass.libBass)
return false
}
bass.init, _ = syscall.GetProcAddress(bass.libBass, "BASS_Init")
// BASS_init(device, freq, flags, win, clsid)
// see http://www.un4seen.com/doc/#bass/BASS_Init.html
device := 1
syscall.Syscall6(bass.init, 5, uintptr(device), uintptr(44100), uintptr(0), uintptr(0), uintptr(0), 0)
return true
}
func StrPtr(s string) uintptr {
// return uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(s)))
p, _ := syscall.UTF16PtrFromString(s)
return uintptr(unsafe.Pointer(p))
}
func (bass *BassLib) PlayFile(filePath string) {
bass.streamCreateFile, _ = syscall.GetProcAddress(bass.libBass, "BASS_StreamCreateFile")
// hstream = BASS_StreamCreateFile(mem=0, &file, offset=0, length=0, flags=(A_IsUnicode ? 0x80000000 : 0x40000))
// see http://www.un4seen.com/doc/#bass/BASS_StreamCreateFile.html
var bassUnicode uint32 = 0x80000000
hstream, _, _ := syscall.Syscall6(bass.streamCreateFile, 5, uintptr(0), StrPtr(filePath), uintptr(0), uintptr(0), uintptr(bassUnicode), 0)
// bassErrorGetCode, _ := syscall.GetProcAddress(bass.libBass, "BASS_ErrorGetCode")
// errCode, _, _ := syscall.Syscall(uintptr(bassErrorGetCode), 0, 0, 0, 0)
// fmt.Println(errCode)
fmt.Println("hstream")
fmt.Println(hstream)
bass.channelPlay, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelPlay")
// BASS_ChannelPlay(hstream)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelPlay.html
ret, _, _ := syscall.Syscall(bass.channelPlay, 2, hstream, uintptr(0), 0)
bassErrorGetCode, _ := syscall.GetProcAddress(bass.libBass, "BASS_ErrorGetCode")
errCode, _, _ := syscall.Syscall(bassErrorGetCode, 0, 0, 0, 0)
fmt.Println(errCode)
fmt.Println(ret)
// sleep to wait playing mp3 file
time.Sleep(time.Second * 10)
// bass.channelPause, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelPause")
// bass.channelStop, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelStop")
// return true
}
func (bass *BassLib) UnLoad() {
if bass.libBass != 0 {
bass.free, _ = syscall.GetProcAddress(bass.libBass, "BASS_Free")
syscall.Syscall(bass.free, 0, 0, 0, 0)
// BASS_Free()
// see http://www.un4seen.com/doc/#bass/BASS_Free.html
syscall.FreeLibrary(bass.libBass)
}
}
func main() {
bass := &BassLib{}
bass.LoadBass("C:\\workspace\\play\\bass.dll")
bass.PlayFile("C:\\workspace\\play\\sample.mp3")
bass.UnLoad()
}
There is a big problem:
if time.Sleep code (bass.go line 68) not added , no sound played with quickly quit out.
When I added time.Sleep(time.Second * 10) code, maybe the audio duration more than 10 seconds.
Is there any possibility that make the program automatically exit after audio played over?
I think you can use defer keyword of golang to trigger an exit when play function have done.
You can refer here: A Tour of Go | Defer
Or here: Golang Blog | Defer
package main
import "fmt"
func main() {
defer fmt.Println("world")
fmt.Println("hello")
}
==========
$ go run main.go
hello
world
I would strongly recommend going through Effective Go on the golang.org website (it's not a long read, I am sure you can go through all the ideas in a single day), paying special attention to the concurrency section.
The whole idea behind Go is to make concurrency and asynchronous programming easy, and it uses several language constructs (channels, goroutines) especially designed to help you handle these cases.
For example, you can use a channel to signal:
func main() {
// end signal
finished := make(chan bool)
// create and run a goroutine
go func() {
// do your bass stuff here
...
// send a signal
finished <- true
}()
// wait
<-finished
}
A common pattern is also to pass the channel to the function doing the job:
func main() {
// end signal
finished := make(chan bool)
// PlayFile is responsible for
// signalling 'finished' when done
go PlayFile(someFile, finished);
// wait
<-finished
}
Or, if you have multiple routines, you will use a WaitGroup:
func main() {
// create the waitgroup
var wg sync.WaitGroup
// number of semaphores
wg.Add(1)
go func() {
// notify WaitGroup when done
// (the 'defer' keyword means
// this call will be executed before
// returning from the method)
defer wg.Done()
// do your bass stuff here
...
}()
wg.Wait()
}
Thanks everyone. Can solve the problem with BASS_ChannelGetLength and BASS_ChannelGetPosition functions.
Here is the code:
// +build windows
package main
import (
"fmt"
"syscall"
"time"
"unsafe"
)
/*
基于 [bass.dll](http://us2.un4seen.com/files/bass24.zip)
和 [Golang syscall](https://github.com/golang/go/wiki/WindowsDLLs)
实现的命令行版播放器。
*/
type (
BASSErrorGetCode int32
)
const (
BassUnicode uint32 = 0x80000000 // BASS_UNICODE
BassSampleFloat uint32 = 256 // BASS_SAMPLE_FLOAT
BassPosByte uint64 = 0 // BASS_POS_BYTE
)
type BassLib struct {
libBass syscall.Handle
init uintptr
free uintptr
streamCreateFile uintptr
channelPlay uintptr
channelPause uintptr
channelStop uintptr
channelGetLength uintptr
channelGetPosition uintptr
channelBytes2Seconds uintptr
}
func (bass *BassLib) LoadBass(bassDllPath string) bool {
bass.libBass, _ = syscall.LoadLibrary(bassDllPath)
if bass.libBass == 0 {
fmt.Println("Load `bass.dll` library failed!")
errCode := bass.GetBassErrorGetCode()
fmt.Println("Bass_Init failed!")
fmt.Println(errCode)
return false
}
bass.init, _ = syscall.GetProcAddress(bass.libBass, "BASS_Init")
// BASS_Init(device, freq, flags, win, clsid)
// see http://www.un4seen.com/doc/#bass/BASS_Init.html
device := 1
r, _, _ := syscall.Syscall6(bass.init, 5, uintptr(device), uintptr(44100), uintptr(0), uintptr(0), uintptr(0), 0)
// var ret = *(* int)(unsafe.Pointer(&r))
if r == 0 {
errCode := bass.GetBassErrorGetCode()
fmt.Println("Bass_Init failed!")
fmt.Println(errCode)
return false
}
return true
}
func StrPtr(s string) uintptr {
p, _ := syscall.UTF16PtrFromString(s)
return uintptr(unsafe.Pointer(p))
}
func (bass *BassLib) PlayFile(filePath string) {
bass.streamCreateFile, _ = syscall.GetProcAddress(bass.libBass, "BASS_StreamCreateFile")
// hStream = BASS_StreamCreateFile(mem=0, &file, offset=0, length=0, flags=(A_IsUnicode ? 0x80000000 : 0x40000))
// see http://www.un4seen.com/doc/#bass/BASS_StreamCreateFile.html
hStream, _, _ := syscall.Syscall6(bass.streamCreateFile, 5, uintptr(0), StrPtr(filePath), uintptr(0), uintptr(0), uintptr(BassUnicode|BassSampleFloat), 0)
bass.channelPlay, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelPlay")
// BASS_ChannelPlay(hStream)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelPlay.html
r, _, _ := syscall.Syscall(bass.channelPlay, 2, hStream, uintptr(0), 0)
if r == 1 {
totalDuration := bass.GetAudioByteLength(hStream)
// currentPos := bass.GetAudioCurrentBytePosition(hStream)
fmt.Println(totalDuration)
// fmt.Println(currentPos)
time.Sleep(time.Second*1)
for {
currentPos := bass.GetAudioCurrentBytePosition(hStream)
if currentPos >= totalDuration {
break
}
}
} else {
errCode := bass.GetBassErrorGetCode()
fmt.Println("Bass_ChannelPlay failed!")
fmt.Println(errCode)
}
}
func (bass *BassLib) GetBassErrorGetCode() BASSErrorGetCode {
bassErrorGetCode, _ := syscall.GetProcAddress(bass.libBass, "BASS_ErrorGetCode")
// BASS_ErrorGetCode()
// BASS_OK BASSErrorGetCode = 0 // all is OK
// BASS_ERROR_MEM BASSErrorGetCode = 1 // memory error
// ...
// see http://www.un4seen.com/doc/#bass/BASS_ErrorGetCode.html
errCode, _, _ := syscall.Syscall(bassErrorGetCode, 0, 0, 0, 0)
var iErrCode = *(*BASSErrorGetCode)(unsafe.Pointer(&errCode))
return iErrCode
}
func (bass *BassLib) GetAudioByteLength(handle uintptr) uintptr {
// (QWORD) BASS_ChannelGetLength(handle=hStream, mode)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelGetLength.html
bass.channelGetLength, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelGetLength")
len, _, _ := syscall.Syscall(bass.channelGetLength, 2, handle, uintptr(BassPosByte), 0)
return len
}
func (bass *BassLib) GetAudioCurrentBytePosition(handle uintptr) uintptr {
// BASS_ChannelGetPosition(handle=hStream, mode)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelGetPosition.html
bass.channelGetPosition, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelGetPosition")
pos, _, _ := syscall.Syscall(bass.channelGetPosition, 2, handle, uintptr(BassPosByte), 0)
return pos
}
func (bass *BassLib) GetChannelBytes2Seconds(handle uintptr, pos uintptr) uintptr {
// BASS_ChannelBytes2Seconds(handle=hStream, pos)
// see http://www.un4seen.com/doc/#bass/BASS_ChannelBytes2Seconds.html
// bass.channelBytes2Seconds, _ = syscall.GetProcAddress(bass.libBass, "BASS_ChannelBytes2Seconds")
len, _, _ := syscall.Syscall(bass.channelBytes2Seconds, 2, handle, pos, 0)
return len
}
func (bass *BassLib) UnLoad() {
if bass.libBass != 0 {
bass.free, _ = syscall.GetProcAddress(bass.libBass, "BASS_Free")
syscall.Syscall(bass.free, 0, 0, 0, 0)
// BASS_Free()
// see http://www.un4seen.com/doc/#bass/BASS_Free.html
syscall.FreeLibrary(bass.libBass)
}
}
func main() {
bass := &BassLib{}
bass.LoadBass("C:\\workspace\\play\\bass.dll")
bass.PlayFile("C:\\workspace\\play\\sample.mp3")
bass.UnLoad()
}
Also you can get at https://gist.github.com/ycrao/e7d1df181f870091b4a6d298d6ea2770#file-bass_play-go-L81-L91 .

What are equal API for syscall.StringToUTF16, syscall.CreateFile and syscall.DeviceIoControl in mac

I have the following Go code in Windows, and I want to port it to Mac.
What are equal API for syscall.StringToUTF16, syscall.CreateFile in Mac?
import (
"syscall"
"unsafe"
"github.com/golang/glog" )
import "C"
const loggerDeviceName string = `\\.\Global\DGAPIMon`
var (
loghandle syscall.Handle
logdevid uint32 )
func InitLogger() (err error) {
// Setup the device id for the logger ioctl
deviceType := 0x00008307
access := 0
function := 0x72 // LOG STRING
method := 0
logdevid = uint32(((deviceType) << 16) | ((access) << 14) | ((function) << 2) | (method))
devPath := syscall.StringToUTF16(loggerDeviceName)
loghandle, err = syscall.CreateFile(&devPath[0], syscall.GENERIC_READ|syscall.GENERIC_WRITE,
0, nil, syscall.OPEN_EXISTING, syscall.FILE_ATTRIBUTE_NORMAL, 0)
if err == nil {
glog.V(3).Infof("loghandle: %v logdevid: 0x%x", loghandle, logdevid)
}
return err }
loghandle and logdevid are using as below to log the message to a file.
typedef struct tagLOGSTRING
{
unsigned long level;
wchar_t message[1024];
}LOGSTRING;
func LogMsg(b []byte) (err error) {
var logstring C.LOGSTRING
logstring.level = 0
tmp := syscall.StringToUTF16(string(b[:]))
for i := range tmp {
logstring.message[i] = C.uint16_t(tmp[i])
}
err = syscall.DeviceIoControl(loghandle, logdevid,
(*byte)(unsafe.Pointer(&logstring)),
(uint32)(unsafe.Sizeof(logstring)),
nil, 0, nil, nil)
return err
}

Go lang set windows events hooks

Hi am trying to set a global event hook in go but i dont get the event handle or any error message , kindly help , below is code , from my code below i expected to get error message from SetWinEventHook if any but it just blocks at Logger.Println("procSetWinEventHook S") please not that i have not included my custo Logger but thats not a blocker.
package main
import(
"fmt"
"syscall"
"unsafe"
"log"
"golang.org/x/sys/windows"
)
var(
user32 = windows.NewLazyDLL("user32.dll")
modkernel32 = windows.NewLazyDLL("kernel32.dll")
procSetWinEventHook = user32.NewProc("SetWinEventHook")
procUnhookWinEvent = user32.NewProc("UnhookWinEvent")
procGetMessage = user32.NewProc("GetMessageW")
procTranslateMessage = user32.NewProc("TranslateMessage")
procDispatchMessage = user32.NewProc("DispatchMessageW")
procGetModuleHandle = modkernel32.NewProc("GetModuleHandleW")
ActiveWinEventHook WINEVENTPROC = func (hWinEventHook HWINEVENTHOOK, event uint32, hwnd HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) {
log.Println("fond")
}
)
type WINEVENTPROC func(hWinEventHook HWINEVENTHOOK, event uint32, hwnd HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) uintptr
type (
HANDLE uintptr
HINSTANCE HANDLE
HHOOK HANDLE
HMODULE HANDLE
HWINEVENTHOOK HANDLE
DWORD uint32
INT int
WPARAM uintptr
LPARAM uintptr
LRESULT uintptr
HWND HANDLE
UINT uint32
BOOL int32
ULONG_PTR uintptr
LONG int32
LPWSTR *WCHAR
WCHAR uint16
)
type POINT struct {
X, Y int32
}
type MSG struct {
Hwnd HWND
Message uint32
WParam uintptr
LParam uintptr
Time uint32
Pt POINT
}
const (
//~ EVENT_SYSTEM_FOREGROUND DWORD = 0x0003
//~ WINEVENT_OUTOFCONTEXT DWORD = 0x0000
//~ WINEVENT_INCONTEXT = 0x0004
EVENT_SYSTEM_FOREGROUND = 3
WINEVENT_OUTOFCONTEXT = 0
WINEVENT_INCONTEXT = 4
WINEVENT_SKIPOWNPROCESS = 2
WINEVENT_SKIPOWNTHREAD = 1
)
func main() {
log.Println("starting")
hinst := GetModuleHandle("")
fmt.Println(hinst)
winEvHook := SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, 0 , ActiveWinEventHook, 0, 0, WINEVENT_OUTOFCONTEXT|WINEVENT_SKIPOWNPROCESS )
log.Println("Windows Event Hook: ")
log.Println("Windows Event Hook: ", winEvHook)
for {
var msg MSG
if m := GetMessage(&msg, 0, 0, 0); m != 0 {
TranslateMessage(&msg)
DispatchMessage(&msg)
}
}
UnhookWinEvent(winEvHook)
return
}
func SetWinEventHook(eventMin DWORD, eventMax DWORD, hmodWinEventProc HMODULE, pfnWinEventProc WINEVENTPROC, idProcess DWORD, idThread DWORD, dwFlags DWORD) HWINEVENTHOOK {
log.Println("procSetWinEventHook S")
ret, ret2 , err := procSetWinEventHook.Call(
uintptr(eventMin),
uintptr(eventMax),
uintptr(hmodWinEventProc),
pfnWinEventProcCallback,
uintptr(idProcess),
uintptr(idThread),
uintptr(dwFlags),
)
log.Printf("%#v", err)
log.Printf("%#v", ret)
log.Printf("%#v", ret2)
log.Println("procSetWinEventHook E")
return HWINEVENTHOOK(ret)
}
func UnhookWinEvent(hWinEventHook HWINEVENTHOOK) bool {
ret, _, _ := procUnhookWinEvent.Call(
uintptr(hWinEventHook),
)
return ret != 0
}
func GetModuleHandle(modulename string) HINSTANCE {
var mn uintptr
if modulename == "" {
mn = 0
} else {
mn = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(modulename)))
}
ret, _, _ := procGetModuleHandle.Call(mn)
return HINSTANCE(ret)
}
func GetMessage(msg *MSG, hwnd HWND, msgFilterMin UINT, msgFilterMax UINT) int {
ret, _, _ := procGetMessage.Call(
uintptr(unsafe.Pointer(msg)),
uintptr(hwnd),
uintptr(msgFilterMin),
uintptr(msgFilterMax))
return int(ret)
}
func TranslateMessage(msg *MSG) bool {
ret, _, _ := procTranslateMessage.Call(
uintptr(unsafe.Pointer(msg)))
return ret != 0
}
func DispatchMessage(msg *MSG) uintptr {
ret, _, _ := procDispatchMessage.Call(
uintptr(unsafe.Pointer(msg)))
return ret
}
So after research i noticed that
syscall.NewCallback() required an output value , for WinEventProc however from MSDN , the callback WinEventProc didn't return any value , so a "forced" a return value of type uintptr and worked perfectly.Like below code :
package main
import(
"fmt"
"syscall"
"unsafe"
"log"
"golang.org/x/sys/windows"
)
var(
user32 = windows.NewLazyDLL("user32.dll")
modkernel32 = windows.NewLazyDLL("kernel32.dll")
procSetWinEventHook = user32.NewProc("SetWinEventHook")
procUnhookWinEvent = user32.NewProc("UnhookWinEvent")
procGetMessage = user32.NewProc("GetMessageW")
procTranslateMessage = user32.NewProc("TranslateMessage")
procDispatchMessage = user32.NewProc("DispatchMessageW")
procGetModuleHandle = modkernel32.NewProc("GetModuleHandleW")
ActiveWinEventHook WINEVENTPROC = func (hWinEventHook HWINEVENTHOOK, event uint32, hwnd HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) uintptr {
log.Println("fond")
}
)
type WINEVENTPROC func(hWinEventHook HWINEVENTHOOK, event uint32, hwnd HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) uintptr
type (
HANDLE uintptr
HINSTANCE HANDLE
HHOOK HANDLE
HMODULE HANDLE
HWINEVENTHOOK HANDLE
DWORD uint32
INT int
WPARAM uintptr
LPARAM uintptr
LRESULT uintptr
HWND HANDLE
UINT uint32
BOOL int32
ULONG_PTR uintptr
LONG int32
LPWSTR *WCHAR
WCHAR uint16
)
type POINT struct {
X, Y int32
}
type MSG struct {
Hwnd HWND
Message uint32
WParam uintptr
LParam uintptr
Time uint32
Pt POINT
}
const (
//~ EVENT_SYSTEM_FOREGROUND DWORD = 0x0003
//~ WINEVENT_OUTOFCONTEXT DWORD = 0x0000
//~ WINEVENT_INCONTEXT = 0x0004
EVENT_SYSTEM_FOREGROUND = 3
WINEVENT_OUTOFCONTEXT = 0
WINEVENT_INCONTEXT = 4
WINEVENT_SKIPOWNPROCESS = 2
WINEVENT_SKIPOWNTHREAD = 1
)
func main() {
log.Println("starting")
hinst := GetModuleHandle("")
fmt.Println(hinst)
winEvHook := SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, 0 , ActiveWinEventHook, 0, 0, WINEVENT_OUTOFCONTEXT|WINEVENT_SKIPOWNPROCESS )
log.Println("Windows Event Hook: ")
log.Println("Windows Event Hook: ", winEvHook)
for {
var msg MSG
if m := GetMessage(&msg, 0, 0, 0); m != 0 {
TranslateMessage(&msg)
DispatchMessage(&msg)
}
}
UnhookWinEvent(winEvHook)
return
}
func SetWinEventHook(eventMin DWORD, eventMax DWORD, hmodWinEventProc HMODULE, pfnWinEventProc WINEVENTPROC, idProcess DWORD, idThread DWORD, dwFlags DWORD) HWINEVENTHOOK {
log.Println("procSetWinEventHook S")
pfnWinEventProcCallback := syscall.NewCallback(pfnWinEventProc)
ret, ret2 , err := procSetWinEventHook.Call(
uintptr(eventMin),
uintptr(eventMax),
uintptr(hmodWinEventProc),
pfnWinEventProcCallback,
uintptr(idProcess),
uintptr(idThread),
uintptr(dwFlags),
)
log.Printf("%#v", err)
log.Printf("%#v", ret)
log.Printf("%#v", ret2)
log.Println("procSetWinEventHook E")
return HWINEVENTHOOK(ret)
}
func UnhookWinEvent(hWinEventHook HWINEVENTHOOK) bool {
ret, _, _ := procUnhookWinEvent.Call(
uintptr(hWinEventHook),
)
return ret != 0
}
func GetModuleHandle(modulename string) HINSTANCE {
var mn uintptr
if modulename == "" {
mn = 0
} else {
mn = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(modulename)))
}
ret, _, _ := procGetModuleHandle.Call(mn)
return HINSTANCE(ret)
}
func GetMessage(msg *MSG, hwnd HWND, msgFilterMin UINT, msgFilterMax UINT) int {
ret, _, _ := procGetMessage.Call(
uintptr(unsafe.Pointer(msg)),
uintptr(hwnd),
uintptr(msgFilterMin),
uintptr(msgFilterMax))
return int(ret)
}
func TranslateMessage(msg *MSG) bool {
ret, _, _ := procTranslateMessage.Call(
uintptr(unsafe.Pointer(msg)))
return ret != 0
}
func DispatchMessage(msg *MSG) uintptr {
ret, _, _ := procDispatchMessage.Call(
uintptr(unsafe.Pointer(msg)))
return ret
}

how to use share memory with Golang? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
How does golang share or read other processes shared memory?
I've checked some information, but did not find relevant information. Can anyone give me an example?
In the world of go, don't communicate by sharing memory; share memory by communicating. If you really want to have a try, you can call the C API with cgo:
wrapper.c:
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/types.h>
int my_shm_open(char* filename, int open_flag){
int shm_id;
key_t key;
key = ftok(filename, 0x03);
if(key == -1){
return -1;
}
if(open_flag)
shm_id = shmget(key, 4096, IPC_CREAT|IPC_EXCL|0600);
else
shm_id = shmget(key, 0, 0);
if(shm_id == -1){
return -1;
}
return shm_id;
}
int my_shm_update(int shm_id, char* content){
char* addr;
addr = (char*)shmat(shm_id, NULL, 0);
if(addr == (char*)-1){
return -1;
}
if(strlen(content) > 4095)
return -1;
strcpy(addr, content);
shmdt(addr);
return 0;
}
int my_shm_close(int shm_id){
shmctl(shm_id, IPC_RMID, NULL);
return 0;
}
char* my_shm_read(char* filename){
int shm_id;
char* addr;
char* s;
shm_id = my_shm_open(filename, 0);
if(shm_id == -1)
return NULL;
addr = (char*)shmat(shm_id, NULL, 0);
if(addr == (char*)-1){
return NULL;
}
s = (char*)malloc(strlen(addr) + 1);
strcpy(s, addr);
shmdt(addr);
return s;
}
reader.go
package main
// #include <stdlib.h>
// #include "wrapper.c"
import "C"
import "unsafe"
import "fmt"
func read(filename string) string {
f := C.CString(filename)
defer C.free(unsafe.Pointer(f))
s := C.my_shm_read(f)
defer C.free(unsafe.Pointer(s))
return C.GoString(s)
}
func main() {
fmt.Println(read("/tmp"))
}
writter.go:
package main
// #include <stdlib.h>
// #include "wrapper.c"
import "C"
import "unsafe"
import (
"log"
"time"
)
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
func open(file string) (int, error) {
f := C.CString(file)
defer C.free(unsafe.Pointer(f))
r := int(C.my_shm_open(f, C.int(1)))
if r == -1 {
return 0, &errorString{"error"}
}
return r, nil
}
func update(shm_id int, content string) error {
c := C.CString(content)
defer C.free(unsafe.Pointer(c))
r := int(C.my_shm_update(C.int(shm_id), c))
if r == -1 {
return &errorString{"update error"}
}
return nil
}
func close(shm_id int) error {
C.my_shm_close(C.int(shm_id))
return nil
}
func main() {
id, err := open("/tmp")
if err != nil {
log.Fatal(err)
}
defer close(id)
err = update(id, "hello world")
if err != nil {
log.Fatal(err)
}
time.Sleep(1e9 * 100)
}
run the writer, then the reader by go run filename.
The code is from here
golang: It is a programming language, so it does not relate to the shared memory that the operating system level things. Not to say golang not use shared memory, but this is not it need to be defined. Posix use shared memory, you can use syscall package, which contains a lot of system calls, as long as the reference c system call interface on the line.

Is there a way to find a process id on windows in Go?

In OS package there is a FindProcess() that you can pass in the ID of the process to get a process. You can then call kill on the process but is there a way to find a process based off of the name? (In windows)
For example i would like to be able to do something like this.
p, perr := os.FindProcessByName("Itunes")
if perr != nil {
fmt.Println(perr)
}
p.Kill()
I only need this to work on Windows.
It's not pretty, but you can use the w32 binding: (github.com/AllenDang/w32)
package main
import (
"fmt"
"github.com/AllenDang/w32"
"unsafe"
)
func GetProcessName(id uint32) string {
snapshot := w32.CreateToolhelp32Snapshot(w32.TH32CS_SNAPMODULE, id)
if snapshot == w32.ERROR_INVALID_HANDLE {
return "<UNKNOWN>"
}
defer w32.CloseHandle(snapshot)
var me w32.MODULEENTRY32
me.Size = uint32(unsafe.Sizeof(me))
if w32.Module32First(snapshot, &me) {
return w32.UTF16PtrToString(&me.SzModule[0])
}
return "<UNKNOWN>"
}
func ListProcesses() []uint32 {
sz := uint32(1000)
procs := make([]uint32, sz)
var bytesReturned uint32
if w32.EnumProcesses(procs, sz, &bytesReturned) {
return procs[:int(bytesReturned)/4]
}
return []uint32{}
}
func FindProcessByName(name string) (uint32, error) {
for _, pid := range ListProcesses() {
if GetProcessName(pid) == name {
return pid, nil
}
}
return 0, fmt.Errorf("unknown process")
}
func main() {
fmt.Println(FindProcessByName("chrome.exe"))
}

Resources