338 lines
10 KiB
C++
338 lines
10 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: linkutil.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "global.hxx"
|
|
#include <dbgdef.h>
|
|
|
|
extern HINSTANCE HinstDll;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
void CryptuiGoLink(HWND hwndParent, char *pszWhere, BOOL fNoCOM)
|
|
{
|
|
HCURSOR hcursPrev = NULL;
|
|
HMODULE hURLMon = NULL;
|
|
BOOL fCallCoUnInit = FALSE;
|
|
|
|
//
|
|
// since we're a model dialog box, we want to go behind IE once it comes up!!!
|
|
//
|
|
SetWindowPos(hwndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
|
|
|
|
hcursPrev = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
__try
|
|
{
|
|
|
|
hURLMon = (HMODULE)LoadLibraryU(L"urlmon.dll");
|
|
|
|
if (!(hURLMon) || fNoCOM)
|
|
{
|
|
//
|
|
// The hyperlink module is unavailable, go to fallback plan
|
|
//
|
|
//
|
|
// This works in test cases, but causes deadlock problems when used from withing
|
|
// the Internet Explorer itself. The dialog box is up (that is, IE is in a modal
|
|
// dialog loop) and in comes this DDE request...).
|
|
//
|
|
ShellExecute(hwndParent, "open", pszWhere, NULL, NULL, SW_SHOWNORMAL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The hyperlink module is there. Use it
|
|
//
|
|
if (SUCCEEDED(CoInitialize(NULL))) // Init OLE if no one else has
|
|
{
|
|
fCallCoUnInit = TRUE;
|
|
|
|
//
|
|
// allow com to fully init...
|
|
//
|
|
MSG msg;
|
|
|
|
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); // peek but not remove
|
|
|
|
typedef void (WINAPI *pfnHlinkSimpleNavigateToString)(LPCWSTR, LPCWSTR, LPCWSTR, IUnknown *,
|
|
IBindCtx *, IBindStatusCallback *,
|
|
DWORD, DWORD);
|
|
|
|
pfnHlinkSimpleNavigateToString pProcAddr;
|
|
|
|
pProcAddr = (pfnHlinkSimpleNavigateToString)GetProcAddress(hURLMon, TEXT("HlinkSimpleNavigateToString"));
|
|
|
|
if (pProcAddr)
|
|
{
|
|
WCHAR *pwszWhere;
|
|
IBindCtx *pbc;
|
|
|
|
pwszWhere = new WCHAR[strlen(pszWhere) + 1];
|
|
if (pwszWhere == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
MultiByteToWideChar(0, 0, (const char *)pszWhere, -1, pwszWhere, strlen(pszWhere) + 1);
|
|
|
|
pbc = NULL;
|
|
|
|
CreateBindCtx( 0, &pbc );
|
|
|
|
(*pProcAddr)(pwszWhere, NULL, NULL, NULL, pbc, NULL, HLNF_OPENINNEWWINDOW, NULL);
|
|
|
|
if (pbc)
|
|
{
|
|
pbc->Release();
|
|
}
|
|
|
|
delete [] pwszWhere;
|
|
}
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
FreeLibrary(hURLMon);
|
|
}
|
|
|
|
SetCursor(hcursPrev);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
if (hURLMon != NULL)
|
|
{
|
|
FreeLibrary(hURLMon);
|
|
}
|
|
|
|
if (fCallCoUnInit)
|
|
{
|
|
CoUninitialize();
|
|
}
|
|
|
|
if (hcursPrev != NULL)
|
|
{
|
|
SetCursor(hcursPrev);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL AllocAndGetIssuerURL(LPSTR *ppURLString, PCCERT_CONTEXT pCertContext)
|
|
{
|
|
PCERT_EXTENSION pExt = NULL;
|
|
PSPC_SP_AGENCY_INFO pInfo = NULL;
|
|
DWORD cbInfo = 0;
|
|
PCERT_ALT_NAME_ENTRY pAltName = NULL;
|
|
DWORD cbAltName = 0;
|
|
|
|
*ppURLString = NULL;
|
|
|
|
//
|
|
// first look for the Agency Info extension and see if it has an URL
|
|
//
|
|
if ((pExt = CertFindExtension(SPC_SP_AGENCY_INFO_OBJID, pCertContext->pCertInfo->cExtension,
|
|
pCertContext->pCertInfo->rgExtension)))
|
|
{
|
|
CryptDecodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT,
|
|
pExt->Value.pbData, pExt->Value.cbData, 0, NULL,
|
|
&cbInfo);
|
|
|
|
if (!(pInfo = (PSPC_SP_AGENCY_INFO) malloc(cbInfo)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(CryptDecodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT,
|
|
pExt->Value.pbData, pExt->Value.cbData, 0, pInfo,
|
|
&cbInfo)))
|
|
{
|
|
free(pInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(pInfo->pPolicyInformation))
|
|
{
|
|
free(pInfo);
|
|
return FALSE;
|
|
}
|
|
|
|
switch (pInfo->pPolicyInformation->dwLinkChoice)
|
|
{
|
|
case SPC_URL_LINK_CHOICE:
|
|
if (NULL != (*ppURLString =
|
|
(LPSTR) malloc(wcslen(pInfo->pPolicyInformation->pwszUrl)+1)))
|
|
{
|
|
WideCharToMultiByte(
|
|
0,
|
|
0,
|
|
pInfo->pPolicyInformation->pwszUrl,
|
|
-1,
|
|
*ppURLString,
|
|
wcslen(pInfo->pPolicyInformation->pwszUrl)+1,
|
|
NULL,
|
|
NULL);
|
|
|
|
free(pInfo);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
free(pInfo);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case SPC_FILE_LINK_CHOICE:
|
|
if (NULL != (*ppURLString =
|
|
(LPSTR) malloc(wcslen(pInfo->pPolicyInformation->pwszFile)+1)))
|
|
{
|
|
WideCharToMultiByte(
|
|
0,
|
|
0,
|
|
pInfo->pPolicyInformation->pwszFile,
|
|
-1,
|
|
*ppURLString,
|
|
wcslen(pInfo->pPolicyInformation->pwszFile)+1,
|
|
NULL,
|
|
NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
free(pInfo);
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
free(pInfo);
|
|
}
|
|
|
|
//
|
|
// if there was no Agency Info extension or it didn't contain an URL,
|
|
// look for the Authority Info Access Syntax extension
|
|
//
|
|
/*if ((pExt = CertFindExtension(SPC_SP_AGENCY_INFO_OBJID, pCertContext->pCertInfo->cExtension,
|
|
pCertContext->pCertInfo->rgExtension)))
|
|
{
|
|
FIX FIX
|
|
}*/
|
|
|
|
//
|
|
// finally, if there was no Agency Info and no Authority Info Access Syntax
|
|
// check to see if there is an Alternate Name extension
|
|
//
|
|
if ((pExt = CertFindExtension(szOID_ISSUER_ALT_NAME, pCertContext->pCertInfo->cExtension,
|
|
pCertContext->pCertInfo->rgExtension)))
|
|
{
|
|
CryptDecodeObject(X509_ASN_ENCODING, szOID_ISSUER_ALT_NAME,
|
|
pExt->Value.pbData, pExt->Value.cbData, 0, NULL,
|
|
&cbAltName);
|
|
|
|
if (!(pAltName = (PCERT_ALT_NAME_ENTRY) malloc(cbAltName)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(CryptDecodeObject(X509_ASN_ENCODING, szOID_ISSUER_ALT_NAME,
|
|
pExt->Value.pbData, pExt->Value.cbData, 0, pAltName,
|
|
&cbAltName)))
|
|
{
|
|
free(pAltName);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pAltName->dwAltNameChoice == CERT_ALT_NAME_URL)
|
|
{
|
|
if (NULL != (*ppURLString = (LPSTR) malloc(wcslen(pAltName->pwszURL)+1)))
|
|
{
|
|
WideCharToMultiByte(
|
|
0,
|
|
0,
|
|
pAltName->pwszURL,
|
|
-1,
|
|
*ppURLString,
|
|
wcslen(pAltName->pwszURL)+1,
|
|
NULL,
|
|
NULL);
|
|
|
|
free(pAltName);
|
|
return TRUE;
|
|
}
|
|
}
|
|
free(pAltName);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL AllocAndGetSubjectURL(LPSTR *ppURLString, PCCERT_CONTEXT pCertContext)
|
|
{
|
|
PCERT_EXTENSION pExt = NULL;
|
|
PCERT_ALT_NAME_ENTRY pAltName = NULL;
|
|
DWORD cbAltName = 0;
|
|
|
|
*ppURLString = NULL;
|
|
|
|
//
|
|
// check to see if there is an Alternate Name extension
|
|
//
|
|
if ((pExt = CertFindExtension(szOID_SUBJECT_ALT_NAME, pCertContext->pCertInfo->cExtension,
|
|
pCertContext->pCertInfo->rgExtension)))
|
|
{
|
|
CryptDecodeObject(X509_ASN_ENCODING, szOID_SUBJECT_ALT_NAME,
|
|
pExt->Value.pbData, pExt->Value.cbData, 0, NULL,
|
|
&cbAltName);
|
|
|
|
if (!(pAltName = (PCERT_ALT_NAME_ENTRY) malloc(cbAltName)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(CryptDecodeObject(X509_ASN_ENCODING, szOID_SUBJECT_ALT_NAME,
|
|
pExt->Value.pbData, pExt->Value.cbData, 0, pAltName,
|
|
&cbAltName)))
|
|
{
|
|
free(pAltName);
|
|
return FALSE;
|
|
}
|
|
|
|
if (pAltName->dwAltNameChoice == CERT_ALT_NAME_URL)
|
|
{
|
|
if (NULL != (*ppURLString = (LPSTR) malloc(wcslen(pAltName->pwszURL)+1)))
|
|
{
|
|
WideCharToMultiByte(
|
|
0,
|
|
0,
|
|
pAltName->pwszURL,
|
|
-1,
|
|
*ppURLString,
|
|
wcslen(pAltName->pwszURL)+1,
|
|
NULL,
|
|
NULL);
|
|
|
|
free(pAltName);
|
|
return TRUE;
|
|
}
|
|
}
|
|
free(pAltName);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|