簡體   English   中英

在Go中調用EnumServicesStatusEx,內存分配?

[英]Calling EnumServicesStatusEx in Go, memory allocation?

我正在編寫一個與Windows服務中的Windows API交互的應用程序。

之后從@chowey幫助負載在這里 ,我有點得到的東西的竅門,並開始,我已經把在GitHub上一個基本庫在這里

現在,我轉到“服務”,要求列出計算機上的所有Windows服務,然后啟動,停止和重新啟動它們。 一旦可以使用服務句柄,啟動/停止/重新啟動就非常簡單了,但是我在努力獲取已安裝服務的列表。

我需要調用Advapi32.dll中的EnumServicesStatusEx ,但它需要一個指向ENUM_SERVICE_STATUS_PROCESS結構數組的預分配內存的指針。

您可以使用空指針調用該函數,它將返回所需的內存分配大小,但是我不相信有一種方法可以直接在Go中分配內存。

起初我以為我可以得到內存分配要求,使用不安全的包將其除以SizeOf結構,創建一個包含該數量元素的切片,然后將指向第一個元素的指針傳遞給函數,但它表示內存需要包含用於字符串數據的空間,而不會。

請問有人知道如何實現嗎? :)。

根據@alex的建議,我得到了以下示例代碼。

看起來我們創建了正確大小的字節片,然后使用unsafe類將其轉換為結構類型。

    _, _, _ = svcEnumServicesStatusEx.Call(
        uintptr(handle),
        uintptr(uint32(SVC_SC_ENUM_PROCESS_INFO)),
        uintptr(uint32(SVC_SERVICE_WIN32)),
        uintptr(uint32(SVC_SERVICE_STATE_ALL)),
        uintptr(0),
        0,
        uintptr(unsafe.Pointer(&bytesReq)),
        uintptr(unsafe.Pointer(&numReturned)),
        uintptr(unsafe.Pointer(&resumeHandle)),
        uintptr(0),
    )

    if bytesReq > 0 {
        var buf []byte = make([]byte, bytesReq)

        ret, _, _ := svcEnumServicesStatusEx.Call(
            uintptr(handle),
            uintptr(uint32(SVC_SC_ENUM_PROCESS_INFO)),
            uintptr(uint32(SVC_SERVICE_WIN32)),
            uintptr(uint32(SVC_SERVICE_STATE_ALL)),
            uintptr(unsafe.Pointer(&buf[0])),
            uintptr(bytesReq),
            uintptr(unsafe.Pointer(&bytesReq)),
            uintptr(unsafe.Pointer(&numReturned)),
            uintptr(unsafe.Pointer(&resumeHandle)),
            uintptr(0),
        )

        if ret > 0 {
            var sizeTest ENUM_SERVICE_STATUS_PROCESS
            iter := uintptr(unsafe.Pointer(&buf[0]))

            for i := uint32(0); i < numReturned; i++ {
                var data *ENUM_SERVICE_STATUS_PROCESS = (*ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(iter))

                fmt.Printf("Service Name: %s - Display Name: %s - %#v\r\n", syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(data.lpServiceName))[:]), syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(data.lpDisplayName))[:]), data.ServiceStatusProcess)

                iter = uintptr(unsafe.Pointer(iter + unsafe.Sizeof(sizeTest)))
            }
        } else {
            return nil, fmt.Errorf("Failed to get Service List even with allocated memory.")
        }
    } else {
        return nil, fmt.Errorf("Unable to get size of required memory allocation.")
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM