|
|
//--------------------------------------------------------------
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: CryptSig.cpp
//
// content: Implements the IContextMenu member functions necessary to support
// the context menu portioins of this shell extension. Context menu
// shell extensions are called when the user right clicks on a file
// History: 16-09-1997 xiaohs created
//
// CryptSig.cpp : Implementation of CCryptSig
//--------------------------------------------------------------
#include "stdafx.h"
#include "cryptext.h"
#include "private.h"
#include "CryptSig.h"
//--------------------------------------------------------------
// CCryptSig
//--------------------------------------------------------------
//
// FUNCTION: GAKPageCallback(HWND, UINT, LPPROPSHEETPAGE)
//
// PURPOSE: Callback procedure for the property page
//
// PARAMETERS:
// hWnd - Reserved (will always be NULL)
// uMessage - Action flag: Are we being created or released
// ppsp - The page that is being created or destroyed
//
// RETURN VALUE:
//
// Depends on message.
//
// For PSPCB_CREATE it's TRUE to let the page be created
// or false to prevent it from being created.
// For PSPCB_RELEASE the return value is ignored.
//
// COMMENTS:
//
BOOL CALLBACK SignPageCallBack(HWND hWnd, UINT uMessage, void *pvCallBack) { switch(uMessage) { case PSPCB_CREATE: return TRUE;
case PSPCB_RELEASE: if (pvCallBack) { ((IShellPropSheetExt *)(pvCallBack))->Release(); } return TRUE; } return TRUE; }
//--------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------
CCryptSig::CCryptSig() { m_pDataObj=NULL; }
//--------------------------------------------------------------
//
// Destructor
//
//--------------------------------------------------------------
CCryptSig::~CCryptSig() { if (m_pDataObj) m_pDataObj->Release();
}
//--------------------------------------------------------------
// FUNCTION: CCryptSig::AddPages(LPFNADDPROPSHEETPAGE, LPARAM)
//
// PURPOSE: Called by the shell just before the property sheet is displayed.
//
// PARAMETERS:
// lpfnAddPage - Pointer to the Shell's AddPage function
// lParam - Passed as second parameter to lpfnAddPage
//
// RETURN VALUE:
//
// NOERROR in all cases. If for some reason our pages don't get added,
// the Shell still needs to bring up the Properties... sheet.
//
// COMMENTS:
//--------------------------------------------------------------
STDMETHODIMP CCryptSig::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam) { HPROPSHEETPAGE hpage; PROPSHEETPAGEW *pPage=NULL; DWORD dwPage=0; DWORD dwIndex=0; DWORD dwSignerCount=0; DWORD cbSize=0;
FORMATETC fmte = {CF_HDROP, (DVTARGETDEVICE FAR *)NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM stgm; UINT ucFiles=0; WCHAR wszFileName[_MAX_PATH]; HCRYPTMSG hMsg=NULL; HRESULT hr=E_FAIL; DWORD dwExceptionCode=0; DWORD dwAttr=0;
CRYPTUI_VIEWSIGNATURES_STRUCTW sigView;
//get the file name that user clicked on. We do not add context menu
//if user has selected more than one file
if (m_pDataObj) hr = m_pDataObj->GetData(&fmte, &stgm);
if (!SUCCEEDED(hr)) return NOERROR;
ucFiles = stgm.hGlobal ? DragQueryFileU((HDROP) stgm.hGlobal, 0xFFFFFFFFL , 0, 0) : 0;
if ((!ucFiles) || (ucFiles >= 2)) { ReleaseStgMedium(&stgm);
return NOERROR; // Shouldn't happen, but it's not important
}
if(0==DragQueryFileU((HDROP) stgm.hGlobal, 0, wszFileName, sizeof wszFileName/ sizeof wszFileName[0])) { ReleaseStgMedium(&stgm);
return NOERROR; }
//we ignore the case when the file is off-line
if(0xFFFFFFFF == (dwAttr=GetFileAttributesU(wszFileName))) { ReleaseStgMedium(&stgm); return NOERROR; }
if(FILE_ATTRIBUTE_OFFLINE & dwAttr) { ReleaseStgMedium(&stgm); return NOERROR; }
//get the content type of the file. We only cares about
//the signed document in binary format
if(!CryptQueryObject(CERT_QUERY_OBJECT_FILE, wszFileName, CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, NULL, &hMsg, NULL)) { //can not recognize the object. Fine
goto CLEANUP; }
//make sure that we have at least on signer
cbSize = sizeof(dwSignerCount); if(!CryptMsgGetParam(hMsg, CMSG_SIGNER_COUNT_PARAM, 0, &dwSignerCount, &cbSize)) goto CLEANUP;
if(0==dwSignerCount) goto CLEANUP;
//Call Reid's function to add the property sheet page
memset(&sigView, 0, sizeof(CRYPTUI_VIEWSIGNATURES_STRUCTW)); sigView.dwSize=sizeof(CRYPTUI_VIEWSIGNATURES_STRUCTW); sigView.choice=hMsg_Chosen; sigView.u.hMsg=hMsg; sigView.szFileName=wszFileName; sigView.pPropPageCallback=SignPageCallBack; sigView.pvCallbackData=this;
if(!CryptUIGetViewSignaturesPagesW( &sigView, &pPage, &dwPage)) goto CLEANUP;
__try { for(dwIndex=0; dwIndex<dwPage; dwIndex++) { // pPage[dwIndex].dwFlags |= PSP_USECALLBACK;
//add the callback functions to release the refcount
//pPage[dwIndex].pfnCallback=SignPageCallBack;
//pPage[dwIndex].pcRefParent=(UINT *)this;
hpage = CreatePropertySheetPageU(&(pPage[dwIndex])); ((IShellPropSheetExt *)this)->AddRef();
if (hpage) { if (!lpfnAddPage(hpage, lParam)) { DestroyPropertySheetPage(hpage); ((IShellPropSheetExt *)this)->Release(); } } }
} __except(EXCEPTION_EXECUTE_HANDLER) { dwExceptionCode = GetExceptionCode(); goto CLEANUP; }
CLEANUP:
ReleaseStgMedium(&stgm);
if(pPage) CryptUIFreeViewSignaturesPagesW(pPage, dwPage); if(hMsg) CryptMsgClose(hMsg);
return NOERROR; }
//--------------------------------------------------------------
// FUNCTION: CCryptSig::ReplacePage(UINT, LPFNADDPROPSHEETPAGE, LPARAM)
//
// PURPOSE: Called by the shell only for Control Panel property sheet
// extensions
//
// PARAMETERS:
// uPageID - ID of page to be replaced
// lpfnReplaceWith - Pointer to the Shell's Replace function
// lParam - Passed as second parameter to lpfnReplaceWith
//
// RETURN VALUE:
//
// E_FAIL, since we don't support this function. It should never be
// called.
// COMMENTS:
//--------------------------------------------------------------
STDMETHODIMP CCryptSig::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam) { return E_FAIL; }
//--------------------------------------------------------------
// FUNCTION: CCryptSig::Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY)
//
// PURPOSE: Called by the shell when initializing a context menu or property
// sheet extension.
//
// PARAMETERS:
// pIDFolder - Specifies the parent folder
// pDataObj - Spefifies the set of items selected in that folder.
// hRegKey - Specifies the type of the focused item in the selection.
//
// RETURN VALUE:
//
// NOERROR in all cases.
//--------------------------------------------------------------
STDMETHODIMP CCryptSig::Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hRegKey) { // Initialize can be called more than once
if (m_pDataObj) m_pDataObj->Release();
// duplicate the object pointer and registry handle
if (pDataObj) { m_pDataObj = pDataObj; pDataObj->AddRef(); }
return NOERROR; }
|