Source code of Windows XP (NT5)
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

  1. //--------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation, 1996 - 1999
  3. //
  4. // File: CryptSig.cpp
  5. //
  6. // content: Implements the IContextMenu member functions necessary to support
  7. // the context menu portioins of this shell extension. Context menu
  8. // shell extensions are called when the user right clicks on a file
  9. // History: 16-09-1997 xiaohs created
  10. //
  11. // CryptSig.cpp : Implementation of CCryptSig
  12. //--------------------------------------------------------------
  13. #include "stdafx.h"
  14. #include "cryptext.h"
  15. #include "private.h"
  16. #include "CryptSig.h"
  17. //--------------------------------------------------------------
  18. // CCryptSig
  19. //--------------------------------------------------------------
  20. //
  21. // FUNCTION: GAKPageCallback(HWND, UINT, LPPROPSHEETPAGE)
  22. //
  23. // PURPOSE: Callback procedure for the property page
  24. //
  25. // PARAMETERS:
  26. // hWnd - Reserved (will always be NULL)
  27. // uMessage - Action flag: Are we being created or released
  28. // ppsp - The page that is being created or destroyed
  29. //
  30. // RETURN VALUE:
  31. //
  32. // Depends on message.
  33. //
  34. // For PSPCB_CREATE it's TRUE to let the page be created
  35. // or false to prevent it from being created.
  36. // For PSPCB_RELEASE the return value is ignored.
  37. //
  38. // COMMENTS:
  39. //
  40. BOOL CALLBACK
  41. SignPageCallBack(HWND hWnd,
  42. UINT uMessage,
  43. void *pvCallBack)
  44. {
  45. switch(uMessage)
  46. {
  47. case PSPCB_CREATE:
  48. return TRUE;
  49. case PSPCB_RELEASE:
  50. if (pvCallBack)
  51. {
  52. ((IShellPropSheetExt *)(pvCallBack))->Release();
  53. }
  54. return TRUE;
  55. }
  56. return TRUE;
  57. }
  58. //--------------------------------------------------------------
  59. //
  60. // Constructor
  61. //
  62. //--------------------------------------------------------------
  63. CCryptSig::CCryptSig()
  64. {
  65. m_pDataObj=NULL;
  66. }
  67. //--------------------------------------------------------------
  68. //
  69. // Destructor
  70. //
  71. //--------------------------------------------------------------
  72. CCryptSig::~CCryptSig()
  73. {
  74. if (m_pDataObj)
  75. m_pDataObj->Release();
  76. }
  77. //--------------------------------------------------------------
  78. // FUNCTION: CCryptSig::AddPages(LPFNADDPROPSHEETPAGE, LPARAM)
  79. //
  80. // PURPOSE: Called by the shell just before the property sheet is displayed.
  81. //
  82. // PARAMETERS:
  83. // lpfnAddPage - Pointer to the Shell's AddPage function
  84. // lParam - Passed as second parameter to lpfnAddPage
  85. //
  86. // RETURN VALUE:
  87. //
  88. // NOERROR in all cases. If for some reason our pages don't get added,
  89. // the Shell still needs to bring up the Properties... sheet.
  90. //
  91. // COMMENTS:
  92. //--------------------------------------------------------------
  93. STDMETHODIMP CCryptSig::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
  94. {
  95. HPROPSHEETPAGE hpage;
  96. PROPSHEETPAGEW *pPage=NULL;
  97. DWORD dwPage=0;
  98. DWORD dwIndex=0;
  99. DWORD dwSignerCount=0;
  100. DWORD cbSize=0;
  101. FORMATETC fmte = {CF_HDROP,
  102. (DVTARGETDEVICE FAR *)NULL,
  103. DVASPECT_CONTENT,
  104. -1,
  105. TYMED_HGLOBAL
  106. };
  107. STGMEDIUM stgm;
  108. UINT ucFiles=0;
  109. WCHAR wszFileName[_MAX_PATH];
  110. HCRYPTMSG hMsg=NULL;
  111. HRESULT hr=E_FAIL;
  112. DWORD dwExceptionCode=0;
  113. DWORD dwAttr=0;
  114. CRYPTUI_VIEWSIGNATURES_STRUCTW sigView;
  115. //get the file name that user clicked on. We do not add context menu
  116. //if user has selected more than one file
  117. if (m_pDataObj)
  118. hr = m_pDataObj->GetData(&fmte, &stgm);
  119. if (!SUCCEEDED(hr))
  120. return NOERROR;
  121. ucFiles = stgm.hGlobal ?
  122. DragQueryFileU((HDROP) stgm.hGlobal, 0xFFFFFFFFL , 0, 0) : 0;
  123. if ((!ucFiles) || (ucFiles >= 2))
  124. {
  125. ReleaseStgMedium(&stgm);
  126. return NOERROR; // Shouldn't happen, but it's not important
  127. }
  128. if(0==DragQueryFileU((HDROP) stgm.hGlobal, 0, wszFileName,
  129. sizeof wszFileName/ sizeof wszFileName[0]))
  130. {
  131. ReleaseStgMedium(&stgm);
  132. return NOERROR;
  133. }
  134. //we ignore the case when the file is off-line
  135. if(0xFFFFFFFF == (dwAttr=GetFileAttributesU(wszFileName)))
  136. {
  137. ReleaseStgMedium(&stgm);
  138. return NOERROR;
  139. }
  140. if(FILE_ATTRIBUTE_OFFLINE & dwAttr)
  141. {
  142. ReleaseStgMedium(&stgm);
  143. return NOERROR;
  144. }
  145. //get the content type of the file. We only cares about
  146. //the signed document in binary format
  147. if(!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
  148. wszFileName,
  149. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
  150. CERT_QUERY_FORMAT_FLAG_BINARY,
  151. 0,
  152. NULL,
  153. NULL,
  154. NULL,
  155. NULL,
  156. &hMsg,
  157. NULL))
  158. {
  159. //can not recognize the object. Fine
  160. goto CLEANUP;
  161. }
  162. //make sure that we have at least on signer
  163. cbSize = sizeof(dwSignerCount);
  164. if(!CryptMsgGetParam(hMsg,
  165. CMSG_SIGNER_COUNT_PARAM,
  166. 0,
  167. &dwSignerCount,
  168. &cbSize))
  169. goto CLEANUP;
  170. if(0==dwSignerCount)
  171. goto CLEANUP;
  172. //Call Reid's function to add the property sheet page
  173. memset(&sigView, 0, sizeof(CRYPTUI_VIEWSIGNATURES_STRUCTW));
  174. sigView.dwSize=sizeof(CRYPTUI_VIEWSIGNATURES_STRUCTW);
  175. sigView.choice=hMsg_Chosen;
  176. sigView.u.hMsg=hMsg;
  177. sigView.szFileName=wszFileName;
  178. sigView.pPropPageCallback=SignPageCallBack;
  179. sigView.pvCallbackData=this;
  180. if(!CryptUIGetViewSignaturesPagesW(
  181. &sigView,
  182. &pPage,
  183. &dwPage))
  184. goto CLEANUP;
  185. __try {
  186. for(dwIndex=0; dwIndex<dwPage; dwIndex++)
  187. {
  188. // pPage[dwIndex].dwFlags |= PSP_USECALLBACK;
  189. //add the callback functions to release the refcount
  190. //pPage[dwIndex].pfnCallback=SignPageCallBack;
  191. //pPage[dwIndex].pcRefParent=(UINT *)this;
  192. hpage = CreatePropertySheetPageU(&(pPage[dwIndex]));
  193. ((IShellPropSheetExt *)this)->AddRef();
  194. if (hpage)
  195. {
  196. if (!lpfnAddPage(hpage, lParam))
  197. {
  198. DestroyPropertySheetPage(hpage);
  199. ((IShellPropSheetExt *)this)->Release();
  200. }
  201. }
  202. }
  203. } __except(EXCEPTION_EXECUTE_HANDLER) {
  204. dwExceptionCode = GetExceptionCode();
  205. goto CLEANUP;
  206. }
  207. CLEANUP:
  208. ReleaseStgMedium(&stgm);
  209. if(pPage)
  210. CryptUIFreeViewSignaturesPagesW(pPage, dwPage);
  211. if(hMsg)
  212. CryptMsgClose(hMsg);
  213. return NOERROR;
  214. }
  215. //--------------------------------------------------------------
  216. // FUNCTION: CCryptSig::ReplacePage(UINT, LPFNADDPROPSHEETPAGE, LPARAM)
  217. //
  218. // PURPOSE: Called by the shell only for Control Panel property sheet
  219. // extensions
  220. //
  221. // PARAMETERS:
  222. // uPageID - ID of page to be replaced
  223. // lpfnReplaceWith - Pointer to the Shell's Replace function
  224. // lParam - Passed as second parameter to lpfnReplaceWith
  225. //
  226. // RETURN VALUE:
  227. //
  228. // E_FAIL, since we don't support this function. It should never be
  229. // called.
  230. // COMMENTS:
  231. //--------------------------------------------------------------
  232. STDMETHODIMP CCryptSig::ReplacePage(UINT uPageID,
  233. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  234. LPARAM lParam)
  235. {
  236. return E_FAIL;
  237. }
  238. //--------------------------------------------------------------
  239. // FUNCTION: CCryptSig::Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY)
  240. //
  241. // PURPOSE: Called by the shell when initializing a context menu or property
  242. // sheet extension.
  243. //
  244. // PARAMETERS:
  245. // pIDFolder - Specifies the parent folder
  246. // pDataObj - Spefifies the set of items selected in that folder.
  247. // hRegKey - Specifies the type of the focused item in the selection.
  248. //
  249. // RETURN VALUE:
  250. //
  251. // NOERROR in all cases.
  252. //--------------------------------------------------------------
  253. STDMETHODIMP CCryptSig::Initialize(LPCITEMIDLIST pIDFolder,
  254. LPDATAOBJECT pDataObj,
  255. HKEY hRegKey)
  256. {
  257. // Initialize can be called more than once
  258. if (m_pDataObj)
  259. m_pDataObj->Release();
  260. // duplicate the object pointer and registry handle
  261. if (pDataObj)
  262. {
  263. m_pDataObj = pDataObj;
  264. pDataObj->AddRef();
  265. }
  266. return NOERROR;
  267. }