diff --git a/ChangeLog b/ChangeLog index 1dc18fec..b8e5ba3e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2019-06-22 Jay Berkenbilt + * Provided a more useful error message when Windows can't get + security context. Thanks to user zdenop for supplying some code. + Fixes #286. + * Favor PointerHolder over manual memory allocation in shippable code where possible. Fixes #235. diff --git a/libqpdf/SecureRandomDataProvider.cc b/libqpdf/SecureRandomDataProvider.cc index 6d40852a..86fb3752 100644 --- a/libqpdf/SecureRandomDataProvider.cc +++ b/libqpdf/SecureRandomDataProvider.cc @@ -62,18 +62,21 @@ class WindowsCryptProvider #endif { if (! CryptAcquireContext(&crypt_prov, - "Container", - NULL, - PROV_RSA_FULL, - CRYPT_NEWKEYSET)) + "Container", + NULL, + PROV_RSA_FULL, + CRYPT_NEWKEYSET)) { throw std::runtime_error( - "unable to acquire crypt context with new keyset"); + "unable to acquire crypt context with new keyset: " + + getErrorMessage()); } } else { - throw std::runtime_error("unable to acquire crypt context"); + throw std::runtime_error( + "unable to acquire crypt context: " + + getErrorMessage()); } } } @@ -84,6 +87,24 @@ class WindowsCryptProvider } HCRYPTPROV crypt_prov; + + private: + std::string getErrorMessage() + { + DWORD errorMessageID = ::GetLastError(); + LPSTR messageBuffer = nullptr; + size_t size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&messageBuffer), 0, NULL); + std::string message(messageBuffer, size); + LocalFree(messageBuffer); + return ("error number " + + QUtil::int_to_string_base(errorMessageID, 16) + + ": " + message); + } }; #endif