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
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, ®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 <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);
|
|
}
|