// This is a part of the Microsoft Management Console. // Copyright (C) Microsoft Corporation, 1995 - 1999 // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Management Console and related // electronic documentation provided with the interfaces. #include "stdafx.h" #include "certsrv.h" #include "setupids.h" #include "misc.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // Event handlers for IFrame::Notify HRESULT CSnapin::OnAddImages(MMC_COOKIE cookie, LPARAM arg, LPARAM param) { if (arg == 0) return E_INVALIDARG; ASSERT(m_pImageResult != NULL); ASSERT((IImageList*)arg == m_pImageResult); CBitmap bmpResultStrip16x16, bmpResultStrip32x32; if (NULL == bmpResultStrip16x16.LoadBitmap(IDB_16x16)) return S_FALSE; if (NULL == bmpResultStrip32x32.LoadBitmap(IDB_32x32)) return S_FALSE; // Set the images m_pImageResult->ImageListSetStrip(reinterpret_cast(static_cast(bmpResultStrip16x16)), reinterpret_cast(static_cast(bmpResultStrip32x32)), 0, RGB(255, 0, 255)); return S_OK; } HRESULT CSnapin::OnShow(MMC_COOKIE cookie, LPARAM arg, LPARAM param) { HRESULT hr; CFolder* pFolder = dynamic_cast(m_pComponentData)->FindObject(cookie); // Note - arg is TRUE when it is time to enumerate if (arg == TRUE) { m_pCurrentlySelectedScopeFolder = pFolder; // if list view on display if (m_CustomViewID == VIEW_DEFAULT_LV) { // Show the headers for this nodetype hr = InitializeHeaders(cookie); // virtual list support if (m_bVirtualView) m_pResult->SetItemCount(1, 0); } } else { // if list view is on display if (m_CustomViewID == VIEW_DEFAULT_LV) { // Free data associated with the result pane items, because // your node is no longer being displayed. } // Note: The console will remove the items from the result pane } return S_OK; } HRESULT CSnapin::GetRowColContents(CFolder* pFolder, LONG idxRow, LPCWSTR szColHead, PBYTE* ppbData, DWORD* pcbData, BOOL fStringFmt /*FALSE*/) { HRESULT hr; LONG idxCol; IEnumCERTVIEWROW* pRow = NULL; IEnumCERTVIEWCOLUMN* pCol = NULL; ICertView* pView = NULL; #if DBG DWORD dwVerifySize; #endif CComponentDataImpl* pCompData = dynamic_cast(m_pComponentData); ASSERT(pFolder != NULL); // pollute the row enumerator we've got hr = m_RowEnum.GetRowEnum(pFolder->GetCA(), &pRow); _JumpIfError(hr, Ret, "GetRowEnum"); hr = m_RowEnum.SetRowEnumPos(idxRow); _JumpIfError(hr, Ret, "SetRowEnumPos"); // now we have the correct row; siphon data out of the correct column hr = m_RowEnum.GetView(pFolder->GetCA(), &pView); _JumpIfError(hr, Ret, "GetView"); // get column number in schema idxCol = pCompData->FindColIdx(szColHead); // retrieve and alloc *pcbData = 0; hr = GetCellContents(&m_RowEnum, pFolder->GetCA(), idxRow, idxCol, NULL, pcbData, fStringFmt); _JumpIfError(hr, Ret, "GetCellContents"); *ppbData = new BYTE[*pcbData]; _JumpIfOutOfMemory(hr, Ret, *ppbData); #if DBG dwVerifySize = *pcbData; #endif hr = GetCellContents(&m_RowEnum, pFolder->GetCA(), idxRow, idxCol, *ppbData, pcbData, fStringFmt); _JumpIfError(hr, Ret, "GetCellContents"); #if DBG ASSERT(dwVerifySize == *pcbData); #endif Ret: // catch column inclusion errors, handle in a smart way if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_INDEX) || hr == HRESULT_FROM_WIN32(ERROR_CONTINUE)) { CString cstrFormat; cstrFormat.LoadString(IDS_COLUMN_INCLUSION_ERROR); LPCWSTR pszLocalizedCol = NULL; hr = myGetColumnDisplayName(szColHead, &pszLocalizedCol); ASSERT ((hr == S_OK) && (NULL != pszLocalizedCol)); CString cstrTmp; cstrTmp.Format(cstrFormat, pszLocalizedCol); cstrFormat.Empty(); cstrFormat.LoadString(IDS_MSG_TITLE); m_pConsole->MessageBoxW(cstrTmp, cstrFormat, MB_OK, NULL); hr = ERROR_CANCELLED; // this is a cancellation so bail silently, we've shown error } return hr; } HRESULT GetBinaryColumnFormat( IN WCHAR const *pwszColumnName, OUT LONG *pFormat) { LONG Format = CV_OUT_BINARY; if (0 == lstrcmpi( wszPROPREQUESTDOT wszPROPREQUESTRAWREQUEST, pwszColumnName)) { Format = CV_OUT_BASE64REQUESTHEADER; } else if (0 == lstrcmpi(wszPROPRAWCERTIFICATE, pwszColumnName) || 0 == lstrcmpi( wszPROPREQUESTDOT wszPROPREQUESTRAWOLDCERTIFICATE, pwszColumnName)) { Format = CV_OUT_BASE64HEADER; } else { Format = CV_OUT_HEX; } *pFormat = Format; return(S_OK); } // Build the display name for templates: "friendly name (internal name)" HRESULT CSnapin::BuildTemplateDisplayName( LPCWSTR pcwszFriendlyName, LPCWSTR pcwszTemplateName, VARIANT& varDisplayName) { CString strName; strName = pcwszFriendlyName; strName += L" ("; strName += pcwszTemplateName; strName += L")"; V_VT(&varDisplayName) = VT_BSTR; V_BSTR(&varDisplayName) = ::SysAllocString(strName); if(!V_BSTR(&varDisplayName)) return E_OUTOFMEMORY; return S_OK; } // copies cell to pbData, truncates if necessary. Real size passed out in pcbData HRESULT CSnapin::GetCellContents(CertViewRowEnum* pCRowEnum, CertSvrCA* pCA, LONG idxRow, LONG idxCol, PBYTE pbData, DWORD* pcbData, BOOL fStringFmt) { HRESULT hr; CComponentDataImpl* pCompData = dynamic_cast(m_pComponentData); if (NULL == pCompData) return E_POINTER; VARIANT varCert; VariantInit(&varCert); LONG idxViewCol; IEnumCERTVIEWROW* pRow; IEnumCERTVIEWCOLUMN* pCol = NULL; hr = pCRowEnum->GetRowEnum(pCA, &pRow); if (hr != S_OK) return hr; do { hr = pCRowEnum->SetRowEnumPos(idxRow); if (hr != S_OK) break; LONG lType; LPCWSTR szColHead; // no free needed hr = pCRowEnum->GetColumnCacheInfo(idxCol, (int*)&idxViewCol); if (hr != S_OK) break; // get col enumerator object hr = pRow->EnumCertViewColumn(&pCol); if (hr != S_OK) break; hr = pCol->Skip(idxViewCol); if (hr != S_OK) break; // get value there hr = pCol->Next(&idxViewCol); if (hr != S_OK) break; if (fStringFmt) { LONG lFormat = CV_OUT_BINARY; VARIANT varTmp; VariantInit(&varTmp); hr = pCompData->GetDBSchemaEntry(idxCol, &szColHead, &lType, NULL); if (hr != S_OK) break; // New: translate _some_ cols to readable strings if (PROPTYPE_BINARY == lType) { hr = GetBinaryColumnFormat(szColHead, &lFormat); if (hr != S_OK) break; } hr = pCol->GetValue(lFormat, &varTmp); if (hr != S_OK) break; if (0 == lstrcmpi(wszPROPREQUESTDOT wszPROPREQUESTRAWARCHIVEDKEY, szColHead)) { if (VT_EMPTY != varTmp.vt) { varCert.bstrVal = ::SysAllocString(g_cResources.m_szYes); varCert.vt = VT_BSTR; } } else if (0 == lstrcmpi(wszPROPCERTTEMPLATE, szColHead)) { LPCWSTR pcwszOID = NULL; if (VT_BSTR == varTmp.vt) { // Map OID or template name to friendly name // Try name first HCERTTYPE hCertType; LPWSTR *pwszCertTypeName; hr = CAFindCertTypeByName( varTmp.bstrVal, NULL, CT_ENUM_MACHINE_TYPES | CT_ENUM_USER_TYPES | 0, &hCertType); if(S_OK==hr) { hr = CAGetCertTypeProperty( hCertType, CERTTYPE_PROP_FRIENDLY_NAME, &pwszCertTypeName); if(S_OK==hr) { BuildTemplateDisplayName( pwszCertTypeName[0], varTmp.bstrVal, varCert); CAFreeCertTypeProperty( hCertType, pwszCertTypeName); } CACloseCertType(hCertType); } // Failed to find by name, try OID if(S_OK!=hr) { pcwszOID = myGetOIDName(varTmp.bstrVal); varCert.vt = VT_BSTR; if (EmptyString(pcwszOID)) { varCert.bstrVal = ::SysAllocString(varTmp.bstrVal); } else { BuildTemplateDisplayName( pcwszOID, varTmp.bstrVal, varCert); } } } } else if (0 == lstrcmpi(wszPROPREQUESTDOT wszPROPREQUESTSTATUSCODE, szColHead)) { if (VT_I4 == varTmp.vt) // don't be empty { WCHAR const *pwszError = myGetErrorMessageText(varTmp.lVal, TRUE); varCert.bstrVal = ::SysAllocString(pwszError); varCert.vt = VT_BSTR; } } else if (0 == lstrcmpi(wszPROPREQUESTDOT wszPROPREQUESTREVOKEDREASON, szColHead)) { if (VT_I4 == varTmp.vt) // don't be empty { // Request.Disposition ASSERT(VT_I4 == varTmp.vt); // we'd better be looking at a dword switch(varTmp.lVal) { case CRL_REASON_KEY_COMPROMISE: varCert.bstrVal = ::SysAllocString(g_cResources.m_szRevokeReason_KeyCompromise); break; case CRL_REASON_CA_COMPROMISE: varCert.bstrVal = ::SysAllocString(g_cResources.m_szRevokeReason_CaCompromise); break; case CRL_REASON_AFFILIATION_CHANGED: varCert.bstrVal = ::SysAllocString(g_cResources.m_szRevokeReason_Affiliation); break; case CRL_REASON_SUPERSEDED: varCert.bstrVal = ::SysAllocString(g_cResources.m_szRevokeReason_Superseded); break; case CRL_REASON_CESSATION_OF_OPERATION: varCert.bstrVal = ::SysAllocString(g_cResources.m_szRevokeReason_Cessatation); break; case CRL_REASON_CERTIFICATE_HOLD: varCert.bstrVal = ::SysAllocString(g_cResources.m_szRevokeReason_CertHold); break; case CRL_REASON_UNSPECIFIED: varCert.bstrVal = ::SysAllocString(g_cResources.m_szRevokeReason_Unspecified); break; case CRL_REASON_REMOVE_FROM_CRL: varCert.bstrVal = ::SysAllocString(g_cResources.m_szRevokeReason_RemoveFromCRL); break; default: { // sprint this into a buffer for display CString cstrSprintVal; cstrSprintVal.Format(L"%i", varTmp.lVal); varCert.bstrVal = cstrSprintVal.AllocSysString(); break; } } if (varCert.bstrVal == NULL) { hr = E_OUTOFMEMORY; break; } varCert.vt = VT_BSTR; } } if (varCert.vt != VT_BSTR) // if this hasn't been converted yet { // default: conversion to string // returns localized string time (even for date!) VERIFY( MakeDisplayStrFromDBVariant(&varTmp, &varCert) ); // variant type change failed!? InplaceStripControlChars(varCert.bstrVal); } VariantClear(&varTmp); } else { hr = pCol->GetValue(CV_OUT_BINARY, &varCert); if (hr != S_OK) break; if (VT_EMPTY == varCert.vt) { hr = CERTSRV_E_PROPERTY_EMPTY; break; } } // finally, copy this value out to pb // copy, truncate if necessary DWORD cbTruncate = *pcbData; if (varCert.vt == VT_BSTR) { *pcbData = SysStringByteLen(varCert.bstrVal) + ((fStringFmt)? sizeof(WCHAR):0); CopyMemory(pbData, varCert.bstrVal, min(cbTruncate, *pcbData)); } else if (varCert.vt == VT_I4) { *pcbData = sizeof(LONG); if (pbData != NULL) *(DWORD*)pbData = varCert.lVal; } else { hr = E_INVALIDARG; break; } }while(0); VariantClear(&varCert); if (pCol) pCol->Release(); return hr; }