猿问

如何正确调用 netapi32!NetSessionEnum()?

我一直在尝试使用 netapi32.dll,但结果喜忧参半。


以下按预期工作


type SERVER_INFO_101 struct {

      PlatformID   uint32

      Name         *uint16

      VersionMajor uint32

      VersionMinor uint32

      Type         uint32

      Comment      *uint16

}



func NetServerGetInfo() {

      info := &SERVER_INFO_101{}

      ret, _, err := procNetServerGetInfo.Call(0, 101, uintptr(unsafe.Pointer(&info)))

      if ret != 0 {

              log.Fatal(err)

      }

      spew.Dump(info)

}

但是,我不确定为什么 info 也必须在 unsafe.Pointer 中包含 & 。


以下不起作用,我似乎无法找出原因。不会抛出错误代码。结构体或变量都不会被填充。


type SESSION_INFO_10 struct {

      Cname    *uint16

      Username *uint16

      Time     uint32

      IdleTime uint32

}


func NetSessionEnum() {

      info := &SESSION_INFO_10{}

      var prefmaxlen int32 = -1

      var entriesread uint32

      var totalentries uint32

      var resumehandle uint32

      x, y, z := procNetSessionEnum.Call(0, 0, 0, 10, uintptr(unsafe.Pointer(info)), uintptr(prefmaxlen), uintptr(unsafe.Pointer(&entriesread)), uintptr(unsafe.Pointer(&totalentries)), uintptr(unsafe.Pointer(&resumehandle)))

      fmt.Println(x, y, z)

      fmt.Println(entriesread, totalentries)

      spew.Dump(info)

}


千万里不及你
浏览 319回答 1
1回答

慕的地6264312

…因为你不应该在那里传递一个指向你的内存块的指针——引用手册:该缓冲区由系统分配,必须使用 NetApiBufferFree 函数释放。该指针的类型具有误导性,但您应该将指针传递给那里的指针,如下所示:func NetSessionEnum() {      var pinfo *SESSION_INFO_10      var prefmaxlen int32 = -1      var entriesread uint32      var totalentries uint32      var resumehandle uint32      x, y, z := procNetSessionEnum.Call(0, 0, 0, 10,          uintptr(unsafe.Pointer(&pinfo)), uintptr(prefmaxlen),          uintptr(unsafe.Pointer(&entriesread)),          uintptr(unsafe.Pointer(&totalentries)),          uintptr(unsafe.Pointer(&resumehandle)))      fmt.Println(x, y, z)      fmt.Println(entriesread, totalentries)      spew.Dump(info)}// Now use `*pinfo.Cname` etc// Don't forget to later call `NetApiBufferFree()` on that pointer.这里发生了什么:该变量pinfo是一个指向类型值的指针SESSION_INFO_10。您获取该变量(它是一个指针)中保存的值所占用的内存块的地址并将其传递给NetSessionEnum().该函数自行分配缓冲区并将其地址写入您传递给函数的地址所指向的内存块。由于您已经传递了pinfo变量的地址,因此缓冲区的地址最终会被写入变量中pinfo。然后,您可以使用存储在 中的地址pinfo来访问由 分配的内存NetSessionEnum()。这就是所谓的“双重间接”,在 Win32 API 的很多地方都有使用。请阅读手册页并研究其中包含的代码示例。更新:事实证明,原始代码存在更多问题,所以我花了一些时间来提供完整的解决方案——这里是要点(在 Windows XP 32 位、Windows 2003 R2 64 上使用 Go 1.6 amd64 和 i386 进行测试)位和 Windows 8.1 64 位)。
随时随地看视频慕课网APP

相关分类

Go
我要回答