#include "pch.hxx" #include "demand.h" #include #include #include #include //WIn64 macros #ifdef _WIN64 #if defined (_AMD64_) || defined (_IA64_) #define ALIGNTYPE LARGE_INTEGER #else #define ALIGNTYPE DWORD #endif #define ALIGN ((ULONG) (sizeof(ALIGNTYPE) - 1)) #define LcbAlignLcb(lcb) (((lcb) + ALIGN) & ~ALIGN) #define PbAlignPb(pb) ((LPBYTE) ((((DWORD) (pb)) + ALIGN) & ~ALIGN)) #define MYALIGN ((POINTER_64_INT) (sizeof(ALIGNTYPE) - 1)) #define MyPbAlignPb(pb) ((LPBYTE) ((((POINTER_64_INT) (pb)) + MYALIGN) & ~MYALIGN)) #else //!WIN64 #define LcbAlignLcb(lcb) (lcb) #define PbAlignPb(pb) (pb) #define MyPbAlignPb(pb) (pb) #endif #define ARRAYSIZE(_rg) (sizeof(_rg)/sizeof(_rg[0])) #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4" typedef struct { DWORD unused; CERT_NAME_BLOB Issuer; CRYPT_INTEGER_BLOB SerialNumber; } CRYPT_RECIPIENT_ID, * PCRYPT_RECIPIENT_ID; #if 0 // From mssip.h // SPC_LINK_STRUCT // pvStructInfo points to SPC_LINK. // typedef BYTE SPC_UUID[16]; typedef struct _SPC_SERIALIZED_OBJECT { SPC_UUID ClassId; CRYPT_DATA_BLOB SerializedData; } SPC_SERIALIZED_OBJECT, *PSPC_SERIALIZED_OBJECT; typedef struct _SPC_LINK { DWORD dwLinkChoice; union { LPWSTR pwszUrl; SPC_SERIALIZED_OBJECT Moniker; LPWSTR pwszFile; }; } SPC_LINK, *PSPC_LINK; #define SPC_URL_LINK_CHOICE 1 #define SPC_MONIKER_LINK_CHOICE 2 #define SPC_FILE_LINK_CHOICE 3 #endif #ifndef WIN16 #include "wintrust.h" #endif // !WIN16 #ifdef MAC #include EXTERN_C INT CALLBACK CreateDate(LPSYSTEMTIME lpst, CHAR * szOutStr, BOOL fNoYear); EXTERN_C INT CreateTime(LPSYSTEMTIME lpst, CHAR *szOutStr, BOOL fNoSeconds); HRESULT TdxFormatMessageVa (IN LPCSTR rgchFormat, OUT CHAR * rgchBuffer, OUT ULONG * pucReqSize, va_list marker); #endif // MAC extern HINSTANCE HinstDll; ///////////////////////////////////////////////////////// #ifndef MAC BOOL IsWin95() { BOOL f; OSVERSIONINFOA ver; ver.dwOSVersionInfoSize = sizeof(ver); f = GetVersionExA(&ver); return !f || (ver.dwPlatformId == 1); } #endif // !MAC #ifndef WIN16 LRESULT MySendDlgItemMessageW(HWND hwnd, int id, UINT msg, WPARAM w, LPARAM l) { char rgch[4096]; LPTV_INSERTSTRUCTW ptvinsW; TV_INSERTSTRUCTA tvins; if (msg == LB_ADDSTRING) { WideCharToMultiByte(CP_ACP, 0, (LPWSTR) l, -1, rgch, sizeof(rgch), NULL, NULL); l = (LPARAM) rgch; } else if (msg == TVM_INSERTITEMW) { msg = TVM_INSERTITEMA; ptvinsW = (LPTV_INSERTSTRUCTW) l; memcpy(&tvins, ptvinsW, sizeof(tvins)); WideCharToMultiByte(CP_ACP, 0, ptvinsW->item.pszText, -1, rgch, sizeof(rgch), NULL, NULL); tvins.item.pszText = rgch; l = (LPARAM) &tvins; } return SendDlgItemMessageA(hwnd, id, msg, w, l); } BOOL MySetDlgItemTextW(HWND hwnd, int id, LPCWSTR pwsz) { char rgch[4096]; WideCharToMultiByte(CP_ACP, 0, pwsz, -1, rgch, sizeof(rgch), NULL, NULL); return SetDlgItemTextA(hwnd, id, rgch); } UINT MyGetDlgItemTextW(HWND hwnd, int id, LPWSTR pwsz, int nMax) { UINT cch; char rgch[4096]; cch = GetDlgItemTextA(hwnd, id, rgch, ARRAYSIZE(rgch)-1); rgch[cch+1] = 0; cch = MultiByteToWideChar(CP_ACP, 0, rgch, cch+1, pwsz, nMax); return cch; } DWORD MyFormatMessageW(DWORD dwFlags, LPCVOID pbSource, DWORD dwMessageId, DWORD dwLangId, LPWSTR lpBuffer, DWORD nSize, va_list * args) { DWORD cch; int i; LPSTR pchDest; DWORD_PTR * pdw; LPWSTR pwchOut; char rgchSource[128]; DWORD_PTR rgdwArgs[10]; int cArgs = 10; #ifdef MAC HRESULT hr; #endif // MAC if (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)) { #ifdef DEBUG DebugBreak(); #endif // DEBUG return 0; } // // We need to figure out how many arguments are in the array. // All Arrays are to be terminated by -1 in order for this to work. // pdw = (DWORD_PTR *) args; for (i=0; i 0xffff) { free((LPVOID) rgdwArgs[i]); } } LocalFree(pchDest); return cch; } int MyLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int cbBuffer) { DWORD cch; char rgch[256]; #ifndef MAC if (!FIsWin95) { return LoadStringW(hInstance, uID, lpBuffer, cbBuffer); } #endif // !MAC cch = LoadStringA(hInstance, uID, rgch, sizeof(rgch)); cch = MultiByteToWideChar(CP_ACP, 0, rgch, -1, lpBuffer, cbBuffer); return cch; } #endif // !WIN16 BOOL MyCryptAcquireContextW(HCRYPTPROV * phProv, LPCWSTR pszContainer, LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags) { char rgch1[256]; char rgch2[256]; if (pszContainer != NULL) { WideCharToMultiByte(CP_ACP, 0, pszContainer, -1, rgch1, ARRAYSIZE(rgch1), NULL, NULL); pszContainer = (LPWSTR) rgch1; } if (pszProvider != NULL) { WideCharToMultiByte(CP_ACP, 0, pszProvider, -1, rgch2, ARRAYSIZE(rgch2), NULL, NULL); pszProvider = (LPWSTR) rgch2; } return CryptAcquireContextA(phProv, (LPCSTR) pszContainer, (LPCSTR) pszProvider, dwProvType, dwFlags); } BOOL MyWinHelpW(HWND hWndMain, LPCWSTR szHelp, UINT uCommand, ULONG_PTR dwData) { char rgch[4096]; WideCharToMultiByte(CP_ACP, 0, szHelp, -1, rgch, ARRAYSIZE(rgch), NULL, NULL); return WinHelpA(hWndMain, rgch, uCommand, dwData); } //////////////////////////////////////////////////////////////// DWORD TruncateToWindowA(HWND hwndDlg, int id, LPSTR psz) { int cch = strlen(psz); int cchMax; int cchMid; int cchMin; HDC hdc; HFONT hfontOld; HFONT hfontNew; HWND hwnd; SIZE siz; SIZE sizDots; RECT rt; TEXTMETRICA tmA; hwnd = GetDlgItem(hwndDlg, id); hdc = GetDC(hwnd); hfontNew = (HFONT) SendMessage(hwnd, WM_GETFONT, NULL, NULL); if (NULL == hfontNew) { goto Error; } hfontOld = (HFONT) SelectObject(hdc, hfontNew); GetTextMetricsA(hdc, &tmA); GetWindowRect(hwnd, &rt); rt.right -= rt.left; GetTextExtentPointA(hdc, psz, cch, &siz); if (rt.right < siz.cx) { GetTextExtentPointA(hdc, "...", 3, &sizDots); rt.right -= sizDots.cx; for (cchMin=0, cchMax=cch, cchMid = (cchMin + cchMax + 1)/2; cchMin < cchMax; cchMid = (cchMin + cchMax + 1)/2) { GetTextExtentPointA(hdc, psz, cchMid, &siz); if (rt.right == siz.cx) { break; } else if (rt.right > siz.cx) { cchMin = cchMid; } else { cchMax = cchMid-1; } } // Make certain that we don't overflow the buffer. if (cchMin + 3 > cch) { // 3 = number of characters in "...". cchMin = cch - 3; } StrCpyNA(&psz[cchMin], "...", cch+1-cchMin); } SelectObject(hdc, hfontOld); Error: ReleaseDC(hwnd, hdc); return TRUE; } DWORD TruncateToWindowW(HWND hwndDlg, int id, WCHAR * pwsz) { if (FIsWin95) { DWORD cch; char rgch[4096]; cch = wcslen(pwsz)+1; WideCharToMultiByte(CP_ACP, 0, pwsz, -1, rgch, sizeof(rgch), NULL, NULL); TruncateToWindowA(hwndDlg, id, rgch); MultiByteToWideChar(CP_ACP, 0, rgch, -1, pwsz, cch); return TRUE; } #ifndef WIN16 #ifndef MAC int cch = wcslen(pwsz); int cchMax; int cchMid; int cchMin; HDC hdc; HFONT hfontOld; HFONT hfontNew; HWND hwnd; SIZE siz; SIZE sizDots; RECT rt; TEXTMETRICW tmW; hwnd = GetDlgItem(hwndDlg, id); hdc = GetDC(hwnd); hfontNew = (HFONT) SendMessage(hwnd, WM_GETFONT, NULL, NULL); hfontOld = (HFONT) SelectObject(hdc, hfontNew); GetTextMetricsW(hdc, &tmW); GetWindowRect(hwnd, &rt); rt.right -= rt.left; GetTextExtentPointW(hdc, pwsz, cch, &siz); if (rt.right < siz.cx) { GetTextExtentPointW(hdc, L"...", 3, &sizDots); rt.right -= sizDots.cx; for (cchMin=0, cchMax=cch, cchMid = (cchMin + cchMax + 1)/2; cchMin < cchMax; cchMid = (cchMin + cchMax + 1)/2) { GetTextExtentPointW(hdc, pwsz, cchMid, &siz); if (rt.right == siz.cx) { break; } else if (rt.right > siz.cx) { cchMin = cchMid; } else { cchMax = cchMid-1; } } // Make certain that we don't overflow the buffer. if (cchMin + 3 > cch) { // 3 = number of characters in L"...". cchMin = cch - 3; } StrCpyNW(&pwsz[cchMin], L"...", cch+1-cchMin); } SelectObject(hdc, hfontOld); ReleaseDC(hwnd, hdc); #endif // !MAC #endif // !WIN16 return TRUE; } //////////////////////////////////////////////////////////////////// #if 0 // From authcode.h //+------------------------------------------------------------------------- // SPC_SP_AGENCY_INFO_STRUCT // pvStructInfo points to SPC_SP_AGENCY_INFO. // typedef struct _SPC_IMAGE { PSPC_LINK pImageLink; CRYPT_DATA_BLOB Bitmap; CRYPT_DATA_BLOB Metafile; CRYPT_DATA_BLOB EnhancedMetafile; CRYPT_DATA_BLOB GifFile; } SPC_IMAGE, *PSPC_IMAGE; typedef struct _SPC_SP_AGENCY_INFO { PSPC_LINK pPolicyInformation; LPWSTR pwszPolicyDisplayText; PSPC_IMAGE pLogoImage; PSPC_LINK pLogoLink; } SPC_SP_AGENCY_INFO, *PSPC_SP_AGENCY_INFO; #endif // 0 /////////////////////////////////////////////////////// BOOL LoadStringInWindow(HWND hwnd, UINT idCtrl, HMODULE hmod, UINT idString) { WCHAR rgwch[1024]; if (FIsWin95) { LoadStringA(hmod, idString, (LPSTR) rgwch, sizeof(rgwch)); SetDlgItemTextA(hwnd, idCtrl, (LPSTR)rgwch); } #ifndef WIN16 #ifndef MAC else { LoadStringW(hmod, idString, rgwch, sizeof(rgwch)/sizeof(rgwch[0])); SetDlgItemText(hwnd, idCtrl, rgwch); } #endif // !MAC #endif // !WIN16 return TRUE; } BOOL LoadStringsInWindow(HWND hwnd, UINT idCtrl, HMODULE hmod, UINT *pidStrings) { BOOL fRet = FALSE; if (FIsWin95) { UINT cchOut; UINT cbOut; CHAR * pszOut; cbOut = 1024 * sizeof(CHAR); pszOut = (CHAR *) malloc(cbOut); if (NULL == pszOut) { goto ret; } for (*pszOut = '\0', cchOut = 1; *pidStrings != UINT_MAX; pidStrings++) { UINT cchBuff; CHAR rgchBuff[1024]; cchBuff = LoadStringA(hmod, *pidStrings, rgchBuff, sizeof(rgchBuff)); if (0 == cchBuff) { goto ErrorA; } cchOut += cchBuff; if (cchOut > (cbOut / sizeof(CHAR))) { CHAR * pszNew; cbOut *= 2; pszNew = (CHAR *) realloc(pszOut, cbOut); if (NULL == pszNew) { goto ErrorA; } pszOut = pszNew; } StrCatBuffA(pszOut, rgchBuff, cbOut/sizeof(CHAR)); } SetDlgItemTextA(hwnd, idCtrl, pszOut); fRet = TRUE; ErrorA: free(pszOut); } #if !defined( MAC ) && !defined( WIN16 ) else { UINT cwchOut; UINT cbOut; WCHAR * pwszOut; cbOut = 1024 * sizeof(WCHAR); pwszOut = (WCHAR *) malloc(cbOut); if (NULL == pwszOut) { goto ret; } for (*pwszOut = L'\0', cwchOut = 1; *pidStrings != UINT_MAX; pidStrings++) { UINT cwchBuff; WCHAR rgwchBuff[1024]; cwchBuff = LoadStringW(hmod, *pidStrings, rgwchBuff, sizeof(rgwchBuff) / sizeof(WCHAR)); if (0 == cwchBuff) { goto ErrorW; } cwchOut += cwchBuff; if (cwchOut > (cbOut / sizeof(WCHAR))) { WCHAR * pwszNew; cbOut *= 2; pwszNew = (WCHAR *) realloc(pwszOut, cbOut); if (NULL == pwszNew) { goto ErrorW; } pwszOut = pwszNew; } StrCatBuffW(pwszOut, rgwchBuff,cbOut/sizeof(WCHAR)); } SetDlgItemTextW(hwnd, idCtrl, pwszOut); fRet = TRUE; ErrorW: free(pwszOut); } #endif // !MAC && !WIN16 ret: return fRet; } /////////////////////////////////////////////////////// const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; const CHAR RgchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; #if 0 LPWSTR FindURL(PCCERT_CONTEXT pccert) { DWORD cbInfo; PCERT_EXTENSION pExt; PSPC_SP_AGENCY_INFO pInfo; LPWSTR pwsz; pExt = CertFindExtension("1.3.6.1.4.311.2.1.10", pccert->pCertInfo->cExtension, pccert->pCertInfo->rgExtension); if (pExt == NULL) { return NULL; } CryptDecodeObject(X509_ASN_ENCODING, (LPCSTR) 2000, pExt->Value.pbData, pExt->Value.cbData, 0, NULL, &cbInfo); if (cbInfo == 0) { return NULL; } pInfo = (PSPC_SP_AGENCY_INFO) malloc(cbInfo); if (!CryptDecodeObject(X509_ASN_ENCODING, (LPCSTR) 2000, pExt->Value.pbData, pExt->Value.cbData, 0, pInfo, &cbInfo)) { free (pInfo); return NULL; } if (pInfo->pPolicyInformation->dwLinkChoice != SPC_URL_LINK_CHOICE) { free (pInfo); return NULL; } #ifndef WIN16 pwsz = _wcsdup(pInfo->pPolicyInformation->pwszUrl); #else pwsz = _strdup(pInfo->pPolicyInformation->pwszUrl); #endif // !WIN16 free (pInfo); return pwsz; } #endif // 0 BOOL FormatAlgorithm(HWND hwnd, UINT id, PCCERT_CONTEXT pccert) { int cch; LPWSTR pszMsg; LPSTR psz = pccert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId; LPWSTR pwsz; DWORD_PTR rgdw[3]; #ifdef MAC CHAR rgch[17]; #endif // MAC WCHAR rgwch[17]; rgdw[2] = (DWORD) -1; // Sentinal Value rgdw[1] = pccert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData * 8; if (strcmp(psz, szOID_RSA_RSA) == 0) { rgdw[0] = (DWORD_PTR) L"RSA"; rgdw[1] &= 0xffffff80; // M00BUG #ifdef MAC wnsprintf(rgch, ARRAYSIZE(rgch), "%d", rgdw[1]); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, rgch, -1, rgwch, sizeof(rgwch) / sizeof(rgwch[0])); #else // !MAC #ifndef WIN16 _ltow((LONG) rgdw[1], rgwch, 10); #else _ltoa(rgdw[1], rgwch, 10); #endif // !WIN16 #endif // MAC rgdw[1] = (DWORD_PTR) rgwch; } else { cch = strlen(psz)+1; pwsz = (LPWSTR) malloc((cch+1)*sizeof(WCHAR)); if (pwsz == NULL) { return FALSE; } MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, psz, cch, pwsz, cch+1); SetDlgItemText(hwnd, id, pwsz); free(pwsz); return TRUE; } FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_ALLOCATE_BUFFER, L"%1 (%2 bits)", 0, 0, (LPWSTR) &pszMsg, 0, (va_list *) rgdw); SetDlgItemText(hwnd, id, pszMsg); #ifndef WIN16 LocalFree((LPVOID) pszMsg); #else LocalFree((HLOCAL) pszMsg); #endif // !WIN16 return TRUE; } BOOL FormatBinary(HWND hwnd, UINT id, LPBYTE pb, DWORD cb) { DWORD i; LPWSTR pwch; pwch = (LPWSTR) malloc( (cb*2+1)*sizeof(WCHAR)); if (pwch == NULL) { return FALSE; } for (i=0; i < cb; i++, pb++) { pwch[i*2] = RgwchHex[(*pb & 0xf0) >> 4]; pwch[i*2+1] = RgwchHex[*pb & 0x0f]; } pwch[i*2] = 0; SetDlgItemText(hwnd, id, pwch); free(pwch); return TRUE; } //// FormatCPS // // Description: // Look for a Certificate Policy Statment in the certificate. // We recognize as CPSs the following items: // 1. What ever PKIX comes up with // 2. The magic Verisign one // BOOL FormatCPS(HWND hwnd, UINT id, PCCERT_CONTEXT pccert) { DWORD cb; BOOL f; PCERT_EXTENSION pExt; LPWSTR pwsz; pExt = CertFindExtension("2.5.29.32", pccert->pCertInfo->cExtension, pccert->pCertInfo->rgExtension); if (pExt != NULL) { cb = 0; f = CryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, pExt->pszObjId, pExt->Value.pbData, pExt->Value.cbData, 0, &cb); if (f && (cb > 0)) { pwsz = (LPWSTR) malloc(cb * sizeof(WCHAR)); CryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, pExt->pszObjId, pExt->Value.pbData, pExt->Value.cbData, pwsz, &cb); SetDlgItemText(hwnd, id, pwsz); free(pwsz); } return TRUE; } return FALSE; } BOOL FormatDate(HWND hwnd, UINT id, FILETIME ft) { int cch; int cch2; LPWSTR pwsz; SYSTEMTIME st; #ifdef MAC CHAR rgch[256]; #else // !MAC LPSTR psz; #endif // MAC if (!FileTimeToSystemTime(&ft, &st)) { return FALSE; } #ifdef MAC cch = CreateDate(&st, rgch, FALSE); pwsz = (LPWSTR) malloc((cch + 2)*sizeof(WCHAR)); if (pwsz == NULL) { return FALSE; } cch2 = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, rgch, -1, pwsz, cch + 2); if (0 == cch2) { free(pwsz); return FALSE; } pwsz[cch2++] = L' '; cch = CreateTime(&st, rgch, FALSE); pwsz = (LPWSTR) realloc(pwsz, (cch + cch2 + 1)*sizeof(WCHAR)); if (pwsz == NULL) { return FALSE; } cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, rgch, -1, pwsz + cch2, cch + 1); if (0 == cch) { free(pwsz); return FALSE; } SetDlgItemText(hwnd, id, pwsz); #else // !MAC if (FIsWin95) { cch = (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + GetDateFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 5); psz = (LPSTR) malloc(cch+5); if (psz == NULL) { return FALSE; } cch2 = GetDateFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, psz, cch); cch2 -= 1; psz[cch2++] = ' '; GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, &psz[cch2], cch-cch2); SetDlgItemTextA(hwnd, id, psz); free(psz); return TRUE; } cch = (GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 5); pwsz = (LPWSTR) malloc((cch+5)*sizeof(WCHAR)); if (pwsz == NULL) { return FALSE; } cch2 = GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, pwsz, cch); cch2 -= 1; pwsz[cch2++] = ' '; GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, &pwsz[cch2], cch-cch2); #ifndef WIN16 SetDlgItemTextW(hwnd, id, pwsz); #else SetDlgItemText(hwnd, id, pwsz); #endif // !WIN16 #endif // MAC free(pwsz); return TRUE; } BOOL FormatIssuer(HWND hwnd, UINT id, PCCERT_CONTEXT pccert, DWORD dwFlags) { DWORD cch; LPWSTR psz; cch = CertNameToStrW(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Issuer, dwFlags | CERT_NAME_STR_CRLF_FLAG, NULL, 0); psz = (LPWSTR) malloc(cch*sizeof(TCHAR)); CertNameToStrW(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Issuer, dwFlags | CERT_NAME_STR_CRLF_FLAG, psz, cch); SetDlgItemText(hwnd, id, psz); free(psz); return TRUE; } BOOL FormatSerialNo(HWND hwnd, UINT id, PCCERT_CONTEXT pccert) { DWORD i; CRYPT_INTEGER_BLOB * pblob; LPBYTE pb; WCHAR rgwch[128]; pblob = &pccert->pCertInfo->SerialNumber; for (i=0, pb = &pblob->pbData[pblob->cbData-1]; i < pblob->cbData; i++, pb--) { rgwch[i*2] = RgwchHex[(*pb & 0xf0) >> 4]; rgwch[i*2+1] = RgwchHex[*pb & 0x0f]; } rgwch[i*2] = 0; TruncateToWindowW(hwnd, id, rgwch); SetDlgItemText(hwnd, id, rgwch); return TRUE; } BOOL FormatSubject(HWND hwnd, UINT id, PCCERT_CONTEXT pccert, DWORD dwFlags) { DWORD cch; LPWSTR psz; cch = CertNameToStrW(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Subject, dwFlags | CERT_NAME_STR_CRLF_FLAG, NULL, 0); psz = (LPWSTR) malloc(cch*sizeof(WCHAR)); CertNameToStrW(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Subject, dwFlags | CERT_NAME_STR_CRLF_FLAG, psz, cch); SetDlgItemText(hwnd, id, psz); free(psz); return TRUE; } BOOL FormatThumbprint(HWND hwnd, UINT id, PCCERT_CONTEXT pccert) { DWORD cb; DWORD i; BYTE rgb[20]; WCHAR rgwch[61]; WCHAR * pwch; cb = sizeof(rgb); if (!CertGetCertificateContextProperty(pccert, CERT_MD5_HASH_PROP_ID, rgb, &cb)) { return FALSE; } for (i=0, pwch = rgwch; i> 4]; pwch[1] = RgwchHex[rgb[i] & 0x0f]; if (((i % 4) == 3) && (i != cb-1)) { pwch[2] = ':'; pwch++; } } *pwch = 0; TruncateToWindowW(hwnd, id, rgwch); SetDlgItemText(hwnd, id, rgwch); return TRUE; } BOOL FormatValidity(HWND hwnd, UINT id, PCCERT_CONTEXT pccert) { DWORD_PTR rgdw[3]; WCHAR rgwchFormat[128]; WCHAR rgwchNotAfter[128]; WCHAR rgwchNotBefore[128]; WCHAR rgwchValidity[256]; SYSTEMTIME stNotAfter; SYSTEMTIME stNotBefore; rgdw[2] = (DWORD) -1; // Sentinal Value FileTimeToSystemTime(&pccert->pCertInfo->NotBefore, &stNotBefore); FileTimeToSystemTime(&pccert->pCertInfo->NotAfter, &stNotAfter); if (FIsWin95) { LoadStringA(HinstDll, IDS_VALIDITY_FORMAT, (LPSTR) rgwchFormat, sizeof(rgwchFormat)); #ifdef MAC CreateDate(&stNotBefore, (LPSTR) rgwchNotBefore, FALSE); CreateDate(&stNotAfter, (LPSTR) rgwchNotAfter, FALSE); _snprintf((LPSTR) rgwchValidity, sizeof(rgwchNotAfter), (LPSTR) rgwchFormat, rgwchNotBefore, rgwchNotAfter); #else // !MAC GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stNotBefore, NULL, (LPSTR) rgwchNotBefore, sizeof(rgwchNotBefore)); GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stNotAfter, NULL, (LPSTR) rgwchNotAfter, sizeof(rgwchNotAfter)); rgdw[0] = (DWORD_PTR) rgwchNotBefore; rgdw[1] = (DWORD_PTR) rgwchNotAfter; FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, rgwchFormat, 0, 0, (LPSTR) rgwchValidity, sizeof(rgwchValidity), (va_list *) rgdw); #endif // MAC SetDlgItemTextA(hwnd, id, (LPSTR) rgwchValidity); return TRUE; } #ifndef MAC GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stNotBefore, NULL, rgwchNotBefore, sizeof(rgwchNotBefore)/sizeof(WCHAR)); GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stNotAfter, NULL, rgwchNotAfter, sizeof(rgwchNotAfter)/sizeof(WCHAR)); LoadString(HinstDll, IDS_VALIDITY_FORMAT, rgwchFormat, sizeof(rgwchFormat)/sizeof(WCHAR)); rgdw[0] = (DWORD_PTR) rgwchNotBefore; rgdw[1] = (DWORD_PTR) rgwchNotAfter; FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, rgwchFormat, 0, 0, rgwchValidity, sizeof(rgwchValidity)/sizeof(WCHAR), (va_list *) rgdw); SetDlgItemText(hwnd, id, rgwchValidity); #endif // !MAC return TRUE; } //////////////////////////////////////////////////////////////////// //+------------------------------------------------------------------------- // Find the szOID_COMMON_NAME extension. // // If found, allocates and converts to a WCHAR string // // Returned WCHAR string needs to be CoTaskMemFree'ed. //-------------------------------------------------------------------------- static LPWSTR GetCommonNameExtension( IN PCCERT_CONTEXT pCert ) { LPWSTR pwsz = NULL; PCERT_INFO pCertInfo = pCert->pCertInfo; PCERT_NAME_VALUE pNameValue = NULL; PCERT_EXTENSION pExt; pExt = CertFindExtension( szOID_COMMON_NAME, pCertInfo->cExtension, pCertInfo->rgExtension ); if (pExt) { DWORD cbInfo = 0; PCERT_RDN_VALUE_BLOB pValue; DWORD dwValueType; DWORD cwsz; CryptDecodeObject( X509_ASN_ENCODING, X509_NAME_VALUE, pExt->Value.pbData, pExt->Value.cbData, 0, // dwFlags NULL, // pNameValue &cbInfo ); if (cbInfo == 0) goto CommonReturn; if (NULL == (pNameValue = (PCERT_NAME_VALUE) /*CoTaskMemAlloc(cbInfo)))*/ malloc(cbInfo))) goto CommonReturn; if (!CryptDecodeObject( X509_ASN_ENCODING, X509_NAME_VALUE, pExt->Value.pbData, pExt->Value.cbData, 0, // dwFlags pNameValue, &cbInfo)) goto CommonReturn; dwValueType = pNameValue->dwValueType; pValue = &pNameValue->Value; cwsz = CertRDNValueToStrW( dwValueType, pValue, NULL, // pwsz 0 // cwsz ); if (cwsz > 1) { pwsz = (LPWSTR) /*CoTaskMemAlloc(cwsz * sizeof(WCHAR))*/ malloc(cwsz*sizeof(WCHAR)); if (pwsz) CertRDNValueToStrW( dwValueType, pValue, pwsz, cwsz ); } } CommonReturn: if (pNameValue) /* CoTaskMemFree(pNameValue);*/ free(pNameValue); return pwsz; } //+------------------------------------------------------------------------- // Searches the name attributes for the first specified ObjId. // // If found, allocates and converts to a WCHAR string // // Returned WCHAR string needs to be CoTaskMemFree'ed. //-------------------------------------------------------------------------- static LPWSTR GetRDNAttrWStr( IN LPCSTR pszObjId, IN PCERT_NAME_BLOB pNameBlob ) { LPWSTR pwsz = NULL; PCERT_NAME_INFO pNameInfo = NULL; PCERT_RDN_ATTR pRDNAttr; DWORD cbInfo = 0; CryptDecodeObject( X509_ASN_ENCODING, X509_NAME, pNameBlob->pbData, pNameBlob->cbData, 0, // dwFlags NULL, // pNameInfo &cbInfo ); if (cbInfo == 0) goto CommonReturn; if (NULL == (pNameInfo = (PCERT_NAME_INFO) /*CoTaskMemAlloc(cbInfo)*/ malloc(cbInfo))) goto CommonReturn; if (!CryptDecodeObject( X509_ASN_ENCODING, X509_NAME, pNameBlob->pbData, pNameBlob->cbData, 0, // dwFlags pNameInfo, &cbInfo)) goto CommonReturn; pRDNAttr = CertFindRDNAttr(pszObjId, pNameInfo); if (pRDNAttr) { PCERT_RDN_VALUE_BLOB pValue = &pRDNAttr->Value; DWORD dwValueType = pRDNAttr->dwValueType; DWORD cwsz; cwsz = CertRDNValueToStrW( dwValueType, pValue, NULL, // pwsz 0 // cwsz ); if (cwsz > 1) { pwsz = (LPWSTR) /*CoTaskMemAlloc(cwsz * sizeof(WCHAR))*/ malloc(cwsz * sizeof(WCHAR)); if (pwsz) CertRDNValueToStrW( dwValueType, pValue, pwsz, cwsz ); } } CommonReturn: if (pNameInfo) /*CoTaskMemFree(pNameInfo);*/ free(pNameInfo); return pwsz; } LPWSTR PrettySubject(PCCERT_CONTEXT pccert) { DWORD cb; DWORD cch; BOOL f; LPWSTR pwsz; // // If the user has put a friendly name onto a certificate, then we // should display that as the pretty name for the certificate. // f = CertGetCertificateContextProperty(pccert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &cb); // cb includes terminating NULL if (f && (cb > sizeof(TCHAR))) { pwsz = (LPWSTR) malloc(cb); if (NULL != pwsz) { CertGetCertificateContextProperty(pccert, CERT_FRIENDLY_NAME_PROP_ID, pwsz, &cb); return pwsz; } } pwsz = GetCommonNameExtension(pccert); if (pwsz != NULL) { return pwsz; } pwsz = GetRDNAttrWStr(szOID_COMMON_NAME, &pccert->pCertInfo->Subject); if (pwsz != NULL) { return pwsz; } pwsz = GetRDNAttrWStr(szOID_RSA_emailAddr, &pccert->pCertInfo->Subject); if (pwsz != NULL) { return pwsz; } cch = CertNameToStr(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, NULL, 0); pwsz = (LPTSTR) malloc(cch*sizeof(TCHAR)); if (pwsz != NULL) { CertNameToStr(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Subject, CERT_SIMPLE_NAME_STR, pwsz, cch); } return pwsz; } LPWSTR PrettyIssuer(PCCERT_CONTEXT pccert) { DWORD cch; LPWSTR pwsz; // pwsz = GetCommonNameExtension(pccert); // if (pwsz != NULL) { // return pwsz; // } pwsz = GetRDNAttrWStr(szOID_COMMON_NAME, &pccert->pCertInfo->Issuer); if (pwsz != NULL) { return pwsz; } cch = CertNameToStr(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, NULL, 0); pwsz = (LPTSTR) malloc(cch*sizeof(TCHAR)); CertNameToStr(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Issuer, CERT_SIMPLE_NAME_STR, pwsz, cch); return pwsz; } LPWSTR PrettySubjectIssuer(PCCERT_CONTEXT pccert) { int cwsz; LPWSTR pwsz; LPWSTR pwszIssuer; LPWSTR pwszSubject; pwszSubject = PrettySubject(pccert); if (NULL == pwszSubject) { return NULL; } pwszIssuer = PrettyIssuer(pccert); if (NULL == pwszIssuer) { free(pwszSubject); return NULL; } cwsz = wcslen(pwszSubject) + wcslen(pwszIssuer) + 20; pwsz = (LPWSTR) malloc(cwsz*sizeof(WCHAR)); StrCpyNW(pwsz, pwszSubject, cwsz); #ifndef WIN16 StrCatBuffW(pwsz, L" (", cwsz); StrCatBuffW(pwsz, pwszIssuer, cwsz); StrCatBuffW(pwsz, L")", cwsz); #else StrCatBuffW(pwsz, " (", cwsz); StrCatBuffW(pwsz, pwszIssuer, cwsz); StrCatBuffW(pwsz, ")", cwsz); #endif free(pwszSubject); free(pwszIssuer); return pwsz; } #ifndef MAC BOOL OnContextHelp(HWND /*hwnd*/, UINT uMsg, WPARAM wParam, LPARAM lParam, HELPMAP const * rgCtxMap) { if (uMsg == WM_HELP) { LPHELPINFO lphi = (LPHELPINFO) lParam; if (lphi->iContextType == HELPINFO_WINDOW) { // must be for a control #ifndef WIN16 WinHelp ((HWND)lphi->hItemHandle, L"iexplore.hlp", HELP_WM_HELP, (ULONG_PTR)(LPVOID)rgCtxMap); #else WinHelp ((HWND)lphi->hItemHandle, "iexplore.hlp", HELP_WM_HELP, (ULONG_PTR)(LPVOID)rgCtxMap); #endif // !WIN16 } return (TRUE); } else if (uMsg == WM_CONTEXTMENU) { #ifndef WIN16 WinHelp ((HWND) wParam, L"iexplore.hlp", HELP_CONTEXTMENU, (ULONG_PTR)(LPVOID)rgCtxMap); #else WinHelp ((HWND) wParam, "iexplore.hlp", HELP_CONTEXTMENU, (ULONG_PTR)(LPVOID)rgCtxMap); #endif // !WIN16 return (TRUE); } return FALSE; } #endif // MAC ///////////////////////////////////////////////////////////////////////// //// GetFriendlyNameOfCertA // // Description: // This routine is an exported routine which can be used to get // a friendly name from a certificate. The function uses the // buffer supplied by the caller to store the formated name in. // This is the ANSI half of the function pair. // DWORD GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert, LPSTR pch, DWORD cch) { DWORD cch2; LPWSTR pwsz; // // Now do the normal pretty printing functionality. This allocates and // returns a buffer to the caller (us). // pwsz = PrettySubject(pccert); if (NULL == pwsz) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } // // Convert the returned string from a Unicode string to an ANSI string // cch2 = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, NULL, 0, NULL, NULL); if ((pch != NULL) && (cch2 <= cch)) { cch2 = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, pch, cch, NULL, NULL); } else if (pch != NULL) { SetLastError(ERROR_MORE_DATA); } free(pwsz); return cch2; } //// GetFriendlyNameOfCertW // // Description: // This routine is an exported routine which can be used to get // a friendly name from a certificate. The function uses the // buffer supplied by the caller to store the formated name in. // This is the UNICODE half of the function pair. // DWORD GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert, LPWSTR pwch, DWORD cwch) { DWORD cwch2; LPWSTR pwsz; // // Now do the normal pretty printing functionality. This allocates and // returns a buffer to the caller (us). // pwsz = PrettySubject(pccert); if (NULL == pwsz) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; } cwch2 = wcslen(pwsz) + 1; // // Duplicate the string into the provided buffer. // if ((pwch != NULL) && (cwch2 <= cwch)) { StrCpyNW(pwch, pwsz, cwch); } else if (pwch != NULL) { SetLastError(ERROR_MORE_DATA); } free(pwsz); return cwch2; } const BYTE mpchfLegalForURL[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x11, 0x01, 0x01, 0x01, 0x01, // 32 0x01, 0x11, 0x01, 0x01, 0x11, 0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 48 0x01, 0x01, 0x11, 0x01, 0x00, 0x01, 0x00, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 64 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 80 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 96 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 112 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; const char szURLSep[] = ":"; const char szURLCloseBrace[] = ">"; const char chURLOpenBrace = '<'; // ordered by match probability and string length const char g_szURLDefaultPrefixs[] = "http" "\0" "file" "\0" "ftp" "\0" "news" "\0" "mailto" "\0" "https" "\0" "gopher" "\0" "telnet" "\0" "nntp" "\0" "wais" "\0" "prospero\0\0"; LPSTR g_pszURLPrefixs = (LPSTR) g_szURLDefaultPrefixs; #define cchURLPrefixMost 28 BOOL g_fLoadBrowserRegistry = 1; TCHAR g_szBrowser[MAX_PATH]; COLORREF g_crLink = RGB(0, 0, 255); /* * NoteRecognizeURLs * * Purpose: * Change the charformat of text in the richedit control * for text that begins with http: ftp: or other. * * Arguments: * HWND A handle to the richedit control * fLoadBrowserRegistry Should we read the registry ? * * Returns: * VOID That would be nothing * * Notes: * * g_fLoadBrowserRegistry must be true on the first call * this may change g_szBrowser, g_crLink, and or g_pszURLPrefixs * g_pszURLPrefixs must equal g_szURLDefaultPrefixs, and must not be NULL * * if g_szBrowser, the path to the browser, is not found in the registry, * it will be defaulted to one of three things: !, url.dll, or iexplore * */ VOID RecognizeURLs(HWND hwndRE) { int isz; LONG cchBrace; LONG cpBraceSearch; LONG cpMatch; LONG cpSep; LONG cpEnd; LPSTR pch; CHARRANGE chrgSave; FINDTEXTEX ft; TEXTRANGEA tr; CHARFORMATA cf; char szBuff[MAX_PATH]; // szBuff must be at least cchURLPrefixMost LPSTR szT; LPARAM lNotifSuppression; #if MAX_PATH < cchURLPrefixMost #error MAX_PATH < cchURLPrefixMost #endif if (g_fLoadBrowserRegistry) { // INT cch; // signed to compare against 0 // hopefully we will not have to re-read // from the registry again, but a winini change // will force another read - see mlview shell.c g_fLoadBrowserRegistry = 0; #if 0 // if they change the default charformat // compute the hex stored color ref cch = GetMailRegistryString(imkeyURLColor, NULL, g_szBrowser, sizeof(g_szBrowser)); if (cch > 0) { LPTSTR psz = g_szBrowser; g_crLink = 0; for (; cch > 0; --cch, psz++) { g_crLink *= 16; if (*psz <= '9') g_crLink += *psz - TEXT('0'); else if (*psz <= 'F') g_crLink += *psz - TEXT('A') + 10; else g_crLink += *psz - TEXT('a') + 10; } } #endif // 0 #if 0 // grab the path to their browser, and // set the disable flag if appropriate cch = GetMailRegistryString(imkeyBrowser, NULL, g_szBrowser, sizeof(g_szBrowser)); if (cch <= 0) { #endif // 0 #ifndef MAC StrCpyN(g_szBrowser, TEXT("c:\\inetsrv\\iexplore\\iexplore.exe"), ARRAYSIZE(g_szBrowser)); #else // MAC StrCpyN(g_szBrowser, TEXT(":MSIE:APPL"), ARRAYSIZE(g_szBrowser)); #endif // !MAC #if 0 } #endif // 0 } // Prepare a few local variables for use szT = szBuff; cf.cbSize = sizeof(cf); ft.chrg.cpMin = 0; ft.chrg.cpMax = -1; // search the entire message body ft.lpstrText = (LPTSTR) szURLSep; // for a colon tr.lpstrText = szBuff; cf.cbSize = sizeof(cf); cf.dwMask = CFM_LINK; cf.dwEffects = 0; cpBraceSearch = 0; SendMessage(hwndRE, EM_EXGETSEL, 0, (LPARAM) &chrgSave); SendMessage(hwndRE, EM_HIDESELECTION, TRUE, FALSE); lNotifSuppression = SendMessage(hwndRE,EM_GETEVENTMASK,0,0); SendMessage(hwndRE, EM_SETEVENTMASK, (WPARAM) 0, 0); // remove existing link bits so that the user does not // get hosed when he/she saves text that was mistakenly marked // as linked ... gee, this SCF_ALL flag is a big perf win SendMessage(hwndRE, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf); // loop all the way to the bottom of the note // one iteration per find of a potential match // when we locate a colon for (;;) { LONG cpLast = 0; // find the colon cpSep = (LONG) SendMessage(hwndRE, EM_FINDTEXTEX, 0, (LPARAM) &ft); if (cpSep < 0) break; cpEnd = ft.chrgText.cpMax; ft.chrg.cpMin = cpEnd; // make sure the word to the left of the colon // is present and of a reasonable size cpMatch = (LONG) SendMessage(hwndRE, EM_FINDWORDBREAK, WB_MOVEWORDLEFT, ft.chrgText.cpMin); if (cpMatch == cpSep) continue; // sender of message is just being a jerk // so, do a quick check to avoid pathological cases if (cpMatch < cpSep - cchURLPrefixMost) { ft.chrg.cpMin = (LONG) SendMessage(hwndRE, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, cpSep); // Assert(ft.chrg.cpMin > cpSep); continue; } // pull the text of the keyword out into szBuff // to compare against our word list ... also grab // the character to the left in case we are // enclosed in matching braces cchBrace = 0; tr.chrg.cpMin = cpMatch - cchBrace; tr.chrg.cpMax = cpSep; if (!SendMessage(hwndRE, EM_GETTEXTRANGE, 0, (LPARAM) &tr)) goto end; // compare to each word in our list for (isz = 0; g_pszURLPrefixs[isz]; isz+=lstrlenA(g_pszURLPrefixs+isz)+1) { if (0 == lstrcmpiA(szBuff + cchBrace, &g_pszURLPrefixs[isz])) goto match; } continue; match: ft.chrgText.cpMin = cpMatch; cpLast = cpEnd; // assume that we will stop after the colon // check to see if this is the brace character if (cchBrace && chURLOpenBrace == szBuff[0]) { FINDTEXTEX ft; LONG cpBraceClose; ft.chrg.cpMin = max(cpEnd, cpBraceSearch); ft.chrg.cpMax = cpEnd + MAX_PATH; ft.lpstrText = (LPTSTR) szURLCloseBrace; cpBraceClose = (LONG) SendMessage(hwndRE, EM_FINDTEXTEX, 0, (LPARAM) &ft); if (cpBraceClose >= 0) { tr.chrg.cpMin = cpEnd; tr.chrg.cpMax = cpEnd + 1; if (!SendMessage(hwndRE, EM_GETTEXTRANGE, 0, (LPARAM) &tr) || ' ' == szBuff[0]) goto end; cpLast = cpEnd = ft.chrgText.cpMin; cpBraceSearch = cpLast + 1; goto end; } else { cpBraceSearch = ft.chrg.cpMax; } } // loop through chunks of the URL in // steps of sizeof(szBuff) looking for a terminator // set cpLast to the last terminator byte that is legal according to us for (;;) { tr.chrg.cpMin = cpLast = cpEnd; tr.chrg.cpMax = cpEnd + sizeof(szBuff) - 1; if (!SendMessage(hwndRE, EM_GETTEXTRANGE, 0, (LPARAM) &tr)) goto end; for (pch = szBuff; *pch; pch++, cpEnd++) { const BYTE fb = mpchfLegalForURL[*pch]; #ifdef DBCS if (!fb || FGLeadByte(*pch)) #else // DBCS if (!fb) #endif // DBCS { goto end; } if(!(fb & 0x10)) { cpLast = cpEnd + 1; } } } end: if (cpLast == cpSep + 1) // hmmm... just "http:" then terminator continue; // must have argument to be legal // select the entire URL including the http colon, // mark it as linked, and change the charformat if appropriate ft.chrgText.cpMax = cpLast; SendMessage(hwndRE, EM_EXSETSEL, 0, (LPARAM) &ft.chrgText); cf.dwMask = CFM_LINK | CFM_UNDERLINE | CFM_COLOR; if (((LONG)g_crLink) < 0) cf.dwMask &= ~CFM_UNDERLINE; /* high bit turns off underline */ if (((LONG)g_crLink) & 0x40000000) cf.dwMask &= ~CFM_COLOR; /* next bit turns off color */ cf.dwEffects = CFE_LINK | CFE_UNDERLINE; cf.crTextColor = g_crLink; SendMessage(hwndRE, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cf); // no need to re-search through the URL // so, just advance past the last totally cool URL character ft.chrg.cpMin = cpLast + 1; } // end loop through richedit text SendMessage(hwndRE, EM_EXSETSEL, 0, (LPARAM) &chrgSave); SendMessage(hwndRE, EM_HIDESELECTION, FALSE, FALSE); SendMessage(hwndRE, EM_SETEVENTMASK, (WPARAM) 0, (LPARAM) lNotifSuppression); return; } #ifndef MAC /* * FNoteDlgNotifyLink * * Purpose: * Handle the user clicking on a link * * Arguments: * hwndDlg Parent dialog * penlink Link notification structure * szURL URL to launch * * Returns: * BOOL TRUE if we processed message, else FALSE */ BOOL FNoteDlgNotifyLink(HWND hwndDlg, ENLINK * penlink, LPSTR szURL) { // BOOL fShift; LONG cch, cchBuffer; TEXTRANGEA tr; char szCmd[2*MAX_PATH + 2]; #ifdef MAC BOOL fPickedBrowser = FALSE; #endif HCURSOR hcursor; // eat the double click - just activate on single click if (WM_LBUTTONDBLCLK == penlink->msg) { return TRUE; } // if we got this far, we are enabled so assert that the path // does not explicitly say we should be disabled // below this point, we return true meaning that // we handled this message, and richedit should do nothing hcursor = SetCursor(LoadCursorA(NULL, (LPSTR) IDC_WAIT)); #ifndef MAC // prepare szCmd for use as the parameter to execution // AssertSz(sizeof(szCmd) > sizeof(g_szBrowser), "cat may overwrite"); wnsprintfA(szCmd, ARRAYSIZE(szCmd), "%s ", g_szBrowser); cch = lstrlenA(szCmd); tr.chrg.cpMin = penlink->chrg.cpMin; tr.chrg.cpMax = min((LONG) (tr.chrg.cpMin + sizeof(szCmd) - cch - 1), penlink->chrg.cpMax); cchBuffer = ARRAYSIZE(szCmd) - cch; tr.lpstrText = &szCmd[cch]; #else cch = 0; szCmd[0] = TEXT('\0'); tr.chrg.cpMin = penlink->chrg.cpMin; tr.chrg.cpMax = min((LONG) (tr.chrg.cpMin + sizeof(szCmd) - cch - 1), penlink->chrg.cpMax); cchBuffer = ARRAYSIZE(szCmd) - cch; tr.lpstrText = szCmd; #endif // add the web path to the command line if (szURL) { cch = lstrlenA(szURL); StrCpyNA(tr.lpstrText, szURL, cchBuffer); } else { cch = (LONG) SendMessage(penlink->nmhdr.hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM) &tr); } if (cch > 0) #ifndef MAC { HINSTANCE hinst; UINT ui; #if defined(WIN32) && !defined(MAC) SetProcessWorkingSetSize(GetCurrentProcess(), 0xffffffff, 0xffffffff); #endif // execute the browser, however the current operating system wants to ... hinst = ShellExecuteA(hwndDlg, NULL, tr.lpstrText, NULL, NULL, SW_SHOWNORMAL); if ((UINT_PTR) hinst > 32) { SetCursor(hcursor); return TRUE; } // the operating system failed to launch the browser, let me try ... ui = WinExec(szCmd, SW_SHOW); if (ui < 32) { // perhaps they moved or deleted their executable regardless // of the error, we will just browse for a path // this is currently by design MessageBeep(MB_OK); SetCursor(hcursor); return FALSE; } } SetCursor(hcursor); return TRUE; #else // MAC { HWND hwndActive; ProcessSerialNumber psn; AppleEvent aeEvent = { 0 }; AppleEvent aeReply = { 0 }; AEAddressDesc aedAddr = { 0 }; AEEventClass aecOpenURL = 'WWW!'; AEEventID aeidOpenURL = 'OURL'; OSErr errLaunch = icPrefNotFoundErr; OSType ostBrowser; OSType ostType; SCODE sc = S_OK; TCHAR szCaption[MAX_PATH]; // Prompt the user to see if we can open the URL safely hwndActive = GetActiveWindow(); if (!GetWindowText(hwndActive, szCaption, (sizeof(szCaption) / sizeof(TCHAR)))) { szCaption[0] = TEXT('\0'); } if (!FIsSafeURL(hwndActive, tr.lpstrText, szCaption)) { goto Exit; } // See if we have an Internet Config instance if (INST(picinstIConfig) != NULL) { ICAppSpec icappHelper = { 0 }; ICAttr icattr; LONG lSize; Str255 strHelper = kICHelper; TCHAR* pchHelper; TCHAR* pchURL; // Locate the end of the Helper string and add the protocol // from the URL pchHelper = strHelper + (sizeof(kICHelper) - 1); pchURL = tr.lpstrText; while ((*pchURL != TEXT('\0')) && (*pchURL != TEXT(':'))) { *pchHelper = *pchURL; pchURL++; pchHelper++; strHelper[0]++; } // Call Internet Config to see if we have a helper for this // protocol defined lSize = sizeof(ICAppSpec); errLaunch = (OSErr)ICGetPref(INST(picinstIConfig), strHelper, &icattr, (LPBYTE)&icappHelper, &lSize); if (errLaunch == noErr) { // Got a helper application, extract the information needed // to launch the correct helper with a GURL event ostBrowser = icappHelper.fCreator; aecOpenURL = 'GURL'; aeidOpenURL = 'GURL'; } } // If we do not have an error at this point that means that Internet // Config found the helper. Otherwise, we need to look in the // standard preferences for the browser. if (errLaunch != noErr) { // Create a Mac OSType from the browser string if (!FMacSignatureFromMacInfo(g_szBrowser, NULL, &ostBrowser, &ostType)) { goto Exit; } } // If Exchange is the designated helper we want to avoid the expense // of using AppleEvents if (ostBrowser != 'EXCH') { // Set up the AppleEvent errLaunch = AECreateDesc(typeApplSignature, &ostBrowser, sizeof(OSType), &aedAddr); if (errLaunch != noErr) { goto CleanupAEvent; } // Create the AppleEvent to send to the web browser errLaunch = AECreateAppleEvent(aecOpenURL, aeidOpenURL, &aedAddr, kAutoGenerateReturnID, kAnyTransactionID, &aeEvent); if (errLaunch != noErr) { goto CleanupAEvent; } // Add the URL as the direct parameter errLaunch = AEPutParamPtr(&aeEvent, keyDirectObject, typeChar, tr.lpstrText, _tcslen(tr.lpstrText)); if (errLaunch != noErr) { goto CleanupAEvent; } // Get a running instance of the browser so that we have something // to actually process our event and send it the open command. errLaunch = ErrLaunchCreatorEx(ostBrowser, launchContinue | launchUseMinimum, &aeEvent, kAEWaitReply | kAEAlwaysInteract, &aeReply, NULL, &psn); if (errLaunch != noErr) { #if 0 // If we could not launch the browser because it was not // found, we need to try and choose a browser to use, // otherwise we just ignore the error and fail gracefully. if ((errLaunch == fnfErr) && (!fPickedBrowser)) { fPickedBrowser = TRUE; SetCursor(hcursor); goto pick; } #endif // 0 goto CleanupAEvent; } ErrSetFrontProcess(&psn); CleanupAEvent: AEDisposeDesc(&aeEvent); AEDisposeDesc(&aeReply); AEDisposeDesc(&aedAddr); } else { LPIEDATA pieData = NULL; LPTSTR pszURL = NULL; LONG iProtocol; ULONG cchText; // Allocate a buffer to store the URL in cchText = _tcslen(tr.lpstrText)+1; pszURL = PvAlloc((cchText * sizeof(TCHAR)), fZeroFill); if (pszURL == NULL) { goto CleanupIEData; } StrCpyN(pszURL, tr.lpstrText, cchText); // Make sure this is a protocol supported by Exchange for (iProtocol = 0; iProtocol < g_lNumIESupProtocols; iProtocol++) { if (_tcsncmp(pszURL, g_iesupMac[iProtocol].szProtocol, _tcslen(g_iesupMac[iProtocol].szProtocol)) == 0) { // Found a match break; } } if (iProtocol == g_lNumIESupProtocols) { // No match found goto CleanupIEData; } // Create the appropriate IEDATA structure pieData = PvAlloc(sizeof(IEDATA), fZeroFill); if (pieData == NULL) { goto CleanupIEData; } pieData->szURL = pszURL; pieData->idxProtocol = iProtocol; // Post an internal message to ourselves to actually do the // processing PostMessage(INST(hwndCentral), EXIE_OPENURL, 0, (LPARAM)pieData); goto Exit; CleanupIEData: if (pszURL != NULL) { FreePv(pszURL); } if (pieData != NULL) { FreePv(pieData); } } } Exit: SetCursor(hcursor); return TRUE; #endif // !MAC } #endif // !MAC ///////////////////////////////////////////////////////////////////////// // // This code provides the first cut of the Verisign Cert Policy Statement // implemenation code. This should be replaced in the next version by // the correct version of this code. It is suppose to read a multi- // language file and pick up the correct version according to // the machine's lanaguage // #ifndef WIN16 WCHAR RgwchVerisign[] = L"This certificate incorporates by reference, and its use is strictly subject " L"to, the VeriSign Certification Practice Statement (CPS), available in the " L"VeriSign repository at: https://www.verisign.com by E-mail at " L"CPS-requests@verisign.com; or by mail at VeriSign, Inc., 1390 Shorebird " L"Way, Mountain View, CA 94043 USA Copyright (c)1997 VeriSign, Inc. All " L"Rights Reserved. CERTAIN WARRANTIES DISCLAIMED AND LIABILITY LIMITED.\n" L"\n" L"WARNING: USE OF THIS CERTIFICATE IS STRICTLY SUBJECT TO THE VERISIGN " L"CERTIFICATION PRACTICE STATEMENT. THE ISSUING AUTHORITY DISCLAIMS CERTAIN " L"IMPLIED AND EXPRESS WARRANTIES, INCLUDING WARRANTIES OF MERCHANTABILITY OR " L"FITNESS FOR A PARTICULAR PURPOSE, AND WILL NOT BE LIABLE FOR CONSEQUENTIAL, " L"PUNITIVE, AND CERTAIN OTHER DAMAGES. SEE THE CPS FOR DETAILS.\n" L"\n" L"Contents of the VeriSign registered nonverifiedSubjectAttribute extension " L"value shall not be considered as information confirmed by the IA."; #else WCHAR RgwchVerisign[] = "This certificate incorporates by reference, and its use is strictly subject " "to, the VeriSign Certification Practice Statement (CPS), available in the " "VeriSign repository at: https://www.verisign.com; by E-mail at " "CPS-requests@verisign.com; or by mail at VeriSign, Inc., 1390 Shorebird " "Way, Mountain View, CA 94043 USA Copyright (c)1997 VeriSign, Inc. All " "Rights Reserved. CERTAIN WARRANTIES DISCLAIMED AND LIABILITY LIMITED.\n" "\n" "WARNING: USE OF THIS CERTIFICATE IS STRICTLY SUBJECT TO THE VERISIGN " "CERTIFICATION PRACTICE STATEMENT. THE ISSUING AUTHORITY DISCLAIMS CERTAIN " "IMPLIED AND EXPRESS WARRANTIES, INCLUDING WARRANTIES OF MERCHANTABILITY OR " "FITNESS FOR A PARTICULAR PURPOSE, AND WILL NOT BE LIABLE FOR CONSEQUENTIAL, " "PUNITIVE, AND CERTAIN OTHER DAMAGES. SEE THE CPS FOR DETAILS.\n" "\n" "Contents of the VeriSign registered nonverifiedSubjectAttribute extension " "value shall not be considered as information confirmed by the IA."; #endif // !WIN16 BOOL WINAPI FormatVerisignExtension( DWORD /*dwCertEncodingType*/, DWORD /*dwFormatType*/, DWORD /*dwFormatStrType*/, void * /*pFormatStruct*/, LPCSTR /*lpszStructType*/, const BYTE * /*pbEncoded*/, DWORD /*cbEncoded*/, void * pbFormat, DWORD * pcbFormat) { if (pbFormat == NULL) { *pcbFormat = sizeof(RgwchVerisign); return TRUE; } if (*pcbFormat < sizeof(RgwchVerisign)) { *pcbFormat = sizeof(RgwchVerisign); return FALSE; } memcpy(pbFormat, RgwchVerisign, sizeof(RgwchVerisign)); return TRUE; } BOOL WINAPI FormatPKIXEmailProtection( DWORD /*dwCertEncodingType*/, DWORD /*dwFormatType*/, DWORD /*dwFormatStrType*/, void * /*pFormatStruct*/, LPCSTR /*lpszStructType*/, const BYTE * /*pbEncoded*/, DWORD /*cbEncoded*/, void * pbFormat, DWORD * pcbFormat) { DWORD cch; WCHAR rgwch[256]; cch = LoadString(HinstDll, IDS_EMAIL_DESC, rgwch, sizeof(rgwch)/sizeof(WCHAR)); if (pbFormat == NULL) { *pcbFormat = (cch+1)*sizeof(WCHAR); return TRUE; } if (*pcbFormat < (cch+1)*sizeof(WCHAR)) { *pcbFormat = (cch+1)*sizeof(WCHAR); return FALSE; } memcpy(pbFormat, rgwch, (cch+1)*sizeof(WCHAR)); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // // This is an encoder which should really be in crypt32 -- however I don't // want to force a drop of crypt32 just to get it. // BOOL WINAPI EncodeAttrSequence(DWORD /*dwType*/, LPCSTR /*lpszStructType*/, const void * pv, LPBYTE pbEncode, DWORD * pcbEncode) { DWORD cb; DWORD dw; BOOL fRet; DWORD i; PCRYPT_ATTRIBUTES pattrs = (PCRYPT_ATTRIBUTES) pv; LPBYTE pb = NULL; CRYPT_SEQUENCE_OF_ANY seq = {0}; UNALIGNED void * pAttr = NULL; // // Allocate something to hold the result of each attribute's encoding // seq.rgValue = (PCRYPT_DER_BLOB) malloc(pattrs->cAttr * sizeof(CRYPT_DER_BLOB)); if (seq.rgValue == NULL) { dw = ERROR_NOT_ENOUGH_MEMORY; goto ErrorExit; } // // Now encode each of the attributes in turn // for (i=0; icAttr; i++) { pAttr =((UNALIGNED void *) &(pattrs->rgAttr[i])); if (!CryptEncodeObject(X509_ASN_ENCODING, PKCS_ATTRIBUTE, pAttr, NULL, &cb) || (cb == 0)) { fRet = FALSE; goto Clean; } pb = (LPBYTE) malloc(LcbAlignLcb(cb)); if (!CryptEncodeObject(X509_ASN_ENCODING, PKCS_ATTRIBUTE, pAttr, pb, &cb)) { fRet = FALSE; goto Clean; } seq.cValue = i+1; seq.rgValue[i].cbData = cb; seq.rgValue[i].pbData = pb; pb = NULL; } // // Now lets encode the sequence // fRet = CryptEncodeObject(X509_ASN_ENCODING, X509_SEQUENCE_OF_ANY, &seq, pbEncode, pcbEncode); Clean: for (i=0; icValue; i++) { if (!CryptDecodeObject(X509_ASN_ENCODING, PKCS_ATTRIBUTE, pseq->rgValue[i].pbData, pseq->rgValue[i].cbData, 0, NULL, &cb)) { fRet = FALSE; goto Exit; } cb = LcbAlignLcb(cb); if (cb > cbMax) cbMax = cb; cbOut += cb; } if (pvStruct == NULL) { *pcbStruct = cbOut; fRet = TRUE; goto Exit; } if (*pcbStruct < cbOut) { *pcbStruct = cbOut; SetLastError(ERROR_MORE_DATA); goto Exit; } // // Now we are going to actually try and compute the real data. // // First we need a buffer to put each attribute in as we are looking at it // pattr = (PCRYPT_ATTRIBUTE) malloc(LcbAlignLcb(cbMax)); if (pattr == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto Exit; } pattrs->cAttr = pseq->cValue; pattrs->rgAttr = (PCRYPT_ATTRIBUTE) (((LPBYTE) pvStruct) + sizeof(CRYPT_ATTRIBUTES)); pbOut = ((LPBYTE) pvStruct + LcbAlignLcb(sizeof(CRYPT_ATTRIBUTES) + pseq->cValue * sizeof(CRYPT_ATTRIBUTE))); for (i=0; icValue; i++) { // // Decode one attribute // cb = cbMax; if (!CryptDecodeObject(X509_ASN_ENCODING, PKCS_ATTRIBUTE, pseq->rgValue[i].pbData, pseq->rgValue[i].cbData, 0, pattr, &cb)) { goto Exit; } // // Copy to real output buffer // pattrs->rgAttr[i].pszObjId = (LPSTR) pbOut; cb = lstrlenA(pattr->pszObjId) + 1; memcpy(pbOut, pattr->pszObjId, cb); pbOut += LcbAlignLcb(cb); pattrs->rgAttr[i].cValue = pattr->cValue; pattrs->rgAttr[i].rgValue = (PCRYPT_ATTR_BLOB) pbOut; pbOut += LcbAlignLcb(sizeof(CRYPT_ATTR_BLOB) * pattr->cValue); for (i1=0; i1cValue; i1++) { #ifndef _WIN64 pattrs->rgAttr[i].rgValue[i1].cbData = pattr->rgValue[i1].cbData; pattrs->rgAttr[i].rgValue[i1].pbData = pbOut; #else pVal = &(pattrs->rgAttr[i].rgValue[i1]); pVal->cbData = pattr->rgValue[i1].cbData; pVal->pbData = pbOut; #endif //_WIN64 memcpy(pbOut, pattr->rgValue[i1].pbData, pattr->rgValue[i1].cbData); pbOut += LcbAlignLcb(pattr->rgValue[i1].cbData); } } fRet = TRUE; Exit: if (pattr != NULL) free(pattr); if (pseq != NULL) free(pseq); return fRet; } // OIDs 1.3.6.1.4.1.311.16.4 BOOL WINAPI EncodeRecipientID(DWORD dwType, LPCSTR /*lpszStructType*/, const void * pv, LPBYTE pbEncode, DWORD * pcbEncode) { DWORD cbInt; BOOL f; LPBYTE pbInt = NULL; CRYPT_RECIPIENT_ID * prid = (CRYPT_RECIPIENT_ID *) pv; CRYPT_DER_BLOB rgValue[2]; CRYPT_SEQUENCE_OF_ANY seq = {0, rgValue}; if (prid->unused != 0) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } f = CryptEncodeObject(dwType, X509_MULTI_BYTE_INTEGER, &prid->SerialNumber, NULL, &cbInt); if (!f) goto ExitHere; pbInt = (LPBYTE) malloc(cbInt); if (pbInt == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); f = FALSE; goto ExitHere; } f = CryptEncodeObject(dwType, X509_MULTI_BYTE_INTEGER, &prid->SerialNumber, pbInt, &cbInt); seq.cValue = 2; seq.rgValue[0].cbData = prid->Issuer.cbData; seq.rgValue[0].pbData = prid->Issuer.pbData; seq.rgValue[1].cbData = cbInt; seq.rgValue[1].pbData = pbInt; f = CryptEncodeObject(dwType, X509_SEQUENCE_OF_ANY, &seq, pbEncode, pcbEncode); ExitHere: if (pbInt != NULL) free(pbInt); return f; } BOOL WINAPI DecodeRecipientID(DWORD dwType, LPCSTR /*lpszStructType*/, const BYTE * pbEncoded, DWORD cbEncoded, DWORD dwFlags, void * pvStruct, DWORD * pcbStruct) { DWORD cb; DWORD cbOut; BOOL fRet = FALSE; CRYPT_INTEGER_BLOB * pInt = NULL; CRYPT_RECIPIENT_ID * prid = (CRYPT_RECIPIENT_ID *) pvStruct; CRYPT_SEQUENCE_OF_ANY * pseq = NULL; // Decode the top level sequence first fRet = CryptDecodeObjectEx(dwType, X509_SEQUENCE_OF_ANY, pbEncoded, cbEncoded, dwFlags | CRYPT_ENCODE_ALLOC_FLAG, NULL, &pseq, &cb); if (!fRet) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto Exit; } // Assert(pseq->cValue == 2); // Decode integer fRet = CryptDecodeObjectEx(dwType, X509_MULTI_BYTE_INTEGER, pseq->rgValue[1].pbData, pseq->rgValue[1].cbData, dwFlags | CRYPT_ENCODE_ALLOC_FLAG, NULL, &pInt, &cb); if (!fRet) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto Exit; } // Compute length needed for the return value cbOut = (sizeof(CRYPT_RECIPIENT_ID) + pseq->rgValue[0].cbData + pInt->cbData); if ((*pcbStruct < cbOut) || (pvStruct == NULL)) { *pcbStruct = cbOut; SetLastError(ERROR_MORE_DATA); fRet = (pvStruct == NULL); goto Exit; } // Now copy the data over prid->unused = 0; prid->Issuer.cbData = pseq->rgValue[0].cbData; prid->Issuer.pbData = sizeof(*prid) + (LPBYTE) prid; memcpy(prid->Issuer.pbData, pseq->rgValue[0].pbData, prid->Issuer.cbData); prid->SerialNumber.cbData = pInt->cbData; prid->SerialNumber.pbData = prid->Issuer.pbData + prid->Issuer.cbData; memcpy(prid->SerialNumber.pbData, pInt->pbData, pInt->cbData); fRet = TRUE; Exit: if (pInt != NULL) LocalFree(pInt); if (pseq != NULL) LocalFree(pseq); return fRet; } //////////////////////////////////////////////////////////////////////////// extern const GUID rgguidActions[] = { CERT_CERTIFICATE_ACTION_VERIFY }; #define REGSTR_PATH_SERVICES "System\\CurrentControlSet\\Services" #ifdef NT5BUILD #else // NT5BUILD const char SzRegPath[] = REGSTR_PATH_SERVICES "\\WinTrust\\TrustProviders\\Email Trust"; const char SzActionIds[] = "$ActionIDs"; const char SzDllName[] = "$DLL"; #endif // !NT5BUILD extern const GUID GuidCertValidate = CERT_CERTIFICATE_ACTION_VERIFY; #ifndef MAC STDAPI DllRegisterServer(void) { #ifdef NT5BUILD HRESULT hr = S_OK; #else // !NT5BUILD DWORD dwDisposition; HKEY hkey; UINT cchSystemDir; BOOL fIsWinNt = FALSE; // M00BUG HRESULT hr = S_OK; LPSTR psz; CHAR rgchLibName[] = "cryptdlg.dll"; CHAR rgchPathName[MAX_PATH + sizeof(rgchLibName)]; #endif // NT5BUILD // // First we register the funny one time function which is currently // hard-coded to go to a fixed verisign statement. This should be removed // if we can get a general purpose one running. // #ifndef WIN16 if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, "2.5.29.32", L"cryptdlg.dll", "FormatVerisignExtension")) { return E_FAIL; } if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, szOID_PKIX_KP_EMAIL_PROTECTION, L"cryptdlg.dll", "FormatPKIXEmailProtection")) { return E_FAIL; } if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, "1.3.6.1.4.1.311.16.1.1", L"cryptdlg.dll", "EncodeAttrSequence")) { return E_FAIL; } if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, "1.3.6.1.4.1.311.16.1.1", L"cryptdlg.dll", "DecodeAttrSequence")) { return E_FAIL; } if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, szOID_MICROSOFT_Encryption_Key_Preference, L"cryptdlg.dll", "EncodeRecipientID")) { return E_FAIL; } if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, szOID_MICROSOFT_Encryption_Key_Preference, L"cryptdlg.dll", "DecodeRecipientID")) { return E_FAIL; } #else if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, "2.5.29.32", "cryptdlg.dll", "FormatVerisignExtension")) { return E_FAIL; } if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, szOID_PKIX_KP_EMAIL_PROTECTION, "cryptdlg.dll", "FormatPKIXEmailProtection")) { return E_FAIL; } if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, "1.3.6.1.4.1.311.16.1.1", "cryptdlg.dll", "EncodeAttrSequence")) { return E_FAIL; } if (!CryptRegisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, "1.3.6.1.4.1.311.16.1.1", "cryptdlg.dll", "DecodeAttrSequence")) { return E_FAIL; } #endif // !WIN16 #ifdef NT5BUILD CRYPT_REGISTER_ACTIONID regdata; regdata.cbStruct = sizeof(regdata); regdata.sInitProvider.cbStruct = sizeof(regdata.sInitProvider); regdata.sInitProvider.pwszDLLName = L"Cryptdlg.dll"; regdata.sInitProvider.pwszFunctionName = L"CertTrustInit"; regdata.sObjectProvider.cbStruct = sizeof(regdata.sObjectProvider); regdata.sObjectProvider.pwszDLLName = NULL; regdata.sObjectProvider.pwszFunctionName = NULL; regdata.sSignatureProvider.cbStruct = sizeof(regdata.sSignatureProvider); regdata.sSignatureProvider.pwszDLLName = NULL; regdata.sSignatureProvider.pwszFunctionName = NULL; regdata.sCertificateProvider.cbStruct = sizeof(regdata.sCertificateProvider); regdata.sCertificateProvider.pwszDLLName = WT_PROVIDER_DLL_NAME; regdata.sCertificateProvider.pwszFunctionName = WT_PROVIDER_CERTTRUST_FUNCTION; regdata.sCertificatePolicyProvider.cbStruct = sizeof(regdata.sCertificatePolicyProvider); regdata.sCertificatePolicyProvider.pwszDLLName = L"Cryptdlg.dll"; regdata.sCertificatePolicyProvider.pwszFunctionName = L"CertTrustCertPolicy"; regdata.sFinalPolicyProvider.cbStruct = sizeof(regdata.sFinalPolicyProvider); regdata.sFinalPolicyProvider.pwszDLLName = L"Cryptdlg.dll"; regdata.sFinalPolicyProvider.pwszFunctionName = L"CertTrustFinalPolicy"; regdata.sTestPolicyProvider.cbStruct = sizeof(regdata.sTestPolicyProvider); regdata.sTestPolicyProvider.pwszDLLName = NULL; regdata.sTestPolicyProvider.pwszFunctionName = NULL; regdata.sCleanupProvider.cbStruct = sizeof(regdata.sCleanupProvider); regdata.sCleanupProvider.pwszDLLName = L"Cryptdlg.dll"; regdata.sCleanupProvider.pwszFunctionName = L"CertTrustCleanup"; WintrustAddActionID((GUID *) &GuidCertValidate, 0, ®data); #else // !NT5BUILD // // Next register the fact that we are also a wintrust provider for // validating certificates // hr = RegCreateKeyExA(HKEY_LOCAL_MACHINE, SzRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dwDisposition); if (hr != ERROR_SUCCESS) { goto RetHere; } // BUGBUG Win95 does not support REG_EXPAND_SZ, so we must do it if (fIsWinNt) { psz = "%SystemRoot%\\system32\\cryptdlg.dll"; } else { // Compose the path as \cryptdlg.dll #ifndef WIN16 cchSystemDir = GetSystemDirectoryA(rgchPathName, MAX_PATH); #else cchSystemDir = GetSystemDirectory(rgchPathName, MAX_PATH); #endif // !WIN16 if (cchSystemDir == 0) { hr = E_FAIL; goto RetHere; } else if (cchSystemDir > MAX_PATH) { hr = ERROR_INSUFFICIENT_BUFFER; goto RetHere; } rgchPathName[cchSystemDir] = '\\'; // system dir can't be a root StrCpyN(&rgchPathName[cchSystemDir+1], rgchLibName, ARRAYSIZE(rgchPathName)-(cchSystemDir+1)); psz = rgchPathName; } #ifndef WIN16 hr = RegSetValueExA(hkey, SzDllName, 0, fIsWinNt ? REG_EXPAND_SZ : REG_SZ, (LPBYTE) psz, strlen(psz)+1); #else hr = RegSetValueExA(hkey, SzDllName, 0, REG_SZ, (LPBYTE) psz, strlen(psz)+1); #endif // !WIN16 if (hr != ERROR_SUCCESS) { goto RetHere; } hr = RegSetValueExA(hkey, SzActionIds, 0, REG_BINARY, (LPBYTE) rgguidActions, sizeof(rgguidActions)); if (hr != ERROR_SUCCESS) { goto RetHere; } RetHere: // NB - Don't do RegCloseKey on these hkey's since we want to be small // and this code is only ever called by REGSRV32.EXE, so we don't // care about a minor leak. #endif // NT5BUILD return hr; } STDAPI DllUnregisterServer(void) { #ifndef NT5BUILD DWORD dw; HKEY hkey; #endif // NT5BUILD HRESULT hr = S_OK; // // Unregister the formatting routine we wrote // if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, "2.5.29.32")) { if (ERROR_FILE_NOT_FOUND != GetLastError()) { hr = E_FAIL; } } if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_FORMAT_OBJECT_FUNC, szOID_PKIX_KP_EMAIL_PROTECTION)) { if (ERROR_FILE_NOT_FOUND != GetLastError()) { hr = E_FAIL; } } if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, "1.3.6.1.4.1.311.16.1.1")) { if (ERROR_FILE_NOT_FOUND != GetLastError()) { hr = E_FAIL; } } if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, "1.3.6.1.4.1.311.16.1.1")) { if (ERROR_FILE_NOT_FOUND != GetLastError()) { hr = E_FAIL; } } if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_ENCODE_OBJECT_FUNC, szOID_MICROSOFT_Encryption_Key_Preference)) { if (ERROR_FILE_NOT_FOUND != GetLastError()) { hr = E_FAIL; } } if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING, CRYPT_OID_DECODE_OBJECT_FUNC, szOID_MICROSOFT_Encryption_Key_Preference)) { if (ERROR_FILE_NOT_FOUND != GetLastError()) { hr = E_FAIL; } } #ifdef NT5BUILD WintrustRemoveActionID((GUID *) &GuidCertValidate); #else // !NT5BUILD // // Now unregister the WinTrust provider // hr = RegCreateKeyExA(HKEY_LOCAL_MACHINE, SzRegPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw); if (FAILED(hr)) { goto RetHere; } RegDeleteValueA(hkey, SzDllName); RegDeleteValueA(hkey, SzActionIds); RetHere: // NB - Don't do RegCloseKey on these hkey's since we want to be small // and this code is only ever called by REGSRV32.EXE, so we don't // care about a minor leak. #endif // NT5BUILD return hr; } #else // MAC /*** *wchar_t *wcsstr(string1, string2) - search for string2 in string1 * (wide strings) * *Purpose: * finds the first occurrence of string2 in string1 (wide strings) * *Entry: * wchar_t *string1 - string to search in * wchar_t *string2 - string to search for * *Exit: * returns a pointer to the first occurrence of string2 in * string1, or NULL if string2 does not occur in string1 * *Uses: * *Exceptions: * *******************************************************************************/ wchar_t * __cdecl WchCryptDlgWcsStr ( const wchar_t * wcs1, const wchar_t * wcs2 ) { wchar_t *cp = (wchar_t *) wcs1; wchar_t *s1, *s2; while (*cp) { s1 = cp; s2 = (wchar_t *) wcs2; while ( *s1 && *s2 && !(*s1-*s2) ) s1++, s2++; if (!*s2) return(cp); cp++; } return(NULL); } #endif // !MAC /////////////////////////////////////////////////////////////////////// LPVOID PVCryptDecode(LPCSTR szOid, DWORD cbEncode, LPBYTE pbEncode) { DWORD cbData; BOOL f; LPVOID pv; f = CryptDecodeObject(X509_ASN_ENCODING, szOid, pbEncode, cbEncode, 0, NULL, &cbData); if (!f) { return NULL; } pv = malloc(cbData); if (pv == NULL) { return NULL; } f = CryptDecodeObject(X509_ASN_ENCODING, szOid, pbEncode, cbEncode, 0, pv, &cbData); if (!f) { free(pv); return NULL; } return pv; } void * __cdecl operator new(size_t cb ) { LPVOID lpv = 0; lpv = malloc(cb); if (lpv) { memset(lpv, 0, cb); } return lpv; } void __cdecl operator delete(LPVOID pv ) { free(pv); }