diff --git a/dlls/cryptui/Makefile.in b/dlls/cryptui/Makefile.in index bc4cd1ceb22..078cb3344ae 100644 --- a/dlls/cryptui/Makefile.in +++ b/dlls/cryptui/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = cryptui.dll -IMPORTS = crypt32 comctl32 user32 kernel32 +IMPORTS = uuid crypt32 ole32 comctl32 user32 kernel32 DELAYIMPORTS = wintrust IMPORTLIB = cryptui diff --git a/dlls/cryptui/cert.bmp b/dlls/cryptui/cert.bmp new file mode 100644 index 00000000000..1f44f367ab2 Binary files /dev/null and b/dlls/cryptui/cert.bmp differ diff --git a/dlls/cryptui/certerror.bmp b/dlls/cryptui/certerror.bmp new file mode 100644 index 00000000000..98bce50b179 Binary files /dev/null and b/dlls/cryptui/certerror.bmp differ diff --git a/dlls/cryptui/certwarning.bmp b/dlls/cryptui/certwarning.bmp new file mode 100644 index 00000000000..5961d9fa6c5 Binary files /dev/null and b/dlls/cryptui/certwarning.bmp differ diff --git a/dlls/cryptui/cryptui.rc b/dlls/cryptui/cryptui.rc index d18034d817a..2a1f0e40f5d 100644 --- a/dlls/cryptui/cryptui.rc +++ b/dlls/cryptui/cryptui.rc @@ -25,4 +25,13 @@ #include "cryptuires.h" +/* @makedep: cert.bmp */ +IDB_CERT BITMAP LOADONCALL DISCARDABLE cert.bmp + +/* @makedep: certerror.bmp */ +IDB_CERT_ERROR BITMAP LOADONCALL DISCARDABLE certerror.bmp + +/* @makedep: certwarning.bmp */ +IDB_CERT_WARNING BITMAP LOADONCALL DISCARDABLE certwarning.bmp + #include "cryptui_En.rc" diff --git a/dlls/cryptui/cryptui_En.rc b/dlls/cryptui/cryptui_En.rc index 3f718cc8b6b..99f18ecc52f 100644 --- a/dlls/cryptui/cryptui_En.rc +++ b/dlls/cryptui/cryptui_En.rc @@ -23,6 +23,11 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT STRINGTABLE DISCARDABLE { IDS_CERTIFICATE "Certificate" + IDS_CERTIFICATEINFORMATION "Certificate Information" + IDS_CERT_INFO_BAD_SIG "This certificate has an invalid signature. The certificate may have been altered or corrupted." + IDS_CERT_INFO_UNTRUSTED_CA "This root certificate is not trusted. To trust it, add it to your system's trusted root certificate store." + IDS_CERT_INFO_UNTRUSTED_ROOT "This certificate could not be validated to a trusted root certificate." + IDS_CERT_INFO_PARTIAL_CHAIN "This certificate's issuer could not be found." IDS_SUBJECT_HEADING "Issued to: " IDS_ISSUER_HEADING "Issued by: " IDS_VALID_FROM "Valid from " diff --git a/dlls/cryptui/cryptuires.h b/dlls/cryptui/cryptuires.h index 8c99b8e1637..dcc1b7a2eb1 100644 --- a/dlls/cryptui/cryptuires.h +++ b/dlls/cryptui/cryptuires.h @@ -19,6 +19,11 @@ #define __CRYPTUIRES_H_ #define IDS_CERTIFICATE 1000 +#define IDS_CERTIFICATEINFORMATION 1001 +#define IDS_CERT_INFO_BAD_SIG 1002 +#define IDS_CERT_INFO_UNTRUSTED_CA 1003 +#define IDS_CERT_INFO_UNTRUSTED_ROOT 1004 +#define IDS_CERT_INFO_PARTIAL_CHAIN 1005 #define IDS_SUBJECT_HEADING 1010 #define IDS_ISSUER_HEADING 1011 @@ -27,6 +32,11 @@ #define IDD_GENERAL 100 +#define IDB_CERT 201 +#define IDB_CERT_ERROR 202 +#define IDB_CERT_WARNING 203 +#define IDB_CHECKS 204 + #define IDC_STATIC 2000 #define IDC_CERTIFICATE_ICON 2001 #define IDC_CERTIFICATE_INFO 2002 diff --git a/dlls/cryptui/main.c b/dlls/cryptui/main.c index 6ec6aa31d9b..234ccd70bad 100644 --- a/dlls/cryptui/main.c +++ b/dlls/cryptui/main.c @@ -20,6 +20,7 @@ #include +#define COBJMACROS #define NONAMELESSUNION #include "windef.h" @@ -29,6 +30,8 @@ #include "softpub.h" #include "wingdi.h" #include "richedit.h" +#include "ole2.h" +#include "richole.h" #include "cryptuiapi.h" #include "cryptuires.h" #include "wine/debug.h" @@ -203,8 +206,144 @@ static void add_cert_string_to_control(HWND hwnd, PCCERT_CONTEXT pCertContext, } } +static void add_icon_to_control(HWND hwnd, int id) +{ + HRESULT hr; + LPRICHEDITOLE richEditOle = NULL; + LPOLEOBJECT object = NULL; + CLSID clsid; + LPOLECACHE oleCache = NULL; + FORMATETC formatEtc; + DWORD conn; + LPDATAOBJECT dataObject = NULL; + HBITMAP bitmap = NULL; + RECT rect; + STGMEDIUM stgm; + REOBJECT reObject; + + TRACE("(%p, %d)\n", hwnd, id); + + SendMessageW(hwnd, EM_GETOLEINTERFACE, 0, (LPARAM)&richEditOle); + if (!richEditOle) + goto end; + hr = OleCreateDefaultHandler(&CLSID_NULL, NULL, &IID_IOleObject, + (void**)&object); + if (FAILED(hr)) + goto end; + hr = IOleObject_GetUserClassID(object, &clsid); + if (FAILED(hr)) + goto end; + hr = IOleObject_QueryInterface(object, &IID_IOleCache, (void**)&oleCache); + if (FAILED(hr)) + goto end; + formatEtc.cfFormat = CF_BITMAP; + formatEtc.ptd = NULL; + formatEtc.dwAspect = DVASPECT_CONTENT; + formatEtc.lindex = -1; + formatEtc.tymed = TYMED_GDI; + hr = IOleCache_Cache(oleCache, &formatEtc, 0, &conn); + if (FAILED(hr)) + goto end; + hr = IOleObject_QueryInterface(object, &IID_IDataObject, + (void**)&dataObject); + if (FAILED(hr)) + goto end; + bitmap = LoadImageW(hInstance, MAKEINTRESOURCEW(id), IMAGE_BITMAP, 0, 0, + LR_DEFAULTSIZE | LR_LOADTRANSPARENT); + if (!bitmap) + goto end; + rect.left = rect.top = 0; + rect.right = GetSystemMetrics(SM_CXICON); + rect.bottom = GetSystemMetrics(SM_CYICON); + stgm.tymed = TYMED_GDI; + stgm.u.hBitmap = bitmap; + stgm.pUnkForRelease = NULL; + hr = IDataObject_SetData(dataObject, &formatEtc, &stgm, TRUE); + if (FAILED(hr)) + goto end; + + reObject.cbStruct = sizeof(reObject); + reObject.cp = REO_CP_SELECTION; + reObject.clsid = clsid; + reObject.poleobj = object; + reObject.pstg = NULL; + reObject.polesite = NULL; + reObject.sizel.cx = reObject.sizel.cy = 0; + reObject.dvaspect = DVASPECT_CONTENT; + reObject.dwFlags = 0; + reObject.dwUser = 0; + + IRichEditOle_InsertObject(richEditOle, &reObject); + +end: + if (dataObject) + IDataObject_Release(dataObject); + if (oleCache) + IOleCache_Release(oleCache); + if (object) + IOleObject_Release(object); + if (richEditOle) + IRichEditOle_Release(richEditOle); +} + #define MY_INDENT 200 +static void set_cert_info(HWND hwnd, + PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo) +{ + CHARFORMATW charFmt; + PARAFORMAT2 parFmt; + HWND icon = GetDlgItem(hwnd, IDC_CERTIFICATE_ICON); + HWND text = GetDlgItem(hwnd, IDC_CERTIFICATE_INFO); + CRYPT_PROVIDER_SGNR *provSigner = WTHelperGetProvSignerFromChain( + (CRYPT_PROVIDER_DATA *)pCertViewInfo->u.pCryptProviderData, + pCertViewInfo->idxSigner, pCertViewInfo->fCounterSigner, + pCertViewInfo->idxCounterSigner); + CRYPT_PROVIDER_CERT *root = + &provSigner->pasCertChain[provSigner->csCertChain - 1]; + + if (provSigner->pChainContext->TrustStatus.dwErrorStatus & + CERT_TRUST_IS_PARTIAL_CHAIN) + add_icon_to_control(icon, IDB_CERT_WARNING); + else if (!root->fTrustedRoot) + add_icon_to_control(icon, IDB_CERT_ERROR); + else + add_icon_to_control(icon, IDB_CERT); + + memset(&charFmt, 0, sizeof(charFmt)); + charFmt.cbSize = sizeof(charFmt); + charFmt.dwMask = CFM_BOLD; + charFmt.dwEffects = CFE_BOLD; + SendMessageW(text, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFmt); + /* FIXME: vertically center text */ + parFmt.cbSize = sizeof(parFmt); + parFmt.dwMask = PFM_STARTINDENT; + parFmt.dxStartIndent = MY_INDENT; + add_string_resource_with_paraformat_to_control(text, + IDS_CERTIFICATEINFORMATION, &parFmt); + + text = GetDlgItem(hwnd, IDC_CERTIFICATE_STATUS); + SendMessageW(text, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&charFmt); + if (provSigner->dwError == TRUST_E_CERT_SIGNATURE) + add_string_resource_with_paraformat_to_control(text, + IDS_CERT_INFO_BAD_SIG, &parFmt); + else if (provSigner->pChainContext->TrustStatus.dwErrorStatus & + CERT_TRUST_IS_PARTIAL_CHAIN) + add_string_resource_with_paraformat_to_control(text, + IDS_CERT_INFO_PARTIAL_CHAIN, &parFmt); + else if (!root->fTrustedRoot) + { + if (provSigner->csCertChain == 1 && root->fSelfSigned) + add_string_resource_with_paraformat_to_control(text, + IDS_CERT_INFO_UNTRUSTED_CA, &parFmt); + else + add_string_resource_with_paraformat_to_control(text, + IDS_CERT_INFO_UNTRUSTED_ROOT, &parFmt); + } + else + FIXME("show policies and issuer statement\n"); +} + static void set_cert_name_string(HWND hwnd, PCCERT_CONTEXT cert, DWORD nameFlags, int heading) { @@ -278,7 +417,7 @@ static void set_cert_validity_period(HWND hwnd, PCCERT_CONTEXT cert) static void set_general_info(HWND hwnd, PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pCertViewInfo) { - FIXME("set cert general info\n"); + set_cert_info(hwnd, pCertViewInfo); set_cert_name_string(hwnd, pCertViewInfo->pCertContext, 0, IDS_SUBJECT_HEADING); set_cert_name_string(hwnd, pCertViewInfo->pCertContext,