diff --git a/CMakeLists.txt b/CMakeLists.txt index 7736c60..70927e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,13 @@ include(GNUInstallDirs) option(BUILD_WITH_QT4 "Build qtkeychain with Qt4 no matter if Qt5 was found" OFF) +if (WIN32) + option(USE_CREDENTIAL_STORE "Build with windows CredentialStore support" ON) + + if (USE_CREDENTIAL_STORE) + add_definitions(-DUSE_CREDENTIAL_STORE=1) + endif() +endif() if( NOT BUILD_WITH_QT4 ) # try Qt5 first, and prefer that if found diff --git a/keychain_win.cpp b/keychain_win.cpp index d5f0967..593dfca 100644 --- a/keychain_win.cpp +++ b/keychain_win.cpp @@ -17,6 +17,82 @@ using namespace QKeychain; +#if defined(USE_CREDENTIAL_STORE) +#include + +void ReadPasswordJobPrivate::scheduledStart() { + std::wstring name = key.toStdWString(); + //Use settings member if there, create local settings object if not + std::auto_ptr local( !q->settings() ? new QSettings( q->service() ) : 0 ); + PCREDENTIALW cred; + + if (!CredReadW(name.c_str(), CRED_TYPE_GENERIC, 0, &cred)) { + Error error; + QString msg; + switch(GetLastError()) { + case ERROR_NOT_FOUND: + error = EntryNotFound; + msg = tr("Password entry not found"); + break; + default: + error = OtherError; + msg = tr("Could not decrypt data"); + break; + } + + q->emitFinishedWithError( error, msg ); + return; + } + + data = QByteArray((char*)cred->CredentialBlob, cred->CredentialBlobSize); + CredFree(cred); + + q->emitFinished(); +} + +void WritePasswordJobPrivate::scheduledStart() { + CREDENTIALW cred; + char *pwd = data.data(); + std::wstring name = key.toStdWString(); + + memset(&cred, 0, sizeof(cred)); + cred.Comment = L"QtKeychain"; + cred.Type = CRED_TYPE_GENERIC; + cred.TargetName = (LPWSTR)name.c_str(); + cred.CredentialBlobSize = data.size(); + cred.CredentialBlob = (LPBYTE)pwd; + cred.Persist = CRED_PERSIST_LOCAL_MACHINE; + + if (!CredWriteW(&cred, 0)) { + q->emitFinishedWithError( OtherError, tr("Encryption failed") ); //TODO more details available? + } else { + q->emitFinished(); + } +} + +void DeletePasswordJobPrivate::scheduledStart() { + std::wstring name = key.toStdWString(); + + if (!CredDeleteW(name.c_str(), CRED_TYPE_GENERIC, 0)) { + Error error; + QString msg; + switch(GetLastError()) { + case ERROR_NOT_FOUND: + error = EntryNotFound; + msg = tr("Password entry not found"); + break; + default: + error = OtherError; + msg = tr("Could not decrypt data"); + break; + } + + q->emitFinishedWithError( error, msg ); + } else { + q->emitFinished(); + } +} +#else void ReadPasswordJobPrivate::scheduledStart() { //Use settings member if there, create local settings object if not std::auto_ptr local( !q->settings() ? new QSettings( q->service() ) : 0 ); @@ -103,3 +179,4 @@ void DeletePasswordJobPrivate::scheduledStart() { q->emitFinished(); } } +#endif