Author: dchapyshev
Date: Thu Feb 26 13:21:59 2009
New Revision: 39760
URL:
http://svn.reactos.org/svn/reactos?rev=39760&view=rev
Log:
- Sync crypt32 and cryptui with Wine head
Modified:
trunk/reactos/dll/win32/crypt32/chain.c
trunk/reactos/dll/win32/crypt32/crypt32_Ko.rc
trunk/reactos/dll/win32/cryptui/cryptui_En.rc
trunk/reactos/dll/win32/cryptui/cryptui_Ko.rc
trunk/reactos/dll/win32/cryptui/cryptuires.h
trunk/reactos/dll/win32/cryptui/main.c
Modified: trunk/reactos/dll/win32/crypt32/chain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/crypt32/chain.c?…
==============================================================================
--- trunk/reactos/dll/win32/crypt32/chain.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/crypt32/chain.c [iso-8859-1] Thu Feb 26 13:21:59 2009
@@ -28,6 +28,7 @@
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
+WINE_DECLARE_DEBUG_CHANNEL(chain);
#define DEFAULT_CYCLE_MODULUS 7
@@ -355,7 +356,7 @@
CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, (void *)root,
CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)root, 0, NULL))
{
- TRACE("Last certificate's signature is invalid\n");
+ TRACE_(chain)("Last certificate's signature is invalid\n");
rootElement->TrustStatus.dwErrorStatus |=
CERT_TRUST_IS_NOT_SIGNATURE_VALID;
}
@@ -411,8 +412,12 @@
}
/* Checks element's basic constraints to see if it can act as a CA, with
- * remainingCAs CAs left in this chain. Updates chainConstraints with the
- * element's constraints, if:
+ * remainingCAs CAs left in this chain. A root certificate is assumed to be
+ * allowed to be a CA whether or not the basic constraints extension is present,
+ * whereas an intermediate CA cert is not. This matches the expected usage in
+ * RFC 3280: a conforming intermediate CA MUST contain the basic constraints
+ * extension. It also appears to match Microsoft's implementation.
+ * Updates chainConstraints with the element's constraints, if:
* 1. chainConstraints doesn't have a path length constraint, or
* 2. element's path length constraint is smaller than chainConstraints's
* Sets *pathLengthConstraintViolated to TRUE if a path length violation
@@ -422,17 +427,17 @@
*/
static BOOL CRYPT_CheckBasicConstraintsForCA(PCCERT_CONTEXT cert,
CERT_BASIC_CONSTRAINTS2_INFO *chainConstraints, DWORD remainingCAs,
- BOOL *pathLengthConstraintViolated)
+ BOOL isRoot, BOOL *pathLengthConstraintViolated)
{
BOOL validBasicConstraints;
CERT_BASIC_CONSTRAINTS2_INFO constraints;
if ((validBasicConstraints = CRYPT_DecodeBasicConstraints(cert,
- &constraints, TRUE)))
+ &constraints, isRoot)))
{
if (!constraints.fCA)
{
- TRACE("chain element %d can't be a CA\n", remainingCAs + 1);
+ TRACE_(chain)("chain element %d can't be a CA\n", remainingCAs
+ 1);
validBasicConstraints = FALSE;
}
else if (constraints.fPathLenConstraint)
@@ -444,7 +449,7 @@
constraints.dwPathLenConstraint <
chainConstraints->dwPathLenConstraint)
{
- TRACE("setting path length constraint to %d\n",
+ TRACE_(chain)("setting path length constraint to %d\n",
chainConstraints->dwPathLenConstraint);
chainConstraints->fPathLenConstraint = TRUE;
chainConstraints->dwPathLenConstraint =
@@ -455,8 +460,8 @@
if (chainConstraints->fPathLenConstraint &&
remainingCAs > chainConstraints->dwPathLenConstraint)
{
- TRACE("remaining CAs %d exceed max path length %d\n", remainingCAs,
- chainConstraints->dwPathLenConstraint);
+ TRACE_(chain)("remaining CAs %d exceed max path length %d\n",
+ remainingCAs, chainConstraints->dwPathLenConstraint);
validBasicConstraints = FALSE;
*pathLengthConstraintViolated = TRUE;
}
@@ -709,6 +714,100 @@
}
}
+static void dump_basic_constraints(PCERT_EXTENSION ext)
+{
+ CERT_BASIC_CONSTRAINTS_INFO *info;
+ DWORD size = 0;
+
+ if (CryptDecodeObjectEx(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS,
+ ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG,
+ NULL, &info, &size))
+ {
+ TRACE_(chain)("SubjectType: %02x\n", info->SubjectType.pbData[0]);
+ TRACE_(chain)("%s path length constraint\n",
+ info->fPathLenConstraint ? "has" : "doesn't have");
+ TRACE_(chain)("path length=%d\n", info->dwPathLenConstraint);
+ LocalFree(info);
+ }
+}
+
+static void dump_basic_constraints2(PCERT_EXTENSION ext)
+{
+ CERT_BASIC_CONSTRAINTS2_INFO constraints;
+ DWORD size = sizeof(CERT_BASIC_CONSTRAINTS2_INFO);
+
+ if (CryptDecodeObjectEx(X509_ASN_ENCODING,
+ szOID_BASIC_CONSTRAINTS2, ext->Value.pbData, ext->Value.cbData,
+ 0, NULL, &constraints, &size))
+ {
+ TRACE_(chain)("basic constraints:\n");
+ TRACE_(chain)("can%s be a CA\n", constraints.fCA ? "" :
"not");
+ TRACE_(chain)("%s path length constraint\n",
+ constraints.fPathLenConstraint ? "has" : "doesn't
have");
+ TRACE_(chain)("path length=%d\n", constraints.dwPathLenConstraint);
+ }
+}
+
+static void dump_extension(PCERT_EXTENSION ext)
+{
+ TRACE_(chain)("%s (%scritical)\n", debugstr_a(ext->pszObjId),
+ ext->fCritical ? "" : "not ");
+ if (!strcmp(ext->pszObjId, szOID_BASIC_CONSTRAINTS))
+ dump_basic_constraints(ext);
+ else if (!strcmp(ext->pszObjId, szOID_BASIC_CONSTRAINTS2))
+ dump_basic_constraints2(ext);
+}
+
+static LPCWSTR filetime_to_str(const FILETIME *time)
+{
+ static WCHAR date[80];
+ WCHAR dateFmt[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
+ SYSTEMTIME sysTime;
+
+ if (!time) return NULL;
+
+ GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_SSHORTDATE, dateFmt,
+ sizeof(dateFmt) / sizeof(dateFmt[0]));
+ FileTimeToSystemTime(time, &sysTime);
+ GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, dateFmt, date,
+ sizeof(date) / sizeof(date[0]));
+ return date;
+}
+
+static void dump_element(PCCERT_CONTEXT cert)
+{
+ LPWSTR name = NULL;
+ DWORD len, i;
+
+ TRACE_(chain)("%p\n", cert);
+ len = CertGetNameStringW(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE,
+ CERT_NAME_ISSUER_FLAG, NULL, NULL, 0);
+ name = CryptMemAlloc(len * sizeof(WCHAR));
+ if (name)
+ {
+ CertGetNameStringW(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE,
+ CERT_NAME_ISSUER_FLAG, NULL, name, len);
+ TRACE_(chain)("issued by %s\n", debugstr_w(name));
+ CryptMemFree(name);
+ }
+ len = CertGetNameStringW(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL,
+ NULL, 0);
+ name = CryptMemAlloc(len * sizeof(WCHAR));
+ if (name)
+ {
+ CertGetNameStringW(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL,
+ name, len);
+ TRACE_(chain)("issued to %s\n", debugstr_w(name));
+ CryptMemFree(name);
+ }
+ TRACE_(chain)("valid from %s to %s\n",
+ debugstr_w(filetime_to_str(&cert->pCertInfo->NotBefore)),
+ debugstr_w(filetime_to_str(&cert->pCertInfo->NotAfter)));
+ TRACE_(chain)("%d extensions\n", cert->pCertInfo->cExtension);
+ for (i = 0; i < cert->pCertInfo->cExtension; i++)
+ dump_extension(&cert->pCertInfo->rgExtension[i]);
+}
+
static void CRYPT_CheckSimpleChain(PCertificateChainEngine engine,
PCERT_SIMPLE_CHAIN chain, LPFILETIME time)
{
@@ -717,14 +816,25 @@
BOOL pathLengthConstraintViolated = FALSE;
CERT_BASIC_CONSTRAINTS2_INFO constraints = { TRUE, FALSE, 0 };
+ TRACE_(chain)("checking chain with %d elements for time %s\n",
+ chain->cElement, debugstr_w(filetime_to_str(time)));
for (i = chain->cElement - 1; i >= 0; i--)
{
+ if (TRACE_ON(chain))
+ dump_element(chain->rgpElement[i]->pCertContext);
if (CertVerifyTimeValidity(time,
chain->rgpElement[i]->pCertContext->pCertInfo) != 0)
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_IS_NOT_TIME_VALID;
if (i != 0)
{
+ BOOL isRoot;
+
+ if (i == chain->cElement - 1)
+ isRoot = CRYPT_IsCertificateSelfSigned(
+ chain->rgpElement[i]->pCertContext);
+ else
+ isRoot = FALSE;
/* Check the signature of the cert this issued */
if (!CryptVerifyCertificateSignatureEx(0, X509_ASN_ENCODING,
CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT,
@@ -741,7 +851,7 @@
CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
else if (!CRYPT_CheckBasicConstraintsForCA(
chain->rgpElement[i]->pCertContext, &constraints, i - 1,
- &pathLengthConstraintViolated))
+ isRoot, &pathLengthConstraintViolated))
chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
CERT_TRUST_INVALID_BASIC_CONSTRAINTS;
else if (constraints.fPathLenConstraint &&
@@ -884,8 +994,7 @@
issuer = CertFindCertificateInStore(store,
subject->dwCertEncodingType, 0, CERT_FIND_SUBJECT_NAME,
&subject->pCertInfo->Issuer, prevIssuer);
- if (issuer)
- *infoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER;
+ *infoStatus = CERT_TRUST_HAS_NAME_MATCH_ISSUER;
}
return issuer;
}
@@ -902,12 +1011,13 @@
while (ret && !CRYPT_IsSimpleChainCyclic(chain) &&
!CRYPT_IsCertificateSelfSigned(cert))
{
- DWORD infoStatus;
- PCCERT_CONTEXT issuer = CRYPT_GetIssuer(world, cert, NULL, &infoStatus);
+ PCCERT_CONTEXT issuer = CRYPT_GetIssuer(world, cert, NULL,
+ &chain->rgpElement[chain->cElement -
1]->TrustStatus.dwInfoStatus);
if (issuer)
{
- ret = CRYPT_AddCertToSimpleChain(engine, chain, issuer, infoStatus);
+ ret = CRYPT_AddCertToSimpleChain(engine, chain, issuer,
+ chain->rgpElement[chain->cElement - 1]->TrustStatus.dwInfoStatus);
/* CRYPT_AddCertToSimpleChain add-ref's the issuer, so free it to
* close the enumeration that found it
*/
@@ -916,7 +1026,7 @@
}
else
{
- TRACE("Couldn't find issuer, halting chain creation\n");
+ TRACE_(chain)("Couldn't find issuer, halting chain
creation\n");
chain->TrustStatus.dwErrorStatus |= CERT_TRUST_IS_PARTIAL_CHAIN;
break;
}
Modified: trunk/reactos/dll/win32/crypt32/crypt32_Ko.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/crypt32/crypt32_…
==============================================================================
--- trunk/reactos/dll/win32/crypt32/crypt32_Ko.rc [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/crypt32/crypt32_Ko.rc [iso-8859-1] Thu Feb 26 13:21:59 2009
@@ -172,6 +172,7 @@
IDS_LOCALIZEDNAME_MY "°³ÀÎ"
IDS_LOCALIZEDNAME_CA "Áß°³ °ËÁõ ±â°ü"
IDS_LOCALIZEDNAME_ADDRESSBOOK "´Ù¸¥ »ç¶÷"
+ IDS_LOCALIZEDNAME_TRUSTEDPUBLISHER "½Å·ÚÇÒ ¼ö ÀÖ´Â ¹ßÇàÀÚ"
}
STRINGTABLE DISCARDABLE
Modified: trunk/reactos/dll/win32/cryptui/cryptui_En.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/cryptui/cryptui_…
==============================================================================
--- trunk/reactos/dll/win32/cryptui/cryptui_En.rc [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/cryptui/cryptui_En.rc [iso-8859-1] Thu Feb 26 13:21:59 2009
@@ -102,8 +102,8 @@
IDS_FRIENDLY_NAME_COLUMN "Friendly Name"
IDS_ALLOWED_PURPOSE_ALL "<All>"
IDS_ALLOWED_PURPOSE_NONE "<None>"
- IDS_WARN_REMOVE_MY "You will no longer be able to decrypt mesages with this
certificate, or sign messages with it.\nAre you sure you want to remove this
certificate?"
- IDS_WARN_REMOVE_PLURAL_MY "You will no longer be able to decrypt mesages with
these certificate, or sign messages with them.\nAre you sure you want to remove these
certificates?"
+ IDS_WARN_REMOVE_MY "You will no longer be able to decrypt messages with this
certificate, or sign messages with it.\nAre you sure you want to remove this
certificate?"
+ IDS_WARN_REMOVE_PLURAL_MY "You will no longer be able to decrypt messages with
these certificates, or sign messages with them.\nAre you sure you want to remove these
certificates?"
IDS_WARN_REMOVE_ADDRESSBOOK "You will no longer be able to encrypt messages with
this certificate, or verify messages signed with it.\nAre you sure you want to remove this
certificate?"
IDS_WARN_REMOVE_PLURAL_ADDRESSBOOK "You will no longer be able to encrypt
messages with these certificates, or verify messages signed with it.\nAre you sure you
want to remove these certificates?"
IDS_WARN_REMOVE_CA "Certificates issued by this certification authority will no
longer be trusted.\nAre you sure you want to remove this certificate?"
@@ -161,6 +161,13 @@
IDS_NO "No"
IDS_EXPORT_SUCCEEDED "The export was successful."
IDS_EXPORT_FAILED "The export failed."
+ IDS_EXPORT_PRIVATE_KEY_TITLE "Export Private Key"
+ IDS_EXPORT_PRIVATE_KEY_SUBTITLE "The certificate contains a private key which
may be exported along with the certificate."
+ IDS_EXPORT_PASSWORD_TITLE "Enter Password"
+ IDS_EXPORT_PASSWORD_SUBTITLE "You may password-protect a private key."
+ IDS_EXPORT_PASSWORD_MISMATCH "The passwords do not match."
+ IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE "Note: The private key for this certificate
could not be opened."
+ IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE "Note: The private key for this
certificate is not exportable."
}
IDD_GENERAL DIALOG DISCARDABLE 0, 0, 255, 236
@@ -379,6 +386,29 @@
-1, 115,56,195,40
LTEXT "To continue, click Next.",
-1, 115,103,195,8
+END
+
+IDD_EXPORT_PRIVATE_KEY DIALOG DISCARDABLE 0,0,317,143
+CAPTION "Certificate Export Wizard"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "If you choose to export the private key, you will be prompted for a
password to protect the private key on a later page.", -1, 21,1,195,23
+ LTEXT "Do you wish to export the private key?", -1, 21,24,195,15
+ AUTORADIOBUTTON "&Yes, export the private key",
+ IDC_EXPORT_PRIVATE_KEY_YES, 31,36,200,12, BS_AUTORADIOBUTTON|WS_TABSTOP
+ AUTORADIOBUTTON "N&o, do not export the private key",
+ IDC_EXPORT_PRIVATE_KEY_NO, 31,48,200,12, BS_AUTORADIOBUTTON
+ LTEXT "", IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE, 21,60,200,24
+END
+
+IDD_EXPORT_PASSWORD DIALOG DISCARDABLE 0,0,317,143
+CAPTION "Certificate Export Wizard"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "&Password:", -1, 21,1,195,10
+ EDITTEXT IDC_EXPORT_PASSWORD, 21,11,208,14, ES_AUTOHSCROLL|WS_TABSTOP
+ LTEXT "&Confirm password:", -1, 21,35,195,10
+ EDITTEXT IDC_EXPORT_PASSWORD_CONFIRM, 21,45,208,14, ES_AUTOHSCROLL|WS_TABSTOP
END
IDD_EXPORT_FORMAT DIALOG DISCARDABLE 0,0,317,143
Modified: trunk/reactos/dll/win32/cryptui/cryptui_Ko.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/cryptui/cryptui_…
==============================================================================
--- trunk/reactos/dll/win32/cryptui/cryptui_Ko.rc [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/cryptui/cryptui_Ko.rc [iso-8859-1] Thu Feb 26 13:21:59 2009
@@ -143,6 +143,34 @@
IDS_PURPOSE_CA_EXCHANGE "»çÀû Å° º¸°ü¼Ò"
IDS_PURPOSE_KEY_RECOVERY_AGENT "Å° º¹±¸ ¿¡ÀÌÀüÆ®"
IDS_PURPOSE_DS_EMAIL_REPLICATION "µð·ºÅ丮 ¼ºñ½º ÀüÀÚ¿ìÆí º¹Á¦"
+ IDS_EXPORT_WIZARD "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý»ç"
+ IDS_EXPORT_FORMAT_TITLE "³»º¸³¾ Çü½Ä"
+ IDS_EXPORT_FORMAT_SUBTITLE "³»¿ëÀ» ÀúÀåÇÒ Çü½Ä ¼±ÅÃ."
+ IDS_EXPORT_FILE_TITLE "³»º¸³¾ ÆÄÀÏÀ̸§"
+ IDS_EXPORT_FILE_SUBTITLE "³»¿ëÀ» ÀúÀåÇÒ ÆÄÀÏ À̸§ ÁöÁ¤."
+ IDS_EXPORT_FILE_EXISTS "ÁöÁ¤µÈ ÆÄÀÏÀº ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù.µ¤¾î ¾²½Ã°Ú½À´Ï±î?"
+ IDS_EXPORT_FILTER_CERT "DER-¾ÏÈ£ÈµÈ ¹ÙÀ̳ʸ® X.509 (*.cer)"
+ IDS_EXPORT_FILTER_BASE64_CERT "Base64-¾ÏÈ£ÈµÈ X.509 (*.cer)"
+ IDS_EXPORT_FILTER_CRL "ÀÎÁõ¼ Æó±â ¸ñ·Ï (*.crl)"
+ IDS_EXPORT_FILTER_CTL "ÀÎÁõ¼ ½Å·Ú ¸ñ·Ï (*.stl)"
+ IDS_EXPORT_FILTER_CMS "CMS/PKCS #7 ¸Þ¼¼Áö (*.p7b)"
+ IDS_EXPORT_FILTER_PFX "°³ÀÎ Á¤º¸ ±³È¯ (*.pfx)"
+ IDS_EXPORT_FILTER_SERIALIZED_CERT_STORE "³ª¿µÈ ÀÎÁõ¼ ÀúÀå¼Ò (*.sst)"
+ IDS_EXPORT_FORMAT "ÆÄÀÏ Çü½Ä"
+ IDS_EXPORT_INCLUDE_CHAIN "ÀÎÁõ °æ·Î¿¡ ÀÖ´Â ¸ðµç ÀÎÁõ¼ Æ÷ÇÔ"
+ IDS_EXPORT_KEYS "³»º¸³¾ Å°"
+ IDS_YES "¿¹"
+ IDS_NO "¾Æ´Ï¿À"
+ IDS_EXPORT_SUCCEEDED "³»º¸³»±â ¼º°ø."
+ IDS_EXPORT_FAILED "³»º¸³»±â ½ÇÆÐ."
+ IDS_EXPORT_PRIVATE_KEY_TITLE "³»º¸³¾ °³ÀÎ Å°"
+ IDS_EXPORT_PRIVATE_KEY_SUBTITLE "ÀÌ ÀÎÁõ¼´Â ÀÎÁõ¼¸¦ ³»º¸³¾ ¶§ °°ÀÌ ³ª°¥
°³ÀÎÅ°¸¦ Æ÷ÇÔÇÏ°í ÀÖ½À´Ï´Ù."
+ IDS_EXPORT_PASSWORD_TITLE "¾ÏÈ£ ÀÔ·Â"
+ IDS_EXPORT_PASSWORD_SUBTITLE "ÀÌ °³ÀÎÅ°´Â ¾Æ¸¶µµ ¾ÏÈ£·Î º¸È£µÇ¾îÀÖ´Â °Í
°°½À´Ï´Ù."
+ IDS_EXPORT_PASSWORD_MISMATCH "ÀÌ ¾ÏÈ£´Â ¸ÂÁö ¾Ê½À´Ï´Ù."
+ IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE "ÁÖÀÇ: ÀÌ ÀÎÁõ¼¸¦ À§ÇÑ °³ÀÎ Å°¸¦ ¿ ¼ö
¾ø½À´Ï´Ù."
+ IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE "ÁÖÀÇ: ÀÌ ÀÎÁõ¼¸¦ À§ÇÑ °³ÀÎ Å°¸¦ ³»º¸³¾
¼ö ¾ø½À´Ï´Ù."
+
}
IDD_GENERAL DIALOG DISCARDABLE 0, 0, 255, 236
@@ -330,3 +358,90 @@
PUSHBUTTON "È®ÀÎ", IDOK, 132,155,51,14, BS_DEFPUSHBUTTON
PUSHBUTTON "Ãë¼Ò", IDCANCEL, 190,155,51,14
END
+
+
+IDD_EXPORT_WELCOME DIALOG DISCARDABLE 0,0,317,143
+CAPTION "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý»ç"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý»ç¿¡ ¿À½Å °ÍÀ» ȯ¿µÇÕ´Ï´Ù", IDC_EXPORT_TITLE,
+ 115,1,195,40
+ LTEXT "ÀÌ ¸¶¹ý»ç´Â ÀÎÁõ¼,ÀÎÁõ¼ Æó±â ¸ñ·Ï,ÀÎÁõ¼ ½Å·Ú ¸ñ·ÏÀ» ÀÎÁõ¼ ÀúÀå¼Ò·ÎºÎÅÍ
ÆÄÀÏ·Î ³»º¸³»´Â °ÍÀ» µµ¿ÍÁÙ°Ì´Ï´Ù.",
+ -1, 115,33,195,16
+ LTEXT " ÀÎÁõ¼´Â ´ç½ÅÀ̳ª ´ç½ÅÀÌ Åë½Å¿¡ »ç¿ëÇÏ´Â ÄÄÇ»Å͸¦ ½Å¿øº¸ÁõÇÏ´Â µ¥
»ç¿ëµË´Ï´Ù. ¶ÇÇÑ ¸Þ¼¼Áö¿¡ »çÀÎÇÏ°í ÀÎÁõÇÏ´Â µ¥µµ »ç¿ëµË´Ï´Ù. ÀÎÁõ¼ º¸°ü¼Ò´Â ÀÎÁõ¼,
ÀÎÁõ¼ Æı⠸ñ·Ï, ÀÎÁõ¼ ½Å·Ú ¸ñ·ÏÀÇ ÀúÀå¼ÒÀÔ´Ï´Ù..",
+ -1, 115,56,195,40
+ LTEXT "°è¼Ó ÇϽǷÁ¸é, <´ÙÀ½>À» Ŭ¸¯ÇϽʽÿÀ.",
+ -1, 115,103,195,8
+END
+
+IDD_EXPORT_PRIVATE_KEY DIALOG DISCARDABLE 0,0,317,143
+CAPTION "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý»ç"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "´ç½ÅÀÌ °³ÀÎ Å°¸¦ ³»º¸³»±â¸¦ ¼±ÅÃÇϸé, ´ç½ÅÀº ´ÙÀ½ ÆäÀÌÁö¿¡¼ °³ÀÎ Å°¸¦
º¸È£ÇÒ ¾ÏÈ£¸¦ ÀÔ·ÂÇÏ°Ô µÉ °ÍÀÔ´Ï´Ù.", -1, 21,1,195,23
+ LTEXT "°³ÀÎ Å°¸¦ ³»º¸³»±â¸¦ ¿øÇմϱî?", -1, 21,24,195,15
+ AUTORADIOBUTTON "¿¹(&Y), °³ÀÎ Å° ³»º¸³»±â",
+ IDC_EXPORT_PRIVATE_KEY_YES, 31,36,200,12, BS_AUTORADIOBUTTON|WS_TABSTOP
+ AUTORADIOBUTTON "¾Æ´Ï¿À(&O), °³ÀÎ Å° ¾È ³»º¸³»±â",
+ IDC_EXPORT_PRIVATE_KEY_NO, 31,48,200,12, BS_AUTORADIOBUTTON
+ LTEXT "", IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE, 21,60,200,24
+END
+
+IDD_EXPORT_PASSWORD DIALOG DISCARDABLE 0,0,317,143
+CAPTION "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý»ç"
+FONT 8, "MS Shell Dlg"
+BEGIN
+LTEXT "¾ÏÈ£(&P):", -1, 21,1,195,10
+EDITTEXT IDC_EXPORT_PASSWORD, 21,11,208,14, ES_AUTOHSCROLL|WS_TABSTOP
+LTEXT "¾ÏÈ£ È®ÀÎ(&C):", -1, 21,35,195,10
+EDITTEXT IDC_EXPORT_PASSWORD_CONFIRM, 21,45,208,14, ES_AUTOHSCROLL|WS_TABSTOP
+END
+
+IDD_EXPORT_FORMAT DIALOG DISCARDABLE 0,0,317,143
+CAPTION "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý»ç"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "»ç¿ëÇÒ ÆÄÀÏ Çü½Ä ¼±ÅÃ:", -1, 21,1,195,10
+ AUTORADIOBUTTON "&DER-¾ÏÈ£ÈµÈ X.509 (.cer)",
+ IDC_EXPORT_FORMAT_DER, 31,18,200,12, BS_AUTORADIOBUTTON|WS_TABSTOP
+ AUTORADIOBUTTON "Ba&se64-¾ÏÈ£ÈµÈ X.509 (.cer):",
+ IDC_EXPORT_FORMAT_BASE64, 31,30,200,12, BS_AUTORADIOBUTTON
+ AUTORADIOBUTTON "¾ÏÈ£ ¸Þ½ÃÁö ¹®¹ý Ç¥ÁØ/PKCS #7 ¸Þ½ÃÁö(&C) (.p7b)",
+ IDC_EXPORT_FORMAT_CMS, 31,42,200,12, BS_AUTORADIOBUTTON
+ CHECKBOX "°¡´ÉÇÑ ÀÎÁõ¼ °æ·Î¿¡ ÀÖ´Â ¸ðµç ÀÎÁõ¼ Æ÷ÇÔ(&I)",
+ IDC_EXPORT_CMS_INCLUDE_CHAIN, 44,57,200,8, BS_AUTOCHECKBOX|WS_TABSTOP|WS_DISABLED
+ AUTORADIOBUTTON "°³ÀÎ Á¤º¸ ±³È¯(&P)/PKCS #12 (.pfx)",
+ IDC_EXPORT_FORMAT_PFX, 31,72,200,12, BS_AUTORADIOBUTTON|WS_DISABLED
+ CHECKBOX "°¡´ÉÇÑ ÀÎÁõ¼ °æ·Î¿¡ ÀÖ´Â ¸ðµç ÀÎÁõ¼ Æ÷ÇÔ(&U)",
+ IDC_EXPORT_PFX_INCLUDE_CHAIN, 44,87,200,8, BS_AUTOCHECKBOX|WS_TABSTOP|WS_DISABLED
+ CHECKBOX "°ÇÑ ¾ÏÈ£È °¡´É(&E)",
+ IDC_EXPORT_PFX_STRONG_ENCRYPTION, 44,102,200,8,
+ BS_AUTOCHECKBOX|WS_TABSTOP|WS_DISABLED
+ CHECKBOX "³»º¸³»±â°¡ ¼º°øÇÏ¸é °³ÀÎ Å° Áö¿ì±â(&K)",
+ IDC_EXPORT_PFX_DELETE_PRIVATE_KEY, 44,117,200,8,
+ BS_AUTOCHECKBOX|WS_TABSTOP|WS_DISABLED
+END
+
+IDD_EXPORT_FILE DIALOG DISCARDABLE 0,0,317,143
+CAPTION "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý»ç"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "ÆÄÀÏ À̸§(&F):", -1, 21,1,195,10
+ EDITTEXT IDC_EXPORT_FILENAME, 21,11,208,14, ES_AUTOHSCROLL|WS_TABSTOP
+ PUSHBUTTON "ã±â(&R)...", IDC_EXPORT_BROWSE_FILE, 236,11,60,14
+END
+
+IDD_EXPORT_FINISH DIALOG DISCARDABLE 0,0,317,143
+CAPTION "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý»ç"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý¼ ¿Ï·áÇÏ´Â Áß", IDC_EXPORT_TITLE,
+ 115,1,195,40
+ LTEXT "´ç½ÅÀº ÀÎÁõ¼ ³»º¸³»±â ¸¶¹ý¸¦ ¿Ï·áÇÏ´Â µ¥ ¼º°øÇÏ¿´½À´Ï´Ù.",
+ -1, 115,33,195,24
+ LTEXT "´ç½ÅÀº ´ÙÀ½ ¼³Á¤À» ÁöÁ¤Çß½À´Ï´Ù:",
+ -1, 115,57,195,12
+ CONTROL "", IDC_EXPORT_SETTINGS, "SysListView32",
+
LVS_REPORT|LVS_NOCOLUMNHEADER|LVS_SINGLESEL|WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER,
+ 115,67,174,100
+END
Modified: trunk/reactos/dll/win32/cryptui/cryptuires.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/cryptui/cryptuir…
==============================================================================
--- trunk/reactos/dll/win32/cryptui/cryptuires.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/cryptui/cryptuires.h [iso-8859-1] Thu Feb 26 13:21:59 2009
@@ -160,6 +160,13 @@
#define IDS_NO 1217
#define IDS_EXPORT_SUCCEEDED 1218
#define IDS_EXPORT_FAILED 1219
+#define IDS_EXPORT_PRIVATE_KEY_TITLE 1220
+#define IDS_EXPORT_PRIVATE_KEY_SUBTITLE 1221
+#define IDS_EXPORT_PASSWORD_TITLE 1222
+#define IDS_EXPORT_PASSWORD_SUBTITLE 1223
+#define IDS_EXPORT_PASSWORD_MISMATCH 1224
+#define IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE 1225
+#define IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE 1226
#define IDD_GENERAL 100
#define IDD_DETAIL 101
@@ -175,9 +182,11 @@
#define IDD_CERT_MGR 111
#define IDD_CERT_MGR_ADVANCED 112
#define IDD_EXPORT_WELCOME 113
-#define IDD_EXPORT_FORMAT 114
-#define IDD_EXPORT_FILE 115
-#define IDD_EXPORT_FINISH 116
+#define IDD_EXPORT_PRIVATE_KEY 114
+#define IDD_EXPORT_PASSWORD 115
+#define IDD_EXPORT_FORMAT 116
+#define IDD_EXPORT_FILE 117
+#define IDD_EXPORT_FINISH 118
#define IDB_SMALL_ICONS 200
#define IDB_CERT 201
@@ -253,5 +262,10 @@
#define IDC_EXPORT_FILENAME 2909
#define IDC_EXPORT_BROWSE_FILE 2910
#define IDC_EXPORT_SETTINGS 2911
+#define IDC_EXPORT_PRIVATE_KEY_YES 2912
+#define IDC_EXPORT_PRIVATE_KEY_NO 2913
+#define IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE 2914
+#define IDC_EXPORT_PASSWORD 2915
+#define IDC_EXPORT_PASSWORD_CONFIRM 2916
#endif /* ndef __CRYPTUIRES_H_ */
Modified: trunk/reactos/dll/win32/cryptui/main.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/cryptui/main.c?r…
==============================================================================
--- trunk/reactos/dll/win32/cryptui/main.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/cryptui/main.c [iso-8859-1] Thu Feb 26 13:21:59 2009
@@ -1076,25 +1076,24 @@
HWND tab = GetDlgItem(hwnd, IDC_MGR_STORES);
data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CertMgrData));
- if (data)
- {
- data->imageList = ImageList_Create(16, 16, ILC_COLOR4 | ILC_MASK,
- 2, 0);
- if (data->imageList)
- {
- HBITMAP bmp;
- COLORREF backColor = RGB(255, 0, 255);
-
- bmp = LoadBitmapW(hInstance, MAKEINTRESOURCEW(IDB_SMALL_ICONS));
- ImageList_AddMasked(data->imageList, bmp, backColor);
- DeleteObject(bmp);
- ImageList_SetBkColor(data->imageList, CLR_NONE);
- SendMessageW(GetDlgItem(hwnd, IDC_MGR_CERTS), LVM_SETIMAGELIST,
- LVSIL_SMALL, (LPARAM)data->imageList);
- }
- SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
- data->title = pCryptUICertMgr->pwszTitle;
- }
+ if (!data)
+ return 0;
+ data->imageList = ImageList_Create(16, 16, ILC_COLOR4 | ILC_MASK, 2, 0);
+ if (data->imageList)
+ {
+ HBITMAP bmp;
+ COLORREF backColor = RGB(255, 0, 255);
+
+ bmp = LoadBitmapW(hInstance, MAKEINTRESOURCEW(IDB_SMALL_ICONS));
+ ImageList_AddMasked(data->imageList, bmp, backColor);
+ DeleteObject(bmp);
+ ImageList_SetBkColor(data->imageList, CLR_NONE);
+ SendMessageW(GetDlgItem(hwnd, IDC_MGR_CERTS), LVM_SETIMAGELIST,
+ LVSIL_SMALL, (LPARAM)data->imageList);
+ }
+ SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
+ data->title = pCryptUICertMgr->pwszTitle;
+
initialize_purpose_selection(hwnd);
add_cert_columns(hwnd);
if (pCryptUICertMgr->pwszTitle)
@@ -5516,8 +5515,11 @@
HFONT titleFont;
DWORD dwFlags;
LPCWSTR pwszWizardTitle;
- PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo;
+ CRYPTUI_WIZ_EXPORT_INFO exportInfo;
CRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO contextInfo;
+ BOOL freePassword;
+ PCRYPT_KEY_PROV_INFO keyProvInfo;
+ BOOL deleteKeys;
LPWSTR fileName;
HANDLE file;
BOOL success;
@@ -5567,6 +5569,141 @@
return ret;
}
+static PCRYPT_KEY_PROV_INFO export_get_private_key_info(PCCERT_CONTEXT cert)
+{
+ PCRYPT_KEY_PROV_INFO info = NULL;
+ DWORD size;
+
+ if (CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID,
+ NULL, &size))
+ {
+ info = HeapAlloc(GetProcessHeap(), 0, size);
+ if (info)
+ {
+ if (!CertGetCertificateContextProperty(cert,
+ CERT_KEY_PROV_INFO_PROP_ID, info, &size))
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ info = NULL;
+ }
+ }
+ }
+ return info;
+}
+
+static BOOL export_acquire_private_key(PCRYPT_KEY_PROV_INFO info,
+ HCRYPTPROV *phProv)
+{
+ BOOL ret;
+
+ ret = CryptAcquireContextW(phProv, info->pwszContainerName,
+ info->pwszProvName, info->dwProvType, 0);
+ if (ret)
+ {
+ DWORD i;
+
+ for (i = 0; i < info->cProvParam; i++)
+ CryptSetProvParam(*phProv, info->rgProvParam[i].dwParam,
+ info->rgProvParam[i].pbData, info->rgProvParam[i].dwFlags);
+ }
+ return ret;
+}
+
+static BOOL export_is_key_exportable(HCRYPTPROV hProv, DWORD keySpec)
+{
+ BOOL ret;
+ HCRYPTKEY key;
+
+ if ((ret = CryptGetUserKey(hProv, keySpec, &key)))
+ {
+ DWORD permissions, size = sizeof(permissions);
+
+ if ((ret = CryptGetKeyParam(key, KP_PERMISSIONS, (BYTE *)&permissions,
+ &size, 0)) && !(permissions & CRYPT_EXPORT))
+ ret = FALSE;
+ CryptDestroyKey(key);
+ }
+ return ret;
+}
+
+static LRESULT CALLBACK export_private_key_dlg_proc(HWND hwnd, UINT msg,
+ WPARAM wp, LPARAM lp)
+{
+ LRESULT ret = 0;
+ struct ExportWizData *data;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lp;
+ PCRYPT_KEY_PROV_INFO info;
+ HCRYPTPROV hProv = 0;
+ int errorID = 0;
+
+ data = (struct ExportWizData *)page->lParam;
+ SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
+ /* Get enough information about a key to see whether it's exportable.
+ */
+ if (!(info = export_get_private_key_info(
+ data->exportInfo.u.pCertContext)))
+ errorID = IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE;
+ else if (!export_acquire_private_key(info, &hProv))
+ errorID = IDS_EXPORT_PRIVATE_KEY_UNAVAILABLE;
+ else if (!export_is_key_exportable(hProv, info->dwKeySpec))
+ errorID = IDS_EXPORT_PRIVATE_KEY_NON_EXPORTABLE;
+
+ if (errorID)
+ {
+ WCHAR error[MAX_STRING_LEN];
+
+ LoadStringW(hInstance, errorID, error,
+ sizeof(error) / sizeof(error[0]));
+ SendMessageW(GetDlgItem(hwnd, IDC_EXPORT_PRIVATE_KEY_UNAVAILABLE),
+ WM_SETTEXT, 0, (LPARAM)error);
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_PRIVATE_KEY_YES), FALSE);
+ }
+ else
+ data->keyProvInfo = info;
+ if (hProv)
+ CryptReleaseContext(hProv, 0);
+ SendMessageW(GetDlgItem(hwnd, IDC_EXPORT_PRIVATE_KEY_NO), BM_CLICK,
+ 0, 0);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ NMHDR *hdr = (NMHDR *)lp;
+
+ switch (hdr->code)
+ {
+ case PSN_SETACTIVE:
+ PostMessageW(GetParent(hwnd), PSM_SETWIZBUTTONS, 0,
+ PSWIZB_BACK | PSWIZB_NEXT);
+ ret = TRUE;
+ break;
+ case PSN_WIZNEXT:
+ data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
+ if (IsDlgButtonChecked(hwnd, IDC_EXPORT_PRIVATE_KEY_NO))
+ {
+ data->contextInfo.dwExportFormat =
+ CRYPTUI_WIZ_EXPORT_FORMAT_DER;
+ data->contextInfo.fExportPrivateKeys = FALSE;
+ }
+ else
+ {
+ data->contextInfo.dwExportFormat =
+ CRYPTUI_WIZ_EXPORT_FORMAT_PFX;
+ data->contextInfo.fExportPrivateKeys = TRUE;
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return ret;
+}
+
static BOOL export_info_has_private_key(PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo)
{
BOOL ret = FALSE;
@@ -5585,6 +5722,41 @@
return ret;
}
+static void export_format_enable_controls(HWND hwnd, struct ExportWizData *data)
+{
+ int defaultFormatID;
+
+ switch (data->contextInfo.dwExportFormat)
+ {
+ case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64:
+ defaultFormatID = IDC_EXPORT_FORMAT_BASE64;
+ break;
+ case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7:
+ defaultFormatID = IDC_EXPORT_FORMAT_CMS;
+ break;
+ case CRYPTUI_WIZ_EXPORT_FORMAT_PFX:
+ defaultFormatID = IDC_EXPORT_FORMAT_PFX;
+ break;
+ default:
+ defaultFormatID = IDC_EXPORT_FORMAT_DER;
+ }
+ SendMessageW(GetDlgItem(hwnd, defaultFormatID), BM_CLICK, 0, 0);
+ if (defaultFormatID == IDC_EXPORT_FORMAT_PFX)
+ {
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_DER), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_BASE64), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_CMS), FALSE);
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_PFX), TRUE);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_DER), TRUE);
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_BASE64), TRUE);
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_CMS), TRUE);
+ EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_PFX), FALSE);
+ }
+}
+
static LRESULT CALLBACK export_format_dlg_proc(HWND hwnd, UINT msg, WPARAM wp,
LPARAM lp)
{
@@ -5596,32 +5768,10 @@
case WM_INITDIALOG:
{
PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lp;
- int defaultFormatID;
- BOOL hasPrivateKey;
data = (struct ExportWizData *)page->lParam;
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
- hasPrivateKey = export_info_has_private_key(data->pExportInfo);
- if (hasPrivateKey)
- EnableWindow(GetDlgItem(hwnd, IDC_EXPORT_FORMAT_PFX), TRUE);
- switch (data->contextInfo.dwExportFormat)
- {
- case CRYPTUI_WIZ_EXPORT_FORMAT_BASE64:
- defaultFormatID = IDC_EXPORT_FORMAT_BASE64;
- break;
- case CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7:
- defaultFormatID = IDC_EXPORT_FORMAT_CMS;
- break;
- case CRYPTUI_WIZ_EXPORT_FORMAT_PFX:
- if (hasPrivateKey)
- defaultFormatID = IDC_EXPORT_FORMAT_PFX;
- else
- defaultFormatID = IDC_EXPORT_FORMAT_DER;
- break;
- default:
- defaultFormatID = IDC_EXPORT_FORMAT_DER;
- }
- SendMessageW(GetDlgItem(hwnd, defaultFormatID), BM_CLICK, 0, 0);
+ export_format_enable_controls(hwnd, data);
break;
}
case WM_NOTIFY:
@@ -5633,10 +5783,14 @@
case PSN_SETACTIVE:
PostMessageW(GetParent(hwnd), PSM_SETWIZBUTTONS, 0,
PSWIZB_BACK | PSWIZB_NEXT);
+ data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
+ export_format_enable_controls(hwnd, data);
ret = TRUE;
break;
case PSN_WIZNEXT:
{
+ BOOL skipPasswordPage = TRUE;
+
data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
if (IsDlgButtonChecked(hwnd, IDC_EXPORT_FORMAT_DER))
data->contextInfo.dwExportFormat =
@@ -5661,8 +5815,12 @@
if (IsDlgButtonChecked(hwnd, IDC_EXPORT_PFX_STRONG_ENCRYPTION))
data->contextInfo.fStrongEncryption = TRUE;
if (IsDlgButtonChecked(hwnd, IDC_EXPORT_PFX_DELETE_PRIVATE_KEY))
- data->contextInfo.fExportPrivateKeys = TRUE;
+ data->deleteKeys = TRUE;
+ skipPasswordPage = FALSE;
}
+ SetWindowLongPtrW(hwnd, DWLP_MSGRESULT,
+ skipPasswordPage ? IDD_EXPORT_FILE : 0);
+ ret = 1;
break;
}
}
@@ -5705,6 +5863,111 @@
return ret;
}
+static void export_password_mismatch(HWND hwnd, struct ExportWizData *data)
+{
+ WCHAR title[MAX_STRING_LEN], error[MAX_STRING_LEN];
+ LPCWSTR pTitle;
+
+ if (data->pwszWizardTitle)
+ pTitle = data->pwszWizardTitle;
+ else
+ {
+ LoadStringW(hInstance, IDS_EXPORT_WIZARD, title,
+ sizeof(title) / sizeof(title[0]));
+ pTitle = title;
+ }
+ LoadStringW(hInstance, IDS_EXPORT_PASSWORD_MISMATCH, error,
+ sizeof(error) / sizeof(error[0]));
+ MessageBoxW(hwnd, error, pTitle, MB_ICONERROR | MB_OK);
+ SetFocus(GetDlgItem(hwnd, IDC_EXPORT_PASSWORD));
+}
+
+static LRESULT CALLBACK export_password_dlg_proc(HWND hwnd, UINT msg,
+ WPARAM wp, LPARAM lp)
+{
+ LRESULT ret = 0;
+ struct ExportWizData *data;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ PROPSHEETPAGEW *page = (PROPSHEETPAGEW *)lp;
+
+ data = (struct ExportWizData *)page->lParam;
+ SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ NMHDR *hdr = (NMHDR *)lp;
+
+ switch (hdr->code)
+ {
+ case PSN_SETACTIVE:
+ PostMessageW(GetParent(hwnd), PSM_SETWIZBUTTONS, 0,
+ PSWIZB_BACK | PSWIZB_NEXT);
+ ret = TRUE;
+ break;
+ case PSN_WIZNEXT:
+ {
+ HWND passwordEdit = GetDlgItem(hwnd, IDC_EXPORT_PASSWORD);
+ HWND passwordConfirmEdit = GetDlgItem(hwnd,
+ IDC_EXPORT_PASSWORD_CONFIRM);
+ DWORD passwordLen = SendMessageW(passwordEdit, WM_GETTEXTLENGTH,
+ 0, 0);
+ DWORD passwordConfirmLen = SendMessageW(passwordConfirmEdit,
+ WM_GETTEXTLENGTH, 0, 0);
+
+ data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
+ if (!passwordLen && !passwordConfirmLen)
+ data->contextInfo.pwszPassword = NULL;
+ else if (passwordLen != passwordConfirmLen)
+ {
+ export_password_mismatch(hwnd, data);
+ SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, 1);
+ ret = 1;
+ }
+ else
+ {
+ LPWSTR password = HeapAlloc(GetProcessHeap(), 0,
+ (passwordLen + 1) * sizeof(WCHAR));
+ LPWSTR passwordConfirm = HeapAlloc(GetProcessHeap(), 0,
+ (passwordConfirmLen + 1) * sizeof(WCHAR));
+ BOOL freePassword = TRUE;
+
+ if (password && passwordConfirm)
+ {
+ SendMessageW(passwordEdit, WM_GETTEXT, passwordLen + 1,
+ (LPARAM)password);
+ SendMessageW(passwordConfirmEdit, WM_GETTEXT,
+ passwordConfirmLen + 1, (LPARAM)passwordConfirm);
+ if (strcmpW(password, passwordConfirm))
+ {
+ export_password_mismatch(hwnd, data);
+ SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, 1);
+ ret = 1;
+ }
+ else
+ {
+ data->contextInfo.pwszPassword = password;
+ freePassword = FALSE;
+ data->freePassword = TRUE;
+ }
+ }
+ if (freePassword)
+ HeapFree(GetProcessHeap(), 0, password);
+ HeapFree(GetProcessHeap(), 0, passwordConfirm);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ return ret;
+}
+
static LPWSTR export_append_extension(struct ExportWizData *data,
LPWSTR fileName)
{
@@ -5727,7 +5990,7 @@
extension = pfx;
break;
default:
- switch (data->pExportInfo->dwSubjectChoice)
+ switch (data->exportInfo.dwSubjectChoice)
{
case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT:
extension = crl;
@@ -5926,9 +6189,9 @@
data = (struct ExportWizData *)page->lParam;
SetWindowLongPtrW(hwnd, DWLP_USER, (LPARAM)data);
- if (data->pExportInfo->pwszExportFileName)
+ if (data->exportInfo.pwszExportFileName)
SendMessageW(GetDlgItem(hwnd, IDC_EXPORT_FILENAME), WM_SETTEXT, 0,
- (LPARAM)data->pExportInfo->pwszExportFileName);
+ (LPARAM)data->exportInfo.pwszExportFileName);
break;
}
case WM_NOTIFY:
@@ -5937,6 +6200,15 @@
switch (hdr->code)
{
+ case PSN_WIZBACK:
+ data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
+ if (data->contextInfo.dwExportFormat !=
+ CRYPTUI_WIZ_EXPORT_FORMAT_PFX)
+ {
+ SetWindowLongPtrW(hwnd, DWLP_MSGRESULT, IDD_EXPORT_FORMAT);
+ ret = 1;
+ }
+ break;
case PSN_WIZNEXT:
{
HWND fileNameEdit = GetDlgItem(hwnd, IDC_EXPORT_FILENAME);
@@ -6006,7 +6278,7 @@
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = make_export_file_filter(
data->contextInfo.dwExportFormat,
- data->pExportInfo->dwSubjectChoice);
+ data->exportInfo.dwSubjectChoice);
ofn.lpstrFile = fileBuf;
ofn.nMaxFile = sizeof(fileBuf) / sizeof(fileBuf[0]);
fileBuf[0] = 0;
@@ -6043,7 +6315,7 @@
}
item.pszText = text;
- switch (data->pExportInfo->dwSubjectChoice)
+ switch (data->exportInfo.dwSubjectChoice)
{
case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT:
case CRYPTUI_WIZ_EXPORT_CTL_CONTEXT:
@@ -6084,7 +6356,7 @@
SendMessageW(lv, LVM_INSERTITEMW, 0, (LPARAM)&item);
item.iSubItem = 1;
- switch (data->pExportInfo->dwSubjectChoice)
+ switch (data->exportInfo.dwSubjectChoice)
{
case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT:
contentID = IDS_EXPORT_FILTER_CRL;
@@ -6227,8 +6499,140 @@
CERT_STORE_SAVE_AS_STORE, CERT_STORE_SAVE_TO_FILE, file, 0);
}
+static BOOL save_pfx(HANDLE file, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo,
+ PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo,
+ PCRYPT_KEY_PROV_INFO keyProvInfo, BOOL deleteKeys)
+{
+ HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING,
+ 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
+ BOOL ret = FALSE;
+
+ if (store)
+ {
+ CRYPT_DATA_BLOB pfxBlob = { 0, NULL };
+ PCCERT_CONTEXT cert = NULL;
+ BOOL freeKeyProvInfo = FALSE;
+
+ if (pContextInfo->fExportChain)
+ {
+ HCERTCHAINENGINE engine = NULL;
+
+ if (pExportInfo->cStores)
+ {
+ CERT_CHAIN_ENGINE_CONFIG config;
+
+ memset(&config, 0, sizeof(config));
+ config.cbSize = sizeof(config);
+ config.cAdditionalStore = pExportInfo->cStores;
+ config.rghAdditionalStore = pExportInfo->rghStores;
+ ret = CertCreateCertificateChainEngine(&config, &engine);
+ }
+ else
+ ret = TRUE;
+ if (ret)
+ {
+ CERT_CHAIN_PARA chainPara;
+ PCCERT_CHAIN_CONTEXT chain;
+
+ memset(&chainPara, 0, sizeof(chainPara));
+ chainPara.cbSize = sizeof(chainPara);
+ ret = CertGetCertificateChain(engine,
+ pExportInfo->u.pCertContext, NULL, NULL, &chainPara, 0, NULL,
+ &chain);
+ if (ret)
+ {
+ DWORD i, j;
+
+ for (i = 0; ret && i < chain->cChain; i++)
+ for (j = 0; ret && j <
chain->rgpChain[i]->cElement;
+ j++)
+ {
+ if (i == 0 && j == 0)
+ ret = CertAddCertificateContextToStore(store,
+
chain->rgpChain[i]->rgpElement[j]->pCertContext,
+ CERT_STORE_ADD_ALWAYS, &cert);
+ else
+ ret = CertAddCertificateContextToStore(store,
+
chain->rgpChain[i]->rgpElement[j]->pCertContext,
+ CERT_STORE_ADD_ALWAYS, NULL);
+ }
+ CertFreeCertificateChain(chain);
+ }
+ }
+ if (engine)
+ CertFreeCertificateChainEngine(engine);
+ }
+ else
+ ret = CertAddCertificateContextToStore(store,
+ pExportInfo->u.pCertContext, CERT_STORE_ADD_ALWAYS, &cert);
+ /* Copy private key info to newly created cert, so it'll get exported
+ * along with the cert.
+ */
+ if (ret && pContextInfo->fExportPrivateKeys)
+ {
+ if (keyProvInfo)
+ ret = CertSetCertificateContextProperty(cert,
+ CERT_KEY_PROV_INFO_PROP_ID, 0, keyProvInfo);
+ else
+ {
+ if (!(keyProvInfo = export_get_private_key_info(cert)))
+ ret = FALSE;
+ else
+ {
+ ret = CertSetCertificateContextProperty(cert,
+ CERT_KEY_PROV_INFO_PROP_ID, 0, keyProvInfo);
+ freeKeyProvInfo = TRUE;
+ }
+ }
+ }
+ if (ret)
+ {
+ DWORD exportFlags =
+ REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY | EXPORT_PRIVATE_KEYS;
+
+ ret = PFXExportCertStore(store, &pfxBlob,
+ pContextInfo->pwszPassword, exportFlags);
+ if (ret)
+ {
+ pfxBlob.pbData = HeapAlloc(GetProcessHeap(), 0, pfxBlob.cbData);
+ if (pfxBlob.pbData)
+ {
+ ret = PFXExportCertStore(store, &pfxBlob,
+ pContextInfo->pwszPassword, exportFlags);
+ if (ret)
+ {
+ DWORD bytesWritten;
+
+ ret = WriteFile(file, pfxBlob.pbData, pfxBlob.cbData,
+ &bytesWritten, NULL);
+ }
+ }
+ else
+ {
+ SetLastError(ERROR_OUTOFMEMORY);
+ ret = FALSE;
+ }
+ }
+ }
+ if (ret && deleteKeys)
+ {
+ HCRYPTPROV prov;
+
+ CryptAcquireContextW(&prov, keyProvInfo->pwszContainerName,
+ keyProvInfo->pwszProvName, keyProvInfo->dwProvType,
+ CRYPT_DELETEKEYSET);
+ }
+ if (freeKeyProvInfo)
+ HeapFree(GetProcessHeap(), 0, keyProvInfo);
+ CertFreeCertificateContext(cert);
+ CertCloseStore(store, 0);
+ }
+ return ret;
+}
+
static BOOL do_export(HANDLE file, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo,
- PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo)
+ PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO pContextInfo,
+ PCRYPT_KEY_PROV_INFO keyProvInfo, BOOL deleteKeys)
{
BOOL ret;
@@ -6272,8 +6676,8 @@
pContextInfo->fExportChain);
break;
case CRYPTUI_WIZ_EXPORT_FORMAT_PFX:
- FIXME("unimplemented for PFX\n");
- ret = FALSE;
+ ret = save_pfx(file, pExportInfo, pContextInfo, keyProvInfo,
+ deleteKeys);
break;
default:
SetLastError(E_FAIL);
@@ -6336,8 +6740,8 @@
DWORD mbFlags;
data = (struct ExportWizData *)GetWindowLongPtrW(hwnd, DWLP_USER);
- if ((data->success = do_export(data->file, data->pExportInfo,
- &data->contextInfo)))
+ if ((data->success = do_export(data->file, &data->exportInfo,
+ &data->contextInfo, data->keyProvInfo, data->deleteKeys)))
{
messageID = IDS_EXPORT_SUCCEEDED;
mbFlags = MB_OK;
@@ -6371,24 +6775,33 @@
LPCWSTR pwszWizardTitle, PCCRYPTUI_WIZ_EXPORT_INFO pExportInfo, void *pvoid)
{
PROPSHEETHEADERW hdr;
- PROPSHEETPAGEW pages[4];
+ PROPSHEETPAGEW pages[6];
struct ExportWizData data;
int nPages = 0;
- BOOL showFormatPage = TRUE;
+ BOOL hasPrivateKey, showFormatPage = TRUE;
+ INT_PTR l;
data.dwFlags = dwFlags;
data.pwszWizardTitle = pwszWizardTitle;
- data.pExportInfo = pExportInfo;
+ memset(&data.exportInfo, 0, sizeof(data.exportInfo));
+ memcpy(&data.exportInfo, pExportInfo,
+ min(sizeof(data.exportInfo), pExportInfo->dwSize));
+ if (pExportInfo->dwSize > sizeof(data.exportInfo))
+ data.exportInfo.dwSize = sizeof(data.exportInfo);
data.contextInfo.dwSize = sizeof(data.contextInfo);
data.contextInfo.dwExportFormat = CRYPTUI_WIZ_EXPORT_FORMAT_DER;
data.contextInfo.fExportChain = FALSE;
data.contextInfo.fStrongEncryption = FALSE;
data.contextInfo.fExportPrivateKeys = FALSE;
+ data.contextInfo.pwszPassword = NULL;
+ data.freePassword = FALSE;
if (pExportInfo->dwSubjectChoice == CRYPTUI_WIZ_EXPORT_CERT_CONTEXT &&
pvoid)
memcpy(&data.contextInfo, pvoid,
min(((PCCRYPTUI_WIZ_EXPORT_CERTCONTEXT_INFO)pvoid)->dwSize,
sizeof(data.contextInfo)));
+ data.keyProvInfo = NULL;
+ data.deleteKeys = FALSE;
data.fileName = NULL;
data.file = INVALID_HANDLE_VALUE;
data.success = FALSE;
@@ -6403,6 +6816,7 @@
pages[nPages].lParam = (LPARAM)&data;
nPages++;
+ hasPrivateKey = export_info_has_private_key(pExportInfo);
switch (pExportInfo->dwSubjectChoice)
{
case CRYPTUI_WIZ_EXPORT_CRL_CONTEXT:
@@ -6419,6 +6833,21 @@
showFormatPage = FALSE;
data.contextInfo.dwExportFormat = CRYPTUI_WIZ_EXPORT_FORMAT_PKCS7;
break;
+ }
+
+ if (hasPrivateKey && showFormatPage)
+ {
+ pages[nPages].dwSize = sizeof(pages[0]);
+ pages[nPages].hInstance = hInstance;
+ pages[nPages].u.pszTemplate = MAKEINTRESOURCEW(IDD_EXPORT_PRIVATE_KEY);
+ pages[nPages].pfnDlgProc = export_private_key_dlg_proc;
+ pages[nPages].dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
+ pages[nPages].pszHeaderTitle =
+ MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_TITLE);
+ pages[nPages].pszHeaderSubTitle =
+ MAKEINTRESOURCEW(IDS_EXPORT_PRIVATE_KEY_SUBTITLE);
+ pages[nPages].lParam = (LPARAM)&data;
+ nPages++;
}
if (showFormatPage)
{
@@ -6431,6 +6860,20 @@
MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_TITLE);
pages[nPages].pszHeaderSubTitle =
MAKEINTRESOURCEW(IDS_EXPORT_FORMAT_SUBTITLE);
+ pages[nPages].lParam = (LPARAM)&data;
+ nPages++;
+ }
+ if (hasPrivateKey && showFormatPage)
+ {
+ pages[nPages].dwSize = sizeof(pages[0]);
+ pages[nPages].hInstance = hInstance;
+ pages[nPages].u.pszTemplate = MAKEINTRESOURCEW(IDD_EXPORT_PASSWORD);
+ pages[nPages].pfnDlgProc = export_password_dlg_proc;
+ pages[nPages].dwFlags = PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
+ pages[nPages].pszHeaderTitle =
+ MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_TITLE);
+ pages[nPages].pszHeaderSubTitle =
+ MAKEINTRESOURCEW(IDS_EXPORT_PASSWORD_SUBTITLE);
pages[nPages].lParam = (LPARAM)&data;
nPages++;
}
@@ -6468,11 +6911,21 @@
hdr.nPages = nPages;
hdr.u4.pszbmWatermark = MAKEINTRESOURCEW(IDB_CERT_WATERMARK);
hdr.u5.pszbmHeader = MAKEINTRESOURCEW(IDB_CERT_HEADER);
- PropertySheetW(&hdr);
+ l = PropertySheetW(&hdr);
DeleteObject(data.titleFont);
+ if (data.freePassword)
+ HeapFree(GetProcessHeap(), 0,
+ (LPWSTR)data.contextInfo.pwszPassword);
+ HeapFree(GetProcessHeap(), 0, data.keyProvInfo);
CloseHandle(data.file);
HeapFree(GetProcessHeap(), 0, data.fileName);
- return data.success;
+ if (l == 0)
+ {
+ SetLastError(ERROR_CANCELLED);
+ return FALSE;
+ }
+ else
+ return data.success;
}
BOOL WINAPI CryptUIWizExport(DWORD dwFlags, HWND hwndParent,
@@ -6494,7 +6947,7 @@
if (file != INVALID_HANDLE_VALUE)
{
- ret = do_export(file, pExportInfo, pvoid);
+ ret = do_export(file, pExportInfo, pvoid, NULL, FALSE);
CloseHandle(file);
}
else