-1

I used the answer here to add credentials programmatically to Windows Credential Manager. The code is inspired by the code in the answer. When I run it however, the credentials in the cred manager show up in Mandarin. I am not sure what am I doing wrong. Would appreciate any pointers. TIA .

For references this is the code I have

#include <iostream>
#include "windows.h"
#include "wincred.h"
#pragma hdrstop

using namespace std;

int main()
{
    const char* password = "testpass";
    CREDENTIALW creds = { 0 };
    creds.Type = CRED_TYPE_GENERIC;
    creds.TargetName = (LPWSTR)("testaccount");
    creds.CredentialBlobSize = strlen(password) + 1;
    creds.CredentialBlob = (LPBYTE)password;
    creds.Persist = CRED_PERSIST_LOCAL_MACHINE;
    creds.UserName = (LPWSTR)("testuser");

    BOOL result = CredWriteW(&creds, 0);

    if (result != TRUE)
    {
        cout << "Some error occurred" << endl;
    }
    else
    {
        cout << "Stored the password successfully" << endl;
    }
    return 0;
}

To ensure there is no default language problem, I manually created a credential from within the credential manager for test.com and had no problems with it. Snapshot of the Cred Manager -

enter image description here

harshc
  • 97
  • 7
  • Try [prefixing](https://learn.microsoft.com/de-de/cpp/cpp/string-and-character-literals-cpp?view=vs-2019) the string literals with `L`, e.g. `creds.TargetName = L"testaccount";`. The fact that a cast is necessary should be a giveaway that a wide string literal is needed, and that it won't work without one! – Erlkoenig Dec 19 '19 at 09:38
  • 1
    The fact that `TargetName` is not `const` might indicate that a mutable array is required, such as: `WCHAR targetName [] = L"testuser"; creds.TargetName = targetName;` – Erlkoenig Dec 19 '19 at 09:46
  • @Erlkoenig I started off with that but the intellisense started complaining type mismatch ("a value of type const wchar_t cannot be assigned to an entity of type LPWSTR") – harshc Dec 19 '19 at 09:54
  • Probably because it needs to be mutable. Try my second snippet. – Erlkoenig Dec 19 '19 at 09:55
  • That worked! Can you please add your comment as an answer so that I can mark it accordingly? Thank you @Erlkoenig! – harshc Dec 19 '19 at 10:00

1 Answers1

0

Appearantly, TargetName needs to refer to a mutable array, i.e. not a string literal. It also needs to be a wide string, or else the characters will be interpreted wrongly, in this case resulting in Chinese characters.

The solution is to define a mutable array that is initialized with a wide string, and have TargetName point to it:

WCHAR targetName [] = L"testuser";
creds.TargetName = targetName;

This way, no suspicious cast is needed to make it compile. When you want to input non-hardcoded strings (e.g. from user input or a file), you need to make sure they are correctly encoded and convert appropriately.

Erlkoenig
  • 2,664
  • 1
  • 9
  • 18