func getWindowText(hwnd C.HWND) string { // WM_GETTEXTLENGTH and WM_GETTEXT return the count /without/ the terminating null character // but WM_GETTEXT expects the buffer size handed to it to /include/ the terminating null character n := C.getWindowTextLen(hwnd) buf := make([]uint16, int(n+1)) C.getWindowText(hwnd, C.WPARAM(n), C.LPWSTR(unsafe.Pointer(&buf[0]))) return syscall.UTF16ToString(buf) }
func (*keychainWindows) AddPassword(service, account, password string) error { // Validate input serviceValid := isValidNonNullUTF8(service) accountValid := isValidNonNullUTF8(account) passwordValid := isValidNonNullUTF8(password) if !(serviceValid && accountValid && passwordValid) { return ErrInvalidValue } // Compute target item name target := targetFormat(service, account) // Convert the target name. We require that inputs be in UTF-8, but even // then we can't use these using the Windows ANSI (A) APIs, so we have to // use the Unicode (W) APIs, but these all use UTF-16, we we need to // generate UTF-16 views of our strings. Fortunately, the Windows syscall // package has a nice API for doing this. targetUTF16Ptr, err := syscall.UTF16PtrFromString(target) if err != nil { return ErrInvalidValue } targetUTF16 := C.LPWSTR(unsafe.Pointer(targetUTF16Ptr)) // Convert the password blob. This is just stored as a raw array of bytes, // so we can store it UTF-8 encoded. passwordBlobSize := C.DWORD(len(password)) passwordVoidBlob := unsafe.Pointer(C.CString(password)) defer C.free(passwordVoidBlob) passwordBlob := C.LPBYTE(passwordVoidBlob) // Set up the credential var credential C.CREDENTIALW credential.Type = C.CRED_TYPE_GENERIC credential.TargetName = targetUTF16 credential.CredentialBlobSize = passwordBlobSize credential.CredentialBlob = passwordBlob credential.Persist = C.CRED_PERSIST_LOCAL_MACHINE // Store the credential if C.CredWriteW(&credential, 0) != C.TRUE { return ErrUnknown } // All done return nil }
func toUTF16(s string) C.LPWSTR { return C.LPWSTR(unsafe.Pointer(syscall.StringToUTF16Ptr(s))) }