AllenDang / w32

A wrapper of windows apis for the Go Programming Language.
Other
766 stars 247 forks source link

advapi32.RegSetString Not Setting Entire String #60

Open nogilnick opened 7 years ago

nogilnick commented 7 years ago

Hi,

First of all, thanks for the library.

It seems that there are a few bugs in the advapi32.RegSetString function. The result is that RegSetString will not write the correct amount of characters to the registry entry. See the below comments:

func RegSetString(hKey HKEY, subKey string, value string) (errno int) {
    var lptr, vptr unsafe.Pointer
    if len(subKey) > 0 {
        lptr = unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))
    }
    var buf []uint16
    //Is this size check needed? UTF16FromString always adds a null
    if len(value) > 0 {
        //New buf variable defined for if-statement scope
        buf, err := syscall.UTF16FromString(value)
        if err != nil {
            return ERROR_BAD_FORMAT
        }
        vptr = unsafe.Pointer(&buf[0])
    }
    //If you fmt.Println(buf) right here it is empty
    ret, _, _ := procRegSetValueEx.Call(
        uintptr(hKey),
        uintptr(lptr),
        uintptr(0),
        uintptr(REG_SZ),
        uintptr(vptr),
        //unsafe.Sizeof(buf) returns the size of the slice descriptor not the memory referenced
        //the slice descriptor is always of size 12 so this is always 14
        uintptr(unsafe.Sizeof(buf) + 2)) // 2 is the size of the terminating null character
    return int(ret)
}

I suggest changing to something more like this:

func RegSetString(hKey HKEY, subKey string, value string) (errno int) {
    var lptr, vptr unsafe.Pointer
    if len(subKey) > 0 {
        lptr = unsafe.Pointer(syscall.StringToUTF16Ptr(subKey))
    }
    buf, err := syscall.UTF16FromString(value)
    if err != nil {
        return ERROR_BAD_FORMAT
    }
    //Buf will at least containing 1 element (the null)
    vptr = unsafe.Pointer(&buf[0])
    ret, _, _ := procRegSetValueEx.Call(
        uintptr(hKey),
        uintptr(lptr),
        uintptr(0),
        uintptr(REG_SZ),
        uintptr(vptr),
        uintptr(int(unsafe.Sizeof(buf[0])) * len(buf))
    return int(ret)
}

Hope this helps,

N

gonutz commented 7 years ago

I found this bug as well, I fixed it in my pull request in this commit.