From 71e944e37af4d6a740e2cc4ae2987db77a41b9c4 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Fri, 23 Jan 2009 12:50:30 -0800 Subject: [PATCH] cryptui: Implement saving from the export wizard. --- dlls/cryptui/cryptui_En.rc | 2 + dlls/cryptui/cryptuires.h | 2 + dlls/cryptui/main.c | 176 ++++++++++++++++++++++++++++++++++++- 3 files changed, 179 insertions(+), 1 deletion(-) diff --git a/dlls/cryptui/cryptui_En.rc b/dlls/cryptui/cryptui_En.rc index 02dc5144bb8..d40d9c11244 100644 --- a/dlls/cryptui/cryptui_En.rc +++ b/dlls/cryptui/cryptui_En.rc @@ -158,6 +158,8 @@ STRINGTABLE DISCARDABLE IDS_EXPORT_KEYS "Export keys" IDS_YES "Yes" IDS_NO "No" + IDS_EXPORT_SUCCEEDED "The export was successful." + IDS_EXPORT_FAILED "The export failed." } IDD_GENERAL DIALOG DISCARDABLE 0, 0, 255, 236 diff --git a/dlls/cryptui/cryptuires.h b/dlls/cryptui/cryptuires.h index bf99375abde..7b8b4f2c975 100644 --- a/dlls/cryptui/cryptuires.h +++ b/dlls/cryptui/cryptuires.h @@ -157,6 +157,8 @@ #define IDS_EXPORT_KEYS 1214 #define IDS_YES 1215 #define IDS_NO 1216 +#define IDS_EXPORT_SUCCEEDED 1217 +#define IDS_EXPORT_FAILED 1218 #define IDD_GENERAL 100 #define IDD_DETAIL 101 diff --git a/dlls/cryptui/main.c b/dlls/cryptui/main.c index aaf69604c54..e473b4a57d1 100644 --- a/dlls/cryptui/main.c +++ b/dlls/cryptui/main.c @@ -5449,6 +5449,7 @@ struct ExportWizData BOOL deletePrivateKey; LPWSTR fileName; HANDLE file; + BOOL success; }; static LRESULT CALLBACK export_welcome_dlg_proc(HWND hwnd, UINT msg, WPARAM wp, @@ -5991,6 +5992,147 @@ static void show_export_details(HWND lv, struct ExportWizData *data) SendMessageW(lv, LVM_SETITEMTEXTW, item.iItem, (LPARAM)&item); } +static inline BOOL save_der(HANDLE file, const BYTE *pb, DWORD cb) +{ + DWORD bytesWritten; + + return WriteFile(file, pb, cb, &bytesWritten, NULL); +} + +static BOOL save_base64(HANDLE file, const BYTE *pb, DWORD cb) +{ + BOOL ret; + DWORD size = 0; + + if ((ret = CryptBinaryToStringA(pb, cb, CRYPT_STRING_BASE64, NULL, &size))) + { + LPSTR buf = HeapAlloc(GetProcessHeap(), 0, size); + + if (buf) + { + if ((ret = CryptBinaryToStringA(pb, cb, CRYPT_STRING_BASE64, buf, + &size))) + ret = WriteFile(file, buf, size, &size, NULL); + HeapFree(GetProcessHeap(), 0, buf); + } + else + { + SetLastError(ERROR_OUTOFMEMORY); + ret = FALSE; + } + } + return ret; +} + +static BOOL save_cms(HANDLE file, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo, + BOOL includeChain) +{ + BOOL ret; + HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, + CERT_STORE_CREATE_NEW_FLAG, NULL); + + if (store) + { + if (includeChain) + { + HCERTSTORE addlStore = CertOpenStore(CERT_STORE_PROV_COLLECTION, + 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); + + if (addlStore) + { + DWORD i; + + ret = TRUE; + for (i = 0; ret && i < pExportInfo->cStores; i++) + ret = CertAddStoreToCollection(addlStore, + pExportInfo->rghStores, 0, 0); + if (ret) + { + PCCERT_CHAIN_CONTEXT chain; + + ret = CertGetCertificateChain(NULL, + pExportInfo->u.pCertContext, NULL, addlStore, NULL, 0, + NULL, &chain); + if (ret) + { + DWORD j; + + for (i = 0; ret && i < chain->cChain; i++) + for (j = 0; ret && j < chain->rgpChain[i]->cElement; + j++) + ret = CertAddCertificateContextToStore(store, + chain->rgpChain[i]->rgpElement[j]->pCertContext, + CERT_STORE_ADD_ALWAYS, NULL); + CertFreeCertificateChain(chain); + } + else + { + /* No chain could be created, just add the individual + * cert to the message. + */ + ret = CertAddCertificateContextToStore(store, + pExportInfo->u.pCertContext, CERT_STORE_ADD_ALWAYS, + NULL); + } + } + CertCloseStore(addlStore, 0); + } + else + ret = FALSE; + } + else + ret = CertAddCertificateContextToStore(store, + pExportInfo->u.pCertContext, CERT_STORE_ADD_ALWAYS, NULL); + if (ret) + ret = CertSaveStore(store, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + CERT_STORE_SAVE_AS_PKCS7, CERT_STORE_SAVE_TO_FILE, file, 0); + CertCloseStore(store, 0); + } + else + ret = FALSE; + return ret; +} + +static BOOL do_export(struct ExportWizData *data) +{ + BOOL ret; + + switch (data->pExportInfo->dwSubjectChoice) + { + case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT: + ret = save_der(data->file, + data->pExportInfo->u.pCRLContext->pbCrlEncoded, + data->pExportInfo->u.pCRLContext->cbCrlEncoded); + break; + case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT: + ret = save_der(data->file, + data->pExportInfo->u.pCTLContext->pbCtlEncoded, + data->pExportInfo->u.pCTLContext->cbCtlEncoded); + break; + default: + switch (data->exportFormat) + { + case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64: + ret = save_base64(data->file, + data->pExportInfo->u.pCertContext->pbCertEncoded, + data->pExportInfo->u.pCertContext->cbCertEncoded); + break; + case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7: + ret = save_cms(data->file, data->pExportInfo, data->includeChain); + break; + case CRYPTUI_WIZ_EXPORT_FORMAT_PFX: + FIXME("unimplemented for PFX\n"); + ret = FALSE; + break; + default: + ret = save_der(data->file, + data->pExportInfo->u.pCertContext->pbCertEncoded, + data->pExportInfo->u.pCertContext->cbCertEncoded); + } + } + return ret; +} + static LRESULT CALLBACK export_finish_dlg_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { @@ -6036,6 +6178,37 @@ static LRESULT CALLBACK export_finish_dlg_proc(HWND hwnd, UINT msg, WPARAM wp, ret = TRUE; break; } + case PSN_WIZFINISH: + { + int messageID; + WCHAR title[MAX_STRING_LEN], message[MAX_STRING_LEN]; + LPCWSTR pTitle; + DWORD mbFlags; + + data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER); + if ((data->success = do_export(data))) + { + messageID = IDS_EXPORT_SUCCEEDED; + mbFlags = MB_OK; + } + else + { + messageID = IDS_EXPORT_FAILED; + mbFlags = MB_OK | MB_ICONERROR; + } + if (data->pwszWizardTitle) + pTitle = data->pwszWizardTitle; + else + { + LoadStringW(hInstance, IDS_EXPORT_WIZARD, title, + sizeof(title) / sizeof(title[0])); + pTitle = title; + } + LoadStringW(hInstance, messageID, message, + sizeof(message) / sizeof(message[0])); + MessageBoxW(hwnd, message, pTitle, mbFlags); + break; + } } break; } @@ -6062,6 +6235,7 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent, data.deletePrivateKey = FALSE; data.fileName = NULL; data.file = INVALID_HANDLE_VALUE; + data.success = FALSE; memset(&pages, 0, sizeof(pages)); @@ -6141,7 +6315,7 @@ static BOOL show_export_ui(DWORD dwFlags, HWND hwndParent, DeleteObject(data.titleFont); CloseHandle(data.file); HeapFree(GetProcessHeap(), 0, data.fileName); - return FALSE; + return data.success; } BOOL WINAPI CryptUIWizExport(DWORD dwFlags, HWND hwndParent,