mirror of https://github.com/tongzx/nt5src
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.
323 lines
8.4 KiB
323 lines
8.4 KiB
//--------------------------------------------------------------
|
|
// 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;
|
|
}
|
|
|