doushi7394 2016-03-09 07:27
浏览 87
已采纳

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

I'v been trying to play with netapi32.dll, but I'm having mixed results.

The following works as expected

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)
}

However, I'm not sure why info has to have & inside the unsafe.Pointer also.

The following does not work, and I can't seem to find out why. No error codes get thrown. Neither the struct or variables gets filled out.

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)
}
  • 写回答

1条回答 默认 最新

  • dou91808 2016-03-09 14:36
    关注

    …because you're not supposed to pass a pointer to your memory block there—to cite the manual:

    This buffer is allocated by the system and must be freed using the NetApiBufferFree function.

    The type of that pointer is misleading but you're supposed to pass a pointer to a pointer there, something like this:

    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.
    

    What happens here:

    1. The variable pinfo is a pointer to a value of type SESSION_INFO_10.

    2. You take the address of the memory block occupied by the value kept in that variable (which is a pointer) and pass it to NetSessionEnum().

    3. That function allocates the buffer by itself and writes its address to the memory block pointed to by the address you have passed to the function.

      Since you've passed an address of the pinfo variable, the address of the buffer ends up being written into the variable pinfo.

    4. You then use that address stored in pinfo to access the memory allocated by NetSessionEnum().

    That's called "double indirection" and is used in quite many places of Win32 API. Hope you got the idea.

    Please read the manual page carefully and study the code example it includes.

    Update: as it turned out, there were more problems with the original code so I've took time to provide full solution—here is the gist (tested with Go 1.6 amd64 and i386 on Windows XP 32-bit, Windows 2003 R2 64-bit and Windows 8.1 64-bit).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 解决一个加好友限制问题 或者有好的方案
  • ¥15 关于#java#的问题,请各位专家解答!
  • ¥15 急matlab编程仿真二阶震荡系统
  • ¥20 TEC-9的数据通路实验
  • ¥15 ue5 .3之前好好的现在只要是激活关卡就会崩溃
  • ¥50 MATLAB实现圆柱体容器内球形颗粒堆积
  • ¥15 python如何将动态的多个子列表,拼接后进行集合的交集
  • ¥20 vitis-ai量化基于pytorch框架下的yolov5模型
  • ¥15 如何实现H5在QQ平台上的二次分享卡片效果?
  • ¥30 求解达问题(有红包)