我试图使用win32 api通过IDiskQuotaControl接口获取IDiskQuotaControl接口中的卷的配额状态
我遇到的问题似乎与初始化有关。请看下面的代码。
//go:build windows && amd64
package main
import (
"flag"
"fmt"
"runtime"
"sync"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
// START OF basic stuff
const COINIT_APARTMENTTHREADED = 0x2
const CLSCTX_INPROC_SERVER = 0x1
const CLSCTX_INPROC_HANDLER = 0x2
const CLSCTX_LOCAL_SERVER = 0x4
var (
modole32 = syscall.NewLazyDLL("ole32.dll")
procCoInitializeEx = modole32.NewProc("CoInitializeEx")
procCoUninitialize = modole32.NewProc("CoUninitialize")
procCoCreateInstance = modole32.NewProc("CoCreateInstance")
)
func CoInitializeEx(pvReserved uintptr, dwCoInit uint32) (r1, r2 uintptr, lastErr error) {
r1, r2, lastErr = procCoInitializeEx.Call(
uintptr(pvReserved),
uintptr(dwCoInit),
)
return
}
func CoUninitialize() (r1, r2 uintptr, lastErr error) {
r1, r2, lastErr = procCoUninitialize.Call()
return
}
func CoCreateInstance(rclsid *GUID, pUnkOuter *byte, dwClsContext uint32, riid *GUID, ppv *uintptr) (r1, r2 uintptr, lastErr error) {
r1, r2, lastErr = procCoCreateInstance.Call(
uintptr(unsafe.Pointer(rclsid)),
uintptr(unsafe.Pointer(pUnkOuter)),
uintptr(dwClsContext),
uintptr(unsafe.Pointer(riid)),
uintptr(unsafe.Pointer(ppv)),
)
return
}
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
type IDiskQuotaControl struct {
lpVtbl *IDiskQuotaControlVtbl
}
type IDiskQuotaControlVtbl struct {
QueryInterface uintptr
AddRef uintptr
Release uintptr
Initialize uintptr
SetQuotaState uintptr
GetQuotaState uintptr
SetQuotaLogFlags uintptr
GetQuotaLogFlags uintptr
SetDefaultQuotaThreshold uintptr
GetDefaultQuotaThreshold uintptr
GetDefaultQuotaThresholdText uintptr
SetDefaultQuotaLimit uintptr
GetDefaultQuotaLimit uintptr
GetDefaultQuotaLimitText uintptr
AddUserSid uintptr
AddUserName uintptr
DeleteUser uintptr
FindUserSid uintptr
FindUserName uintptr
CreateEnumUsers uintptr
CreateUserBatch uintptr
InvalidateSidNameCache uintptr
GiveUserNameResolutionPriority uintptr
ShutdownNameResolution uintptr
}
func (x *IDiskQuotaControl) AddRef() (r1, r2 uintptr, lastErr error) {
r1, r2, lastErr = syscall.SyscallN(
x.lpVtbl.AddRef,
uintptr(unsafe.Pointer(x)),
)
return
}
func (x *IDiskQuotaControl) Release() (r1, r2 uintptr, lastErr error) {
r1, r2, lastErr = syscall.SyscallN(
x.lpVtbl.Release,
uintptr(unsafe.Pointer(x)),
)
return
}
func (x *IDiskQuotaControl) Initialize(pszPath *uint16, bReadWrite int32) (r1, r2 uintptr, lastErr error) {
r1, r2, lastErr = syscall.SyscallN(
x.lpVtbl.Initialize,
uintptr(unsafe.Pointer(x)),
uintptr(unsafe.Pointer(pszPath)),
uintptr(bReadWrite),
)
return
}
func (x *IDiskQuotaControl) GetQuotaState(pdwState *uint32) (r1, r2 uintptr, lastErr error) {
r1, r2, lastErr = syscall.SyscallN(
x.lpVtbl.GetQuotaState,
uintptr(unsafe.Pointer(x)),
uintptr(unsafe.Pointer(pdwState)),
)
return
}
func (x *IDiskQuotaControl) GetDefaultQuotaLimit(pllLimit *int64) (r1, r2 uintptr, lastErr error) {
r1, r2, lastErr = syscall.SyscallN(
x.lpVtbl.GetDefaultQuotaLimit,
uintptr(unsafe.Pointer(x)),
uintptr(unsafe.Pointer(pllLimit)),
)
return
}
var CLSID_DiskQuotaControl = &GUID{0x7988b571, 0xec89, 0x11cf, [8]byte{0x9c, 0x0, 0x0, 0xaa, 0x0, 0xa1, 0x4f, 0x56}}
var IID_IDiskQuotaControl = &GUID{0x7988b572, 0xec89, 0x11cf, [8]byte{0x9c, 0x0, 0x0, 0xaa, 0x0, 0xa1, 0x4f, 0x56}}
// END OF basic stuff
func getVolumeQuota(wg *sync.WaitGroup, volume string) {
defer wg.Done()
runtime.LockOSThread()
defer runtime.UnlockOSThread()
// Init COM
r1, r2, lastErr := CoInitializeEx(
0, // must be NULL
COINIT_APARTMENTTHREADED,
)
defer CoUninitialize()
fmt.Println("CoInitializeEx", r1, r2, lastErr) // Print results for debug
// Create a COM instance
var ppv uintptr
r1, r2, lastErr = CoCreateInstance(
CLSID_DiskQuotaControl,
nil,
CLSCTX_INPROC_SERVER,
IID_IDiskQuotaControl,
&ppv,
)
fmt.Println("CoCreateInstance", r1, r2, lastErr)
diskQuotaControl := (*IDiskQuotaControl)(unsafe.Pointer(ppv))
defer diskQuotaControl.Release()
pszPath, err := windows.UTF16PtrFromString(volume)
if err != nil {
panic(err)
}
// Initialize seems to fail even the return is a success
r1, r2, lastErr = diskQuotaControl.Initialize(
pszPath,
0, // false => read only
)
fmt.Println("Initialize", r1, r2, lastErr)
var pdwState uint32
r1, r2, lastErr = diskQuotaControl.GetQuotaState(
&pdwState,
)
fmt.Println("GetQuotaState", r1, r2, lastErr)
fmt.Println(pdwState)
var pllLimit int64
r1, r2, lastErr = diskQuotaControl.GetDefaultQuotaLimit(
&pllLimit,
)
fmt.Println("GetDefaultQuotaLimit", r1, r2, lastErr)
fmt.Println(pllLimit)
}
func main() {
volume := flag.String("v", `C:\`, "volume")
flag.Parse()
fmt.Println("Volume", *volume)
var wg sync.WaitGroup
wg.Add(1)
go getVolumeQuota(&wg, *volume)
wg.Wait()
}
我认为问题出现在Initialize中的原因是,无论我输入什么(使用标志-v),我都会得到成功的返回。
结果:
Volume C:\
CoInitializeEx 0 0 The operation completed successfully.
CoCreateInstance 0 0 The operation completed successfully.
Initialize 0 9298000 The operation completed successfully.
GetQuotaState 2147942403 9298000 The system cannot find the path specified.
0
GetDefaultQuotaLimit 2147942421 9298000 The operation completed successfully.
0
Volume \\?\C:\
CoInitializeEx 0 0 The operation completed successfully.
CoCreateInstance 0 0 The operation completed successfully.
Initialize 0 9103168 The operation completed successfully.
GetQuotaState 2147942403 9103168 The system cannot find the path specified.
0
GetDefaultQuotaLimit 2147942421 9103168 The operation completed successfully.
0
Volume Invalid:Volume://+
CoInitializeEx 0 0 The operation completed successfully.
CoCreateInstance 0 0 The operation completed successfully.
Initialize 0 8709600 The operation completed successfully.
GetQuotaState 2147942403 8709600 The system cannot find the path specified.
0
GetDefaultQuotaLimit 2147942421 8709600 The operation completed successfully.
0
GetDefaultQuotaLimit (2147942421 = 0x80070015)中的错误翻译为“未初始化此对象”
发布于 2022-09-22 08:04:47
IDiskQuotaControl接口继承自IUnknown接口。
这是错误的!IDiskQuotaControl
来自IConnectionPointContainer,而不是IUnknown
。你可以在dskquota.h中看到这一点
DECLARE_INTERFACE_IID_(IDiskQuotaControl, IConnectionPointContainer, "7988B572-EC89-11cf-9C00-00AA00A14F56")
因此,您的vtable定义是错误的,您必须在Release
和Initialize
方法之间添加两个方法。
https://stackoverflow.com/questions/73807191
复制相似问题