記事を書いたら、自己解決する法則でもあるのかなぁ。
// +build run package main import ( "fmt" "unsafe" "golang.org/x/sys/windows" ) const RESOURCE_CONNECTED = 1 const RESOURCE_CONTEXT = 5 const RESOURCE_GLOBALNET = 2 const RESOURCE_REMEMBERED = 3 const RESOURCETYPE_ANY = 0 const RESOURCETYPE_DISK = 1 const RESOURCETYPE_PRINT = 2 const RESOURCEDISPLAYTYPE_NETWORK = 6 const RESOURCEUSAGE_CONNECTABLE = 1 const RESOURCEUSAGE_CONTAINER = 2 const RESOURCEUSAGE_ATTACHED = 16 const RESOURCEUSAGE_ALL = 19 const ERROR_NO_MORE_ITEMS = 259 var mpr = windows.NewLazySystemDLL("mpr.dll") var procWNetOpenEnum = mpr.NewProc("WNetOpenEnumW") var procWNetEnumResource = mpr.NewProc("WNetEnumResourceW") var procWNetCloseEnum = mpr.NewProc("WNetCloseEnum") type netresourceT struct { Scope uint32 Type uint32 DisplayType uint32 Usage uint32 LocalName *uint16 RemoteName *uint16 Comment *uint16 Provider *uint16 } func u2str(u *uint16) string { if u == nil { return "" } buffer := make([]uint16, 0, 100) for *u != 0 { buffer = append(buffer, *u) u = (*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(u)) + 2)) } return windows.UTF16ToString(buffer) } func WNetEnum(nr *netresourceT, handler func(localName string, remoteName string)) error { var handle uintptr // localNameW,err := windows.UTF16PtrFromString("localhost") // if err != nil { // return err // } rc, _, err := procWNetOpenEnum.Call( RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, uintptr(unsafe.Pointer(nr)), uintptr(unsafe.Pointer(&handle))) if rc != windows.NO_ERROR { return fmt.Errorf("NetOpenEnum: %s", err) } defer procWNetCloseEnum.Call(handle) for { var buffer [16*1024]byte count := int32(-1) size := len(buffer) rc, _, err := procWNetEnumResource.Call( handle, uintptr(unsafe.Pointer(&count)), uintptr(unsafe.Pointer(&buffer[0])), uintptr(unsafe.Pointer(&size))) if rc == windows.NO_ERROR { println("open") for i := int32(0) ; i < count ; i++ { var p *netresourceT p = (*netresourceT)(unsafe.Pointer(&buffer[ uintptr(i)*unsafe.Sizeof(*p) ])) handler(u2str(p.LocalName), u2str(p.RemoteName)) WNetEnum(p,handler) } println("close") } else if rc == ERROR_NO_MORE_ITEMS { return nil } else { return fmt.Errorf("NetEnumResource: %s", err) } } } func main() { err := WNetEnum(nil,func(localName, remoteName string) { println(localName, " -> ", remoteName) }) if err != nil { println(err.Error()) } } // https://msdn.microsoft.com/ja-jp/library/cc447030.aspx // http://eternalwindows.jp/security/share/share06.html
要は再帰的に呼ばないとダメというわけですね
$ go run eachnetdrive_run.go open -> Microsoft Terminal Services -> Microsoft Windows Network open -> MICROSOFTACCOUNT -> WORKGROUP open -> \\ATERM-71C395 -> \\DESKTOP-LGGUCRA open -> \\DESKTOP-LGGUCRA\tmp close close close -> Web Client Network close