I try to integrate root certificate installation within my programm installer. I have to create an object from certificate and then add it to the store.
const std::string cert = R"cert(
-----BEGIN CERTIFICATE-----
/***/
-----END CERTIFICATE-----
)cert";
PCCERT_CONTEXT pCertCtx = NULL;
CRYPT_INTEGER_BLOB blob;
blob.pbData = (BYTE*)cert.c_str();
bool result = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
CERT_QUERY_CONTENT_FLAG_CERT,
CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED,
0, NULL, NULL, NULL, NULL, NULL, (const void**)&pCertCtx);
if (!result) {
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),
(LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return ERROR_INSTALL_FAILURE;
}
I make my own dll with this custom action and add this to WiX.
<Binary Id="pathFixer" SourceFile="$(var.product.inputFilesDir)\path-fixer.dll" />
<Binary Id="additionalActions" SourceFile="$(var.product.inputFilesDir)\additional-actions.dll" />
<CustomAction Id="SetNativeMessageHostPath" BinaryKey="pathFixer" DllEntry="SetNativeMessageHostPath" Execute="deferred" Impersonate="no"/>
<CustomAction Id="SetInstallDir" Property="SetNativeMessageHostPath" Value="[INSTALLDIR]" Execute="immediate" />
<CustomAction Id="installRootCert" BinaryKey="additionalActions" DllEntry="installRootCert" Execute="deferred" Impersonate="no"/>
<CustomAction Id="ResetOldVersionFound" Property="OTHER_VERSION_FOUND" Value="" Execute="immediate" />
<CustomAction Id="GetPerUserOldVersionFound" Property="USER_OTHER_VERSION_FOUND" Value="[OTHER_VERSION_FOUND]" Execute="immediate" />
<CustomAction Id="GetPerMachineOldVersionFound" Property="MACHINE_OTHER_VERSION_FOUND" Value="[OTHER_VERSION_FOUND]" Execute="immediate" />
<CustomAction Id="SetPerUserOldVersionToRemove" Property="OTHER_VERSION_FOUND" Value="[USER_OTHER_VERSION_FOUND]" Execute="immediate" />
<CustomAction Id="SetPerMachineOldVersionToRemove" Property="OTHER_VERSION_FOUND" Value="[MACHINE_OTHER_VERSION_FOUND]" Execute="immediate" />
<InstallExecuteSequence>
<Custom Action="SetPerUserOldVersionToRemove" Before="RemoveExistingProducts">MSIINSTALLPERUSER=1</Custom>
<Custom Action="SetPerMachineOldVersionToRemove" Before="RemoveExistingProducts">MSIINSTALLPERUSER=""</Custom>
<Custom Action="SetInstallDir" After="InstallInitialize"/>
<RemoveExistingProducts After="InstallInitialize" />
<InstallExecute After="RemoveExistingProducts" />
</InstallExecuteSequence>
<Media Id="1" Cabinet="$(var.project.name).cab" EmbedCab="yes" CompressionLevel="high" />
<CustomAction Id="SetPerUserFolder" Directory="APPLICATIONFOLDER" Value="[AppDataFolder]" Execute="immediate" />
<CustomAction Id="SetPerMachineFolder" Directory="APPLICATIONFOLDER" Value="[ProgramFilesFolder]" Execute="immediate" />
<InstallExecuteSequence>
<Custom Action="SetPerUserFolder" After="CostFinalize">NOT Installed AND MSIINSTALLPERUSER=1</Custom>
<Custom Action="SetPerMachineFolder" After="SetPerUserFolder">NOT Installed AND MSIINSTALLPERUSER=""</Custom>
<Custom Action="SetNativeMessageHostPath" After="PublishProduct">NOT REMOVE</Custom>
<Custom Action="installRootCert" After="PublishProduct">NOT REMOVE</Custom>
</InstallExecuteSequence>
Debuging says directly that due installing functions is executed. But with some magic operations like join MessageBox, Debuging, i take from CryptQueryObject
true
and false
periodcly, but not systematicly. GetLastError
says Parameter is incorrect
. Why could this happen?
I resolve it just adding the count, in bytes, of data, before call CryptQueryObject
.
blob.cbData = cert.length();
Be careful with struct data.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.