func (*keychainWindows) DeletePassword(service, account string) error { // Validate input serviceValid := isValidNonNullUTF8(service) accountValid := isValidNonNullUTF8(account) if !(serviceValid && accountValid) { return ErrInvalidValue } // Compute target item name target := targetFormat(service, account) // Convert the target name. See note in AddPassword. targetUTF16Ptr, err := syscall.UTF16PtrFromString(target) if err != nil { return ErrInvalidValue } // NOTE: For some reason they use LPCWSTR here, as opposed to LPWSTR in the // CREDENTIALW struct targetUTF16 := C.LPCWSTR(unsafe.Pointer(targetUTF16Ptr)) // Delete the credential if C.CredDeleteW(targetUTF16, C.CRED_TYPE_GENERIC, 0) != C.TRUE { return ErrUnknown } // All done return nil }
func (*keychainWindows) GetPassword(service, account string) (string, error) { // Validate input serviceValid := isValidNonNullUTF8(service) accountValid := isValidNonNullUTF8(account) if !(serviceValid && accountValid) { return "", ErrInvalidValue } // Compute target item name target := targetFormat(service, account) // Convert the target name. See note in AddPassword. targetUTF16Ptr, err := syscall.UTF16PtrFromString(target) if err != nil { return "", ErrInvalidValue } // NOTE: For some reason they use LPCWSTR here, as opposed to LPWSTR in the // CREDENTIALW struct targetUTF16 := C.LPCWSTR(unsafe.Pointer(targetUTF16Ptr)) // Query the credential var credential C.PCREDENTIALW if C.CredReadW(targetUTF16, C.CRED_TYPE_GENERIC, 0, &credential) != C.TRUE { return "", ErrNotFound } // Extract the password blob result := C.GoStringN( (*C.char)(unsafe.Pointer(credential.CredentialBlob)), C.int(credential.CredentialBlobSize), ) // Free the credential memory C.CredFree(C.PVOID(credential)) // All done return result, nil }
func utf16Convert(s string) (ptr C.LPCWSTR, length int) { encoded := utf16.Encode([]rune(s + "\x00")) return C.LPCWSTR((*C.WCHAR)(&encoded[0])), len(encoded) }