Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2797 lines
84 KiB

#include "pch.hxx"
#include "demand.h"
#include <string.h>
#include <shellapi.h>
#include <commctrl.h>
#include <limits.h>
//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 <stdio.h>
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<cArgs; i++) {
if (pdw[i] == 0xffffffff) {
cArgs = i-1;
break;
}
if (pdw[i] <= 0xffff) {
rgdwArgs[i] = pdw[i];
}
else {
cch = wcslen((LPWSTR) pdw[i]);
rgdwArgs[i] = (DWORD_PTR) malloc((cch+1));
WideCharToMultiByte(CP_ACP, 0, (LPWSTR) pdw[i], -1,
(LPSTR) rgdwArgs[i], cch+1, NULL, NULL);
}
}
if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
WideCharToMultiByte(CP_ACP, 0, (LPWSTR) pbSource, -1,
rgchSource, sizeof(rgchSource), NULL, NULL);
pbSource = rgchSource;
}
#ifdef MAC
dwLangId; // Unused
dwMessageId; // Unused
hr = TdxFormatMessageVa ((LPCSTR) pbSource, NULL, &cch, (va_list) rgdwArgs);
if (FAILED(hr))
{
return 0;
}
pchDest = (LPSTR) LocalAlloc(LMEM_FIXED, cch + 1);
if (NULL == pchDest)
{
return 0;
}
hr = TdxFormatMessageVa ((LPCSTR) pbSource, pchDest, &cch, (va_list) rgdwArgs);
if (FAILED(hr))
{
LocalFree(pchDest);
return 0;
}
#else // !MAC
cch = FormatMessageA(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER, pbSource,
dwMessageId, dwLangId, (LPSTR) &pchDest, 0,
(va_list *) rgdwArgs);
#endif // MAC
if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
cch = MultiByteToWideChar(CP_ACP, 0, pchDest, -1, NULL, 0);
pwchOut = (LPWSTR) LocalAlloc(LMEM_FIXED, (cch+1)*sizeof(WCHAR));
cch = MultiByteToWideChar(CP_ACP, 0, pchDest, -1, pwchOut, cch);
*((LPWSTR *) lpBuffer) = pwchOut;
}
else {
cch = MultiByteToWideChar(CP_ACP, 0, pchDest, -1, lpBuffer, nSize);
}
for (i=0; i<cArgs; i++) {
if (rgdwArgs[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<cb; i++, pwch += 2) {
pwch[0] = RgwchHex[(rgb[i] & 0xf0) >> 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"[email protected]; 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 "
"[email protected]; 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; i<pattrs->cAttr; 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; i<seq.cValue; i++) free(seq.rgValue[i].pbData);
if (seq.rgValue != NULL) free(seq.rgValue);
if (pb != NULL) free(pb);
return fRet;
ErrorExit:
SetLastError(dw);
fRet = FALSE;
goto Clean;
}
BOOL WINAPI
DecodeAttrSequence(DWORD /*dwType*/, LPCSTR /*lpszStructType*/,
const BYTE * pbEncoded, DWORD cbEncoded,
DWORD /*dwFlags*/, void * pvStruct,
DWORD * pcbStruct)
{
DWORD cb;
DWORD cbMax = 0;
DWORD cbOut;
BOOL fRet = FALSE;
DWORD i;
DWORD i1;
PCRYPT_ATTRIBUTE pattr = NULL;
PCRYPT_ATTRIBUTES pattrs = (PCRYPT_ATTRIBUTES) pvStruct;
LPBYTE pbOut = NULL;
PCRYPT_SEQUENCE_OF_ANY pseq = NULL;
#ifdef _WIN64
UNALIGNED CRYPT_ATTR_BLOB *pVal = NULL;
#endif
//
// Decode the top level sequence
//
if (!CryptDecodeObject(X509_ASN_ENCODING, X509_SEQUENCE_OF_ANY,
pbEncoded, cbEncoded, 0, NULL, &cb)) {
goto Exit;
}
pseq = (PCRYPT_SEQUENCE_OF_ANY) malloc(cb);
if (pseq == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Exit;
}
if (!CryptDecodeObject(X509_ASN_ENCODING, X509_SEQUENCE_OF_ANY,
pbEncoded, cbEncoded, 0, pseq, &cb)) {
goto Exit;
}
//
// Decode each attribute for length
//
cbOut = sizeof(CRYPT_ATTRIBUTES);
for (i=0; i<pseq->cValue; 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; i<pseq->cValue; 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; i1<pattr->cValue; 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, &regdata);
#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 <system_dir>\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);
}