Leaked source code of windows server 2003
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.

1777 lines
58 KiB

  1. /*-----------------------------------------
  2. //
  3. // CertProp.C -- Displays Certificate File
  4. // Properties and Allows
  5. /// Add Cert to WAB
  6. //
  7. //-----------------------------------------*/
  8. #include <windows.h>
  9. #include <wab.h>
  10. #include <wabguid.h>
  11. #include "..\wab32res\resrc2.h"
  12. #include <wincrypt.h>
  13. #include <cryptdlg.h>
  14. #include <cryptui.h>
  15. #include "wabexe.h"
  16. const UCHAR cszOID_PKIX_KP_EMAIL_PROTECTION[] = szOID_PKIX_KP_EMAIL_PROTECTION;
  17. const UCHAR szRoot[] = "ROOT";
  18. const UCHAR szCA[] = "CA";
  19. const UCHAR szAB[] = "AddressBook";
  20. #define iAddToWAB 0
  21. // Test for PT_ERROR property tag
  22. // #define PROP_ERROR(prop) (prop.ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(prop.ulPropTag)))
  23. #define PROP_ERROR(prop) (PROP_TYPE(prop.ulPropTag) == PT_ERROR)
  24. #define GET_PROC_ADDR(h, fn) \
  25. VAR_##fn = (TYP_##fn) GetProcAddress(h, #fn); \
  26. Assert(VAR_##fn != NULL); \
  27. if(NULL == VAR_##fn ) { \
  28. VAR_##fn = LOADER_##fn; \
  29. }
  30. #define GET_PROC_ADDR_FLAG(h, fn, pflag) \
  31. VAR_##fn = (TYP_##fn) GetProcAddress(h, #fn); \
  32. *pflag = (VAR_##fn != NULL);
  33. #undef LOADER_FUNCTION
  34. #define LOADER_FUNCTION(ret, name, args1, args2, err, dll) \
  35. typedef ret (WINAPI * TYP_##name) args1; \
  36. extern TYP_##name VAR_##name; \
  37. ret LOADER_##name args1 \
  38. { \
  39. if (!DemandLoad##dll()) return err; \
  40. return VAR_##name args2; \
  41. } \
  42. TYP_##name VAR_##name = LOADER_##name;
  43. #ifdef DEBUG
  44. void DebugTraceCertContextName(PCCERT_CONTEXT pcCertContext, LPTSTR lpDescription);
  45. #endif
  46. // *****************************************************************************************
  47. // CRYPTDLG.DLL
  48. // *****************************************************************************************
  49. BOOL DemandLoadCryptDlg(void);
  50. static HMODULE s_hCryptDlg = 0;
  51. LOADER_FUNCTION( DWORD, GetFriendlyNameOfCertA,
  52. (PCCERT_CONTEXT pccert, LPSTR pchBuffer, DWORD cchBuffer),
  53. (pccert, pchBuffer, cchBuffer),
  54. 0, CryptDlg)
  55. #define GetFriendlyNameOfCertA VAR_GetFriendlyNameOfCertA
  56. LOADER_FUNCTION( BOOL, CertViewPropertiesA,
  57. (PCERT_VIEWPROPERTIES_STRUCT_A pCertViewInfo),
  58. (pCertViewInfo),
  59. FALSE, CryptDlg)
  60. #define CertViewPropertiesA VAR_CertViewPropertiesA
  61. // *****************************************************************************************
  62. // CRYPT32.DLL
  63. // *****************************************************************************************
  64. BOOL DemandLoadCrypt32(void);
  65. static HMODULE s_hCrypt32 = 0;
  66. LOADER_FUNCTION( BOOL, CertFreeCertificateContext,
  67. (PCCERT_CONTEXT pCertContext),
  68. (pCertContext),
  69. FALSE, Crypt32)
  70. #define CertFreeCertificateContext VAR_CertFreeCertificateContext
  71. LOADER_FUNCTION( PCCERT_CONTEXT, CertDuplicateCertificateContext,
  72. (PCCERT_CONTEXT pCertContext),
  73. (pCertContext), NULL, Crypt32)
  74. #define CertDuplicateCertificateContext VAR_CertDuplicateCertificateContext
  75. LOADER_FUNCTION( BOOL, CertCloseStore,
  76. (HCERTSTORE hCertStore, DWORD dwFlags),
  77. (hCertStore, dwFlags),
  78. FALSE, Crypt32)
  79. #define CertCloseStore VAR_CertCloseStore
  80. LOADER_FUNCTION( HCERTSTORE, CertOpenSystemStoreA,
  81. (HCRYPTPROV hProv, LPCSTR szSubsystemProtocol),
  82. (hProv, szSubsystemProtocol),
  83. NULL, Crypt32)
  84. #define CertOpenSystemStoreA VAR_CertOpenSystemStoreA
  85. LOADER_FUNCTION( BOOL, CertGetCertificateContextProperty,
  86. (PCCERT_CONTEXT pCertContext, DWORD dwPropId, void *pvData, DWORD *pcbData),
  87. (pCertContext, dwPropId, pvData, pcbData),
  88. FALSE, Crypt32)
  89. #define CertGetCertificateContextProperty VAR_CertGetCertificateContextProperty
  90. LOADER_FUNCTION( HCERTSTORE, CertOpenStore,
  91. (LPCSTR lpszStoreProvider, DWORD dwEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags, const void *pvPara),
  92. (lpszStoreProvider, dwEncodingType, hCryptProv, dwFlags, pvPara),
  93. NULL, Crypt32)
  94. #define CertOpenStore VAR_CertOpenStore
  95. LOADER_FUNCTION( PCCERT_CONTEXT, CertEnumCertificatesInStore,
  96. (HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext),
  97. (hCertStore, pPrevCertContext),
  98. NULL, Crypt32)
  99. #define CertEnumCertificatesInStore VAR_CertEnumCertificatesInStore
  100. LOADER_FUNCTION( PCCERT_CONTEXT, CertGetIssuerCertificateFromStore,
  101. (HCERTSTORE hCertStore, PCCERT_CONTEXT pSubjectContext, PCCERT_CONTEXT pPrevIssuerContext, DWORD *pdwFlags),
  102. (hCertStore, pSubjectContext, pPrevIssuerContext, pdwFlags),
  103. NULL, Crypt32)
  104. #define CertGetIssuerCertificateFromStore VAR_CertGetIssuerCertificateFromStore
  105. LOADER_FUNCTION( BOOL, CertCompareCertificate,
  106. (DWORD dwCertEncodingType, PCERT_INFO pCertId1, PCERT_INFO pCertId2),
  107. (dwCertEncodingType, pCertId1, pCertId2),
  108. FALSE, Crypt32)
  109. #define CertCompareCertificate VAR_CertCompareCertificate
  110. LOADER_FUNCTION( BOOL, CryptMsgClose,
  111. (HCRYPTMSG hCryptMsg),
  112. (hCryptMsg),
  113. FALSE, Crypt32)
  114. #define CryptMsgClose VAR_CryptMsgClose
  115. LOADER_FUNCTION( BOOL, CryptMsgGetParam,
  116. (HCRYPTMSG hCryptMsg, DWORD dwParamType, DWORD dwIndex, void *pvData, DWORD *pcbData),
  117. (hCryptMsg, dwParamType, dwIndex, pvData, pcbData),
  118. FALSE, Crypt32)
  119. #define CryptMsgGetParam VAR_CryptMsgGetParam
  120. LOADER_FUNCTION( BOOL, CryptMsgUpdate,
  121. (HCRYPTMSG hCryptMsg, const BYTE *pbData, DWORD cbData, BOOL fFinal),
  122. (hCryptMsg, pbData, cbData, fFinal),
  123. FALSE, Crypt32)
  124. #define CryptMsgUpdate VAR_CryptMsgUpdate
  125. LOADER_FUNCTION( HCRYPTMSG, CryptMsgOpenToDecode,
  126. (DWORD dwMsgEncodingType, DWORD dwFlags, DWORD dwMsgType, HCRYPTPROV hCryptProv, PCERT_INFO pRecipientInfo, PCMSG_STREAM_INFO pStreamInfo),
  127. (dwMsgEncodingType, dwFlags, dwMsgType, hCryptProv, pRecipientInfo, pStreamInfo),
  128. NULL, Crypt32)
  129. #define CryptMsgOpenToDecode VAR_CryptMsgOpenToDecode
  130. LOADER_FUNCTION( DWORD, CertRDNValueToStrA,
  131. (DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, LPTSTR pszValueString, DWORD cszValueString),
  132. (dwValueType, pValue, pszValueString, cszValueString),
  133. 0, Crypt32)
  134. #define CertRDNValueToStrA VAR_CertRDNValueToStrA
  135. LOADER_FUNCTION( PCERT_RDN_ATTR, CertFindRDNAttr,
  136. (LPCSTR pszObjId, PCERT_NAME_INFO pName),
  137. (pszObjId, pName),
  138. NULL, Crypt32)
  139. #define CertFindRDNAttr VAR_CertFindRDNAttr
  140. LOADER_FUNCTION( BOOL, CryptDecodeObject,
  141. (DWORD dwEncodingType, LPCSTR lpszStructType, const BYTE * pbEncoded, DWORD cbEncoded, DWORD dwFlags,
  142. void * pvStructInfo, DWORD * pcbStructInfo),
  143. (dwEncodingType, lpszStructType, pbEncoded, cbEncoded, dwFlags,
  144. pvStructInfo, pcbStructInfo),
  145. FALSE, Crypt32)
  146. #define CryptDecodeObject VAR_CryptDecodeObject
  147. LOADER_FUNCTION( BOOL, CertAddCertificateContextToStore,
  148. (HCERTSTORE hCertStore, PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition, PCCERT_CONTEXT * ppStoreContext),
  149. (hCertStore, pCertContext, dwAddDisposition, ppStoreContext),
  150. FALSE, Crypt32)
  151. #define CertAddCertificateContextToStore VAR_CertAddCertificateContextToStore
  152. LOADER_FUNCTION( BOOL, CertAddEncodedCertificateToStore,
  153. (HCERTSTORE hCertStore, DWORD dwCertEncodingType, const BYTE *pbCertEncoded, DWORD cbCertEncoded, DWORD dwAddDisposition, PCCERT_CONTEXT *ppCertContext),
  154. (hCertStore, dwCertEncodingType, pbCertEncoded, cbCertEncoded, dwAddDisposition, ppCertContext),
  155. FALSE, Crypt32)
  156. #define CertAddEncodedCertificateToStore VAR_CertAddEncodedCertificateToStore
  157. // *****************************************************************************************
  158. // ADVAPI.DLL
  159. // *****************************************************************************************
  160. BOOL DemandLoadAdvApi32(void);
  161. static HMODULE s_hAdvApi = 0;
  162. LOADER_FUNCTION(BOOL, CryptAcquireContextA,
  163. (HCRYPTPROV * phProv, LPCTSTR pszContainer, LPCTSTR pszProvider, DWORD dwProvType, DWORD dwFlags),
  164. (phProv, pszContainer, pszProvider, dwProvType, dwFlags),
  165. FALSE, AdvApi32)
  166. #define CryptAcquireContextA VAR_CryptAcquireContextA
  167. LOADER_FUNCTION( BOOL, CryptReleaseContext,
  168. (HCRYPTPROV hProv, DWORD dwFlags),
  169. (hProv, dwFlags),
  170. FALSE, AdvApi32)
  171. #define CryptReleaseContext VAR_CryptReleaseContext
  172. // *****************************************************************************************
  173. // Various Structures and typdefs
  174. // *****************************************************************************************
  175. typedef BLOB THUMBBLOB;
  176. // This struct and tags will be published by the exchange group -- this is temporary.
  177. #define NUM_CERT_TAGS 2
  178. #define CERT_TAG_DEFAULT 0x20
  179. #define CERT_TAG_THUMBPRINT 0x22
  180. // SIZE_CERTTAGS is the size of the structure excluding the byte array.
  181. #define SIZE_CERTTAGS (2 * sizeof(WORD))
  182. //N warnings, should probably just remove the []
  183. #pragma warning (disable:4200)
  184. typedef struct _CertTag
  185. {
  186. WORD tag;
  187. WORD cbData;
  188. BYTE rgbData[];
  189. } CERTTAGS, FAR * LPCERTTAGS;
  190. #pragma warning (default:4200)
  191. #define LPARAM_SENTRY 0x424A4800
  192. typedef struct _AB_DIALOG_PANE_PARAMS {
  193. DWORD dwSentry; // Must be set to value of LPARAM_SENTRY
  194. LPWABOBJECT lpWABObject;
  195. LPADRBOOK lpAdrBook;
  196. PCERT_CONTEXT * rgCertContext; // array of cert context pointers
  197. ULONG cCertContexts; // how many cert in rgCertContext
  198. ULONG iLeafCert; // index in array of the leaf cert
  199. LPTSTR lpDisplayName;
  200. LPTSTR lpEmailAddress;
  201. HCRYPTPROV hCryptProv;
  202. } AB_DIALOG_PANE_PARAMS, *LPAB_DIALOG_PANE_PARAMS;
  203. static BOOL s_fCertViewPropertiesCryptUIA = FALSE;
  204. BOOL DemandLoadCryptDlg(void) {
  205. BOOL fRet = TRUE;
  206. if (0 == s_hCryptDlg) {
  207. s_hCryptDlg = LoadLibrary("CRYPTDLG.DLL");
  208. if (0 == s_hCryptDlg) {
  209. DebugTrace("LoadLibrary of CRYPTDLG.DLL failed\n");
  210. fRet = FALSE;
  211. } else {
  212. GET_PROC_ADDR(s_hCryptDlg, GetFriendlyNameOfCertA)
  213. GET_PROC_ADDR(s_hCryptDlg, CertViewPropertiesA)
  214. }
  215. }
  216. return(fRet);
  217. }
  218. BOOL CryptUIAvailable(void) {
  219. DemandLoadCryptDlg();
  220. return(s_fCertViewPropertiesCryptUIA);
  221. }
  222. BOOL DemandLoadCrypt32(void) {
  223. BOOL fRet = TRUE;
  224. if (0 == s_hCrypt32) {
  225. s_hCrypt32 = LoadLibrary("CRYPT32.DLL");
  226. if (0 == s_hCrypt32) {
  227. DebugTrace("LoadLibrary of CRYPT32.DLL failed\n");
  228. fRet = FALSE;
  229. } else {
  230. GET_PROC_ADDR(s_hCrypt32, CertFreeCertificateContext)
  231. GET_PROC_ADDR(s_hCrypt32, CertDuplicateCertificateContext)
  232. GET_PROC_ADDR(s_hCrypt32, CertCloseStore)
  233. GET_PROC_ADDR(s_hCrypt32, CertOpenSystemStoreA)
  234. GET_PROC_ADDR(s_hCrypt32, CertGetCertificateContextProperty)
  235. GET_PROC_ADDR(s_hCrypt32, CertOpenStore)
  236. GET_PROC_ADDR(s_hCrypt32, CertEnumCertificatesInStore)
  237. GET_PROC_ADDR(s_hCrypt32, CertGetIssuerCertificateFromStore)
  238. GET_PROC_ADDR(s_hCrypt32, CertCompareCertificate)
  239. GET_PROC_ADDR(s_hCrypt32, CryptMsgClose)
  240. GET_PROC_ADDR(s_hCrypt32, CryptMsgGetParam)
  241. GET_PROC_ADDR(s_hCrypt32, CryptMsgUpdate)
  242. GET_PROC_ADDR(s_hCrypt32, CryptMsgOpenToDecode)
  243. GET_PROC_ADDR(s_hCrypt32, CertRDNValueToStrA)
  244. GET_PROC_ADDR(s_hCrypt32, CertFindRDNAttr)
  245. GET_PROC_ADDR(s_hCrypt32, CryptDecodeObject)
  246. GET_PROC_ADDR(s_hCrypt32, CertAddCertificateContextToStore)
  247. GET_PROC_ADDR(s_hCrypt32, CertAddEncodedCertificateToStore)
  248. }
  249. }
  250. return(fRet);
  251. }
  252. BOOL DemandLoadAdvApi32(void) {
  253. BOOL fRet = TRUE;
  254. if (0 == s_hAdvApi) {
  255. s_hAdvApi = LoadLibrary("ADVAPI32.DLL");
  256. if (0 == s_hAdvApi) {
  257. DebugTrace("LoadLibrary of ADVAPI32.DLL failed\n");
  258. fRet = FALSE;
  259. } else {
  260. GET_PROC_ADDR(s_hAdvApi, CryptAcquireContextA)
  261. GET_PROC_ADDR(s_hAdvApi, CryptReleaseContext)
  262. }
  263. }
  264. return(fRet);
  265. }
  266. /***************************************************************************
  267. Name : IsThumbprintInMVPBin
  268. Purpose : Check the PR_USER_X509_CERTIFICATE prop for this vsthumbprint
  269. Parameters: spv = prop value structure of PR_USER_X509_CERTIFICATE
  270. lpThumbprint -> THUMBBLOB structure to find
  271. Returns : TRUE if found
  272. Comment :
  273. ***************************************************************************/
  274. BOOL IsThumbprintInMVPBin(SPropValue spv, THUMBBLOB * lpThumbprint) {
  275. ULONG cValues, i;
  276. LPSBinary lpsb = NULL;
  277. LPCERTTAGS lpCurrentTag;
  278. LPBYTE lpbTagEnd;
  279. if (! PROP_ERROR((spv))) {
  280. lpsb = spv.Value.MVbin.lpbin;
  281. cValues = spv.Value.MVbin.cValues;
  282. // Check for duplicates
  283. for (i = 0; i < cValues; i++) {
  284. lpCurrentTag = (LPCERTTAGS)lpsb[i].lpb;
  285. lpbTagEnd = (LPBYTE)lpCurrentTag + lpsb[i].cb;
  286. while ((LPBYTE)lpCurrentTag < lpbTagEnd) {
  287. // Check if this is the tag that contains the thumbprint
  288. if (CERT_TAG_THUMBPRINT == lpCurrentTag->tag) {
  289. if ((lpThumbprint->cbSize == lpCurrentTag->cbData - SIZE_CERTTAGS) &&
  290. ! memcmp(lpThumbprint->pBlobData, &lpCurrentTag->rgbData,
  291. lpThumbprint->cbSize)) {
  292. return(TRUE);
  293. }
  294. }
  295. lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + lpCurrentTag->cbData);
  296. }
  297. }
  298. }
  299. return(FALSE);
  300. }
  301. /***************************************************************************
  302. Name : HrBuildCertSBinaryData
  303. Purpose : Takes as input all the data needed for a cert entry
  304. in PR_USER_X509_CERTIFICATE and returns a pointer to
  305. memory that contains all the input data in the correct
  306. format to be plugged in to the lpb member of an SBinary
  307. structure. This memory should be Freed by the caller.
  308. Parameters: bIsDefault - TRUE if this is the default cert
  309. pblobCertThumbPrint - The actual certificate thumbprint
  310. lplpbData - receives the buffer with the data
  311. lpcbData - receives size of the data
  312. Returns : HRESULT
  313. Comment :
  314. ***************************************************************************/
  315. HRESULT HrBuildCertSBinaryData(
  316. BOOL bIsDefault,
  317. THUMBBLOB* pPrint,
  318. LPBYTE FAR* lplpbData,
  319. ULONG FAR* lpcbData)
  320. {
  321. WORD cbDefault, cbPrint;
  322. HRESULT hr = S_OK;
  323. LPCERTTAGS lpCurrentTag;
  324. ULONG cbSize, cProps;
  325. LPBYTE lpb = NULL;
  326. cbDefault = sizeof(bIsDefault);
  327. cbPrint = (WORD) pPrint->cbSize;
  328. cProps = 2;
  329. cbSize = cbDefault + cbPrint;
  330. cbSize += (cProps * SIZE_CERTTAGS);
  331. if (! (lpb = LocalAlloc(LPTR, cbSize))) {
  332. hr = E_OUTOFMEMORY;
  333. goto exit;
  334. }
  335. // Set the default property
  336. lpCurrentTag = (LPCERTTAGS)lpb;
  337. lpCurrentTag->tag = CERT_TAG_DEFAULT;
  338. lpCurrentTag->cbData = SIZE_CERTTAGS + cbDefault;
  339. memcpy(&lpCurrentTag->rgbData, &bIsDefault, cbDefault);
  340. // Set the thumbprint property
  341. lpCurrentTag = (LPCERTTAGS)((BYTE*)lpCurrentTag + lpCurrentTag->cbData);
  342. lpCurrentTag->tag = CERT_TAG_THUMBPRINT;
  343. lpCurrentTag->cbData = SIZE_CERTTAGS + cbPrint;
  344. memcpy(&lpCurrentTag->rgbData, pPrint->pBlobData, cbPrint);
  345. *lpcbData = cbSize;
  346. *lplpbData = lpb;
  347. exit:
  348. return(hr);
  349. }
  350. /* PVGetCertificateParam:
  351. **
  352. ** Purpose:
  353. ** Combine the "how big? okay, here." double question to get a parameter
  354. ** from a certificate. Give it a thing to get and it will alloc the mem.
  355. ** Takes:
  356. ** IN pCert - CAPI certificate to query
  357. ** IN dwParam - parameter to find, ex: CERT_SHA1_HASH_PROP_ID
  358. ** OUT OPTIONAL cbOut - (def value of NULL) size of the returned PVOID
  359. ** Returns:
  360. ** data that was obtained, NULL if failed
  361. */
  362. LPVOID PVGetCertificateParam(
  363. PCCERT_CONTEXT pCert,
  364. DWORD dwParam,
  365. DWORD *cbOut)
  366. {
  367. DWORD cbData;
  368. void *pvData = NULL;
  369. if (!pCert) {
  370. SetLastError((DWORD)E_INVALIDARG);
  371. goto ErrorReturn;
  372. }
  373. cbData = 0;
  374. CertGetCertificateContextProperty(pCert, dwParam, NULL, &cbData);
  375. if (! cbData || (! (pvData = LocalAlloc(LPTR, cbData)))) {
  376. DebugTrace("CertGetCertificateContextProperty -> %x\n", GetLastError());
  377. goto ErrorReturn;
  378. }
  379. if (! CertGetCertificateContextProperty(pCert, dwParam, pvData, &cbData)) {
  380. DebugTrace("CertGetCertificateContextProperty -> %x\n", GetLastError());
  381. goto ErrorReturn;
  382. }
  383. exit:
  384. if (cbOut) {
  385. *cbOut = cbData;
  386. }
  387. return(pvData);
  388. ErrorReturn:
  389. if (pvData) {
  390. LocalFree(pvData);
  391. pvData = NULL;
  392. }
  393. cbData = 0;
  394. goto exit;
  395. }
  396. /*
  397. **
  398. ** FUNCTION: GetAttributeString
  399. **
  400. ** PURPOSE: Get the string associated with the given attribute
  401. **
  402. ** PARAMETERS: lplpszAttributeString - pointer that will be LocalAlloc'ed
  403. ** to hold the string. Caller must LocalFree this!
  404. ** pbEncoded - the encoded blob
  405. ** cbEncoded - size of the encoded blob
  406. ** lpszObjID - object ID of attribute to retrieve
  407. **
  408. ** RETURNS: HRESULT.
  409. **
  410. ** HISTORY:
  411. ** 96/10/03 markdu Created for WAB
  412. **
  413. */
  414. HRESULT GetAttributeString(LPTSTR FAR * lplpszAttributeString,
  415. BYTE *pbEncoded,
  416. DWORD cbEncoded,
  417. LPCSTR lpszObjID)
  418. {
  419. HRESULT hr = hrSuccess;
  420. BOOL fRet;
  421. PCERT_RDN_ATTR pRdnAttr;
  422. PCERT_NAME_INFO pNameInfo = NULL;
  423. DWORD cbInfo;
  424. DWORD cbData; //N need both?
  425. // Initialize so we know if any data was copied in.
  426. *lplpszAttributeString = NULL;
  427. // Get the size of the subject name data
  428. cbInfo = 0;
  429. CryptDecodeObject(
  430. X509_ASN_ENCODING, // indicates X509 encoding
  431. (LPCSTR)X509_NAME, // flag indicating a name blob is to be decoded
  432. pbEncoded, // pointer to a buffer holding the encoded name
  433. cbEncoded, // length in bytes of the encoded name
  434. //N maybe can use nocopy flag
  435. 0, // flags
  436. NULL, // NULL used when just geting length
  437. &cbInfo); // length in bytes of the decoded name
  438. if (0 == cbInfo) {
  439. hr = GetLastError();
  440. goto exit;
  441. }
  442. // Allocate space for the decoded name
  443. if (! (pNameInfo = LocalAlloc(LPTR, cbInfo))) {
  444. hr = ResultFromScode(MAPI_E_NOT_ENOUGH_MEMORY);
  445. goto exit;
  446. }
  447. // Get the subject name
  448. if (! CryptDecodeObject(
  449. X509_ASN_ENCODING, // indicates X509 encoding
  450. (LPCSTR)X509_NAME, // flag indicating a name blob is to be decoded
  451. pbEncoded, // pointer to a buffer holding the encoded name
  452. cbEncoded, // length in bytes of the encoded name
  453. 0, // flags
  454. pNameInfo, // the buffer where the decoded name is written to
  455. &cbInfo)) { // length in bytes of the decoded name
  456. hr = GetLastError();
  457. goto exit;
  458. }
  459. // Now we have a decoded name RDN array, so find the oid we want
  460. if (! (pRdnAttr = CertFindRDNAttr(lpszObjID, pNameInfo))) {
  461. hr = MAPI_E_NOT_FOUND;
  462. goto exit;
  463. }
  464. // We only handle certain types
  465. //N look to see if we should have a stack var for the ->
  466. if ((CERT_RDN_NUMERIC_STRING != pRdnAttr->dwValueType) &&
  467. (CERT_RDN_PRINTABLE_STRING != pRdnAttr->dwValueType) &&
  468. (CERT_RDN_IA5_STRING != pRdnAttr->dwValueType) &&
  469. (CERT_RDN_VISIBLE_STRING != pRdnAttr->dwValueType) &&
  470. (CERT_RDN_ISO646_STRING != pRdnAttr->dwValueType) &&
  471. (CERT_RDN_UNIVERSAL_STRING != pRdnAttr->dwValueType) &&
  472. (CERT_RDN_TELETEX_STRING != pRdnAttr->dwValueType) &&
  473. (CERT_RDN_UNICODE_STRING != pRdnAttr->dwValueType)) {
  474. hr = MAPI_E_INVALID_PARAMETER;
  475. goto exit;
  476. }
  477. // Find out how much space to allocate.
  478. switch (pRdnAttr->dwValueType) {
  479. case CERT_RDN_UNICODE_STRING:
  480. cbData = WideCharToMultiByte(
  481. CP_ACP,
  482. 0,
  483. (LPWSTR)pRdnAttr->Value.pbData,
  484. -1,
  485. NULL,
  486. 0,
  487. NULL,
  488. NULL);
  489. break;
  490. case CERT_RDN_UNIVERSAL_STRING:
  491. case CERT_RDN_TELETEX_STRING:
  492. cbData = CertRDNValueToStr(pRdnAttr->dwValueType,
  493. (PCERT_RDN_VALUE_BLOB)&(pRdnAttr->Value),
  494. NULL,
  495. 0);
  496. break;
  497. default:
  498. cbData = pRdnAttr->Value.cbData + 1;
  499. break;
  500. }
  501. // Allocate the space for the string.
  502. if (! (*lplpszAttributeString = LocalAlloc(LPTR, cbData))) {
  503. hr = ResultFromScode(MAPI_E_NOT_ENOUGH_MEMORY);
  504. goto exit;
  505. }
  506. // Copy the string
  507. switch (pRdnAttr->dwValueType) {
  508. case CERT_RDN_UNICODE_STRING:
  509. if (FALSE == WideCharToMultiByte(
  510. CP_ACP,
  511. 0,
  512. (LPWSTR)pRdnAttr->Value.pbData,
  513. -1,
  514. *lplpszAttributeString,
  515. cbData,
  516. NULL,
  517. NULL))
  518. {
  519. DWORD dwErr = GetLastError();
  520. switch(dwErr)
  521. {
  522. case ERROR_INSUFFICIENT_BUFFER:
  523. hr = ResultFromScode(MAPI_E_NOT_ENOUGH_MEMORY);
  524. break;
  525. case ERROR_INVALID_PARAMETER:
  526. hr = ResultFromScode(MAPI_E_INVALID_PARAMETER);
  527. break;
  528. default:
  529. hr = ResultFromScode(MAPI_E_CALL_FAILED);
  530. break;
  531. }
  532. goto exit;
  533. }
  534. break;
  535. case CERT_RDN_UNIVERSAL_STRING:
  536. case CERT_RDN_TELETEX_STRING:
  537. CertRDNValueToStr(pRdnAttr->dwValueType,
  538. (PCERT_RDN_VALUE_BLOB)&(pRdnAttr->Value),
  539. *lplpszAttributeString,
  540. cbData);
  541. break;
  542. default:
  543. lstrcpyn(*lplpszAttributeString, (LPCSTR)pRdnAttr->Value.pbData, cbData);
  544. (*lplpszAttributeString)[cbData - 1] = '\0';
  545. break;
  546. }
  547. exit:
  548. if (hr && *lplpszAttributeString) {
  549. LocalFree(*lplpszAttributeString);
  550. *lplpszAttributeString = NULL;
  551. }
  552. if (NULL != pNameInfo) {
  553. LocalFree(pNameInfo);
  554. }
  555. return(hr);
  556. }
  557. /***************************************************************************
  558. Name : AddPropToMVPBin
  559. Purpose : Add a property to a multi-valued binary property in a prop array
  560. Parameters: lpWABObject -> WAB Object
  561. lpaProps -> array of properties
  562. uPropTag = property tag for MVP
  563. index = index in lpaProps of MVP
  564. lpNew -> new data
  565. cbNew = size of lpbNew
  566. fNoDuplicates = TRUE if we should not add duplicates
  567. Returns : HRESULT
  568. Comment : Find the size of the existing MVP
  569. Add in the size of the new entry
  570. allocate new space
  571. copy old to new
  572. free old
  573. copy new entry
  574. point prop array lpbin the new space
  575. increment cValues
  576. Note: The new MVP memory is AllocMore'd onto the lpaProps
  577. allocation. We will unlink the pointer to the old MVP array,
  578. but this will be cleaned up when the prop array is freed.
  579. ***************************************************************************/
  580. HRESULT AddPropToMVPBin(LPWABOBJECT lpWABObject,
  581. LPSPropValue lpaProps,
  582. DWORD index,
  583. LPVOID lpNew,
  584. ULONG cbNew,
  585. BOOL fNoDuplicates)
  586. {
  587. UNALIGNED SBinaryArray * lprgsbOld = NULL;
  588. SBinaryArray * lprgsbNew = NULL;
  589. LPSBinary lpsbOld = NULL;
  590. LPSBinary lpsbNew = NULL;
  591. ULONG cbMVP = 0;
  592. ULONG cExisting = 0;
  593. LPBYTE lpNewTemp = NULL;
  594. HRESULT hResult = hrSuccess;
  595. SCODE sc = SUCCESS_SUCCESS;
  596. ULONG i;
  597. // Find the size of any existing MVP entries
  598. if (PT_ERROR == PROP_TYPE(lpaProps[index].ulPropTag)) {
  599. // Un-ERROR the property tag
  600. lpaProps[index].ulPropTag = PROP_TAG(PT_MV_BINARY, PROP_ID(lpaProps[index].ulPropTag));
  601. } else {
  602. // point to the structure in the prop array.
  603. lprgsbOld = &(lpaProps[index].Value.MVbin);
  604. lpsbOld = lprgsbOld->lpbin;
  605. cExisting = lprgsbOld->cValues;
  606. // Check for duplicates
  607. if (fNoDuplicates) {
  608. for (i = 0; i < cExisting; i++) {
  609. if (cbNew == lpsbOld[i].cb &&
  610. ! memcmp(lpNew, lpsbOld[i].lpb, cbNew)) {
  611. DebugTrace("AddPropToMVPBin found duplicate.\n");
  612. return(hrSuccess);
  613. }
  614. }
  615. }
  616. cbMVP = cExisting * sizeof(SBinary);
  617. }
  618. // cbMVP now contains the current size of the MVP
  619. cbMVP += sizeof(SBinary); // room in the MVP for another Sbin
  620. // Allocate room for new MVP
  621. if (sc = lpWABObject->lpVtbl->AllocateMore(lpWABObject, cbMVP, lpaProps, (LPVOID*)&lpsbNew)) {
  622. DebugTrace("AddPropToMVPBin allocation (%u) failed %x\n", cbMVP, sc);
  623. hResult = ResultFromScode(sc);
  624. return(hResult);
  625. }
  626. // If there are properties there already, copy them to our new MVP
  627. for (i = 0; i < cExisting; i++) {
  628. // Copy this property value to the MVP
  629. lpsbNew[i].cb = lpsbOld[i].cb;
  630. lpsbNew[i].lpb = lpsbOld[i].lpb;
  631. }
  632. // Add the new property value
  633. // Allocate room for it
  634. if (sc = lpWABObject->lpVtbl->AllocateMore(lpWABObject, cbNew, lpaProps, (LPVOID*)&(lpsbNew[i].lpb))) {
  635. DebugTrace("AddPropToMVPBin allocation (%u) failed %x\n", cbNew, sc);
  636. hResult = ResultFromScode(sc);
  637. return(hResult);
  638. }
  639. lpsbNew[i].cb = cbNew;
  640. CopyMemory(lpsbNew[i].lpb, lpNew, cbNew);
  641. lpaProps[index].Value.MVbin.lpbin = lpsbNew;
  642. lpaProps[index].Value.MVbin.cValues = cExisting + 1;
  643. return(hResult);
  644. }
  645. // enum for ADRENTRY props
  646. enum {
  647. irnPR_ENTRYID = 0,
  648. irnPR_DISPLAY_NAME,
  649. irnPR_EMAIL_ADDRESS,
  650. irnPR_OBJECT_TYPE,
  651. irnMax
  652. };
  653. // enum for getting the entryid of an entry
  654. enum {
  655. itbdPR_USER_X509_CERTIFICATE,
  656. itbMax
  657. };
  658. static const SizedSPropTagArray(itbMax, ptaCert) =
  659. {
  660. itbMax,
  661. {
  662. PR_USER_X509_CERTIFICATE,
  663. }
  664. };
  665. enum {
  666. iconPR_DEF_CREATE_MAILUSER = 0,
  667. iconMax
  668. };
  669. static const SizedSPropTagArray(iconMax, ptaCon)=
  670. {
  671. iconMax,
  672. {
  673. PR_DEF_CREATE_MAILUSER,
  674. }
  675. };
  676. // enum for setting the created properties
  677. enum {
  678. imuPR_DISPLAY_NAME = 0, // must be first so DL's can use same enum
  679. imuPR_EMAIL_ADDRESS,
  680. imuPR_ADDRTYPE,
  681. imuMax
  682. };
  683. static const SizedSPropTagArray(imuMax, ptag)=
  684. {
  685. imuMax,
  686. {
  687. PR_DISPLAY_NAME,
  688. PR_EMAIL_ADDRESS,
  689. PR_ADDRTYPE,
  690. }
  691. };
  692. // enum for getting the entryid of an entry
  693. enum {
  694. ieidPR_ENTRYID,
  695. ieidMax
  696. };
  697. static const SizedSPropTagArray(ieidMax, ptaEID)=
  698. {
  699. ieidMax,
  700. {
  701. PR_ENTRYID,
  702. }
  703. };
  704. HRESULT HrAddCertsToWAB(HWND hwnd, LPWABOBJECT lpWABObject, LPADRBOOK lpAdrBook, HCRYPTPROV hCryptProv,
  705. PCERT_CONTEXT * rgCertContext, ULONG cCertContexts, ULONG iLeaf, LPTSTR lpDisplayName, LPTSTR lpEmailAddress)
  706. {
  707. HRESULT hr;
  708. SCODE sc;
  709. BOOL fFound;
  710. ULONG cCerts;
  711. LPSPropValue ppv = NULL;
  712. LPSPropValue ppvEID = NULL;
  713. BOOL fAlreadyHasCert;
  714. ULONG ul;
  715. LPADRLIST lpAdrList = NULL;
  716. LPMAILUSER lpMailUser = NULL;
  717. ULONG ulObjectType;
  718. LPBYTE lpCertProp;
  719. ULONG cbCertProp;
  720. LPSPropValue ppvUndo = NULL;
  721. HCERTSTORE hcAB = 0, hcCA = 0;
  722. PCCERT_CONTEXT pccLeaf = NULL;
  723. THUMBBLOB Thumbprint = {0};
  724. ULONG i, iEntry;
  725. BOOL fShowUI = TRUE;
  726. HCRYPTPROV hProv = 0;
  727. SPropValue spv[imuMax];
  728. ULONG cbEIDWAB;
  729. LPENTRYID lpEIDWAB = NULL;
  730. ULONG cProps;
  731. LPSPropValue lpCreateEIDs = NULL;
  732. LPABCONT lpContainer = NULL;
  733. BOOL fCreateNew = FALSE;
  734. if (! rgCertContext || ! lpAdrBook || ! lpWABObject) {
  735. return(ResultFromScode(E_FAIL));
  736. }
  737. DebugTrace("Certificate for '%s'. Email: '%s'\n", lpDisplayName, lpEmailAddress ? lpEmailAddress : szEmpty);
  738. if (! (hcCA = CertOpenSystemStoreA(hCryptProv, szCA))) {
  739. hr = GetLastError();
  740. goto exit;
  741. }
  742. if (! (hcAB = CertOpenSystemStore(hCryptProv, szAB))) {
  743. hr = GetLastError();
  744. goto exit;
  745. }
  746. // Add all the certs to the cert stores
  747. // Leaf goes in WAB store, others go in CA
  748. for (i = 0; i < cCertContexts; i++) {
  749. if (i == iLeaf) {
  750. if (CertAddCertificateContextToStore(hcAB,
  751. rgCertContext[i],
  752. CERT_STORE_ADD_REPLACE_EXISTING,
  753. &pccLeaf)) {
  754. // Get it's thumbprint
  755. if (! (Thumbprint.pBlobData = (BYTE *)PVGetCertificateParam(
  756. pccLeaf,
  757. CERT_HASH_PROP_ID,
  758. &Thumbprint.cbSize))) {
  759. goto exit;
  760. }
  761. } else {
  762. hr = GetLastError();
  763. DebugTrace("CertAddCertificateContextToStore -> %x\n", hr);
  764. goto exit;
  765. }
  766. } else {
  767. if (! CertAddCertificateContextToStore(hcCA,
  768. rgCertContext[i],
  769. CERT_STORE_ADD_REPLACE_EXISTING,
  770. NULL)) {
  771. DebugTrace("CertAddCertificateContextToStore -> %x\n", GetLastError());
  772. // Don't fail, just go on
  773. }
  774. }
  775. }
  776. if (sc = lpWABObject->lpVtbl->AllocateBuffer(lpWABObject,
  777. sizeof(ADRLIST) + 1 * sizeof(ADRENTRY), (LPVOID*)&lpAdrList)) {
  778. hr = ResultFromScode(sc);
  779. goto exit;
  780. }
  781. lpAdrList->cEntries = 1;
  782. lpAdrList->aEntries[0].ulReserved1 = 0;
  783. lpAdrList->aEntries[0].cValues = irnMax;
  784. // Allocate the prop array for the ADRENTRY
  785. if (sc = lpWABObject->lpVtbl->AllocateBuffer(lpWABObject,
  786. lpAdrList->aEntries[0].cValues * sizeof(SPropValue),
  787. (LPVOID*)&lpAdrList->aEntries[0].rgPropVals)) {
  788. hr = ResultFromScode(sc);
  789. goto exit;
  790. }
  791. lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].ulPropTag = PR_ENTRYID;
  792. lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin.cb = 0;
  793. lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin.lpb = NULL;
  794. lpAdrList->aEntries[0].rgPropVals[irnPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
  795. lpAdrList->aEntries[0].rgPropVals[irnPR_OBJECT_TYPE].Value.l = MAPI_MAILUSER;
  796. if (lpDisplayName) {
  797. lpAdrList->aEntries[0].rgPropVals[irnPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME;
  798. lpAdrList->aEntries[0].rgPropVals[irnPR_DISPLAY_NAME].Value.LPSZ = lpDisplayName;
  799. } else {
  800. lpAdrList->aEntries[0].rgPropVals[irnPR_DISPLAY_NAME].ulPropTag = PR_NULL;
  801. }
  802. if (lpEmailAddress) {
  803. lpAdrList->aEntries[0].rgPropVals[irnPR_EMAIL_ADDRESS].ulPropTag = PR_EMAIL_ADDRESS;
  804. lpAdrList->aEntries[0].rgPropVals[irnPR_EMAIL_ADDRESS].Value.LPSZ = lpEmailAddress;
  805. } else {
  806. lpAdrList->aEntries[0].rgPropVals[irnPR_EMAIL_ADDRESS].ulPropTag = PR_NULL;
  807. }
  808. hr = lpAdrBook->lpVtbl->ResolveName(lpAdrBook,
  809. (ULONG_PTR)hwnd,
  810. MAPI_DIALOG | WAB_RESOLVE_LOCAL_ONLY | WAB_RESOLVE_ALL_EMAILS |
  811. WAB_RESOLVE_NO_ONE_OFFS | WAB_RESOLVE_NO_NOT_FOUND_UI,
  812. NULL, // BUGBUG: name for NewEntry dialog?
  813. lpAdrList);
  814. switch (GetScode(hr)) {
  815. case SUCCESS_SUCCESS: // Should be a resolved entry now
  816. // Should have PR_ENTRYID in rgPropVals[irnPR_ENTRYID]
  817. if (lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].ulPropTag == PR_ENTRYID) {
  818. if (HR_FAILED(hr = lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
  819. lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin.cb,
  820. (LPENTRYID)lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin.lpb,
  821. NULL,
  822. MAPI_MODIFY, // ulFlags
  823. &ulObjectType,
  824. (LPUNKNOWN *)&lpMailUser))) {
  825. DebugTrace("OpenEntry -> %x\n", GetScode(hr));
  826. goto exit;
  827. }
  828. }
  829. break;
  830. case MAPI_E_NOT_FOUND:
  831. // no match, create one
  832. // Get the PAB object
  833. if (HR_FAILED(hr = lpAdrBook->lpVtbl->GetPAB(lpAdrBook, &cbEIDWAB, &lpEIDWAB))) {
  834. goto exit; // Bad stuff here!
  835. }
  836. if (HR_FAILED(hr = lpAdrBook->lpVtbl->OpenEntry(lpAdrBook,
  837. cbEIDWAB, // size of EntryID to open
  838. lpEIDWAB, // EntryID to open
  839. NULL, // interface
  840. 0, // flags
  841. &ulObjectType,
  842. (LPUNKNOWN *)&lpContainer))) {
  843. goto exit;
  844. }
  845. // Get us the creation entryids
  846. if (hr = lpContainer->lpVtbl->GetProps(lpContainer, (LPSPropTagArray)&ptaCon, 0, &cProps, &lpCreateEIDs)) {
  847. goto exit; // Bad stuff here!
  848. }
  849. if (HR_FAILED(hr = lpContainer->lpVtbl->CreateEntry(lpContainer,
  850. lpCreateEIDs[iconPR_DEF_CREATE_MAILUSER].Value.bin.cb,
  851. (LPENTRYID)lpCreateEIDs[iconPR_DEF_CREATE_MAILUSER].Value.bin.lpb,
  852. 0, //CREATE_CHECK_DUP_STRICT
  853. (LPMAPIPROP *)&lpMailUser))) {
  854. goto exit;
  855. }
  856. // Successful creation of new entry. Fill in email and displayname
  857. spv[imuPR_EMAIL_ADDRESS].ulPropTag = PR_EMAIL_ADDRESS;
  858. spv[imuPR_EMAIL_ADDRESS].Value.lpszA = lpEmailAddress;
  859. spv[imuPR_ADDRTYPE].ulPropTag = PR_ADDRTYPE;
  860. spv[imuPR_ADDRTYPE].Value.lpszA = "SMTP";
  861. spv[imuPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME;
  862. spv[imuPR_DISPLAY_NAME].Value.lpszA = lpDisplayName;
  863. if (HR_FAILED(hr = lpMailUser->lpVtbl->SetProps(lpMailUser, // this
  864. imuMax, // cValues
  865. spv, // property array
  866. NULL))) { // problems array
  867. DebugTrace("SetProps -> %x\n", GetScode(hr));
  868. }
  869. // Need to save so we can get an entryid later
  870. if (HR_FAILED(hr = lpMailUser->lpVtbl->SaveChanges(lpMailUser, KEEP_OPEN_READWRITE))) {
  871. goto exit;
  872. }
  873. if (HR_FAILED(hr = lpMailUser->lpVtbl->GetProps(lpMailUser,
  874. (LPSPropTagArray)&ptaEID, 0, &ul, &ppvEID))) {
  875. goto exit;
  876. }
  877. lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].ulPropTag = PR_ENTRYID;
  878. lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin.cb =
  879. ppvEID[ieidPR_ENTRYID].Value.bin.cb;
  880. lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin.lpb =
  881. ppvEID[ieidPR_ENTRYID].Value.bin.lpb;
  882. fCreateNew = TRUE;
  883. break;
  884. case MAPI_E_USER_CANCEL:
  885. // cancel, don't update
  886. default:
  887. break;
  888. }
  889. if (lpMailUser) {
  890. // Got the entry, Set the cert property
  891. if (HR_FAILED(hr = lpMailUser->lpVtbl->GetProps(lpMailUser, (LPSPropTagArray)&ptaCert, 0, &ul, &ppv))) {
  892. // Shouldn't happen, but if it does, we don't have a lpPropArray
  893. goto exit;
  894. }
  895. if (! IsThumbprintInMVPBin(ppv[0], &Thumbprint)) {
  896. if (HR_FAILED(hr = HrBuildCertSBinaryData(PROP_ERROR(ppv[0]), // Default if there is no current value
  897. &Thumbprint,
  898. &lpCertProp,
  899. &cbCertProp))) {
  900. goto exit;
  901. }
  902. // Add the new thumbprint to PR_USER_X509_CERTIFICATE
  903. if (HR_FAILED(hr = AddPropToMVPBin(lpWABObject,
  904. ppv, // prop array
  905. 0, // index of PR_USER_X509_CERTIFICATE in ppv
  906. lpCertProp,
  907. cbCertProp,
  908. TRUE))) { // fNoDuplicates
  909. goto exit;
  910. }
  911. if (fShowUI) {
  912. // Save undo information
  913. if (HR_FAILED(hr = lpMailUser->lpVtbl->GetProps(lpMailUser, (LPSPropTagArray)&ptaCert, 0,
  914. &ul, &ppvUndo))) {
  915. ppvUndo = NULL;
  916. }
  917. }
  918. if (HR_FAILED(hr = lpMailUser->lpVtbl->SetProps(lpMailUser, 1, ppv, NULL))) {
  919. goto exit;
  920. }
  921. if (HR_FAILED(hr = lpMailUser->lpVtbl->SaveChanges(lpMailUser, KEEP_OPEN_READWRITE))) {
  922. goto exit;
  923. }
  924. }
  925. if (fShowUI) {
  926. hr = lpAdrBook->lpVtbl->Details(lpAdrBook,
  927. (PULONG_PTR)&hwnd,
  928. NULL,
  929. NULL,
  930. lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin.cb,
  931. (LPENTRYID)lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin.lpb,
  932. NULL,
  933. NULL,
  934. NULL,
  935. 0);
  936. if (ResultFromScode(hr) == MAPI_E_USER_CANCEL && (ppvUndo || fCreateNew)) {
  937. // Undo
  938. if (fCreateNew && lpContainer) {
  939. ENTRYLIST EntryList;
  940. EntryList.cValues = 1;
  941. EntryList.lpbin = &lpAdrList->aEntries[0].rgPropVals[irnPR_ENTRYID].Value.bin;
  942. // Now, delete the entry found.
  943. if (hr = lpContainer->lpVtbl->DeleteEntries(lpContainer, &EntryList, 0)) {
  944. goto exit;
  945. }
  946. } else {
  947. // Not a new entry, restore the original cert props
  948. if (HR_FAILED(hr = lpMailUser->lpVtbl->SetProps(lpMailUser, 1, ppvUndo, NULL))) {
  949. goto exit;
  950. }
  951. if (HR_FAILED(hr = lpMailUser->lpVtbl->SaveChanges(lpMailUser, 0))) {
  952. goto exit;
  953. }
  954. }
  955. }
  956. }
  957. }
  958. exit:
  959. if (lpAdrList) {
  960. for (iEntry = 0; iEntry < lpAdrList->cEntries; ++iEntry)
  961. {
  962. if(lpAdrList->aEntries[iEntry].rgPropVals)
  963. lpWABObject->lpVtbl->FreeBuffer(lpWABObject,
  964. lpAdrList->aEntries[iEntry].rgPropVals);
  965. }
  966. lpWABObject->lpVtbl->FreeBuffer(lpWABObject, lpAdrList);
  967. lpAdrList = NULL;
  968. }
  969. if (lpCreateEIDs) {
  970. lpWABObject->lpVtbl->FreeBuffer(lpWABObject, lpCreateEIDs);
  971. }
  972. if (ppvEID) {
  973. lpWABObject->lpVtbl->FreeBuffer(lpWABObject, ppvEID);
  974. }
  975. if (lpEIDWAB) {
  976. lpWABObject->lpVtbl->FreeBuffer(lpWABObject, lpEIDWAB);
  977. }
  978. if (lpContainer) {
  979. lpContainer->lpVtbl->Release(lpContainer);
  980. }
  981. if (lpMailUser) {
  982. lpMailUser->lpVtbl->Release(lpMailUser);
  983. }
  984. if (ppv) {
  985. lpWABObject->lpVtbl->FreeBuffer(lpWABObject, ppv);
  986. }
  987. if (ppvUndo) {
  988. lpWABObject->lpVtbl->FreeBuffer(lpWABObject, ppvUndo);
  989. }
  990. if (Thumbprint.pBlobData) {
  991. LocalFree(Thumbprint.pBlobData);
  992. }
  993. if (pccLeaf) {
  994. CertFreeCertificateContext(pccLeaf);
  995. }
  996. if (hcAB) {
  997. CertCloseStore(hcAB, 0);
  998. }
  999. if (hcCA) {
  1000. CertCloseStore(hcCA, 0);
  1001. }
  1002. return(hr);
  1003. }
  1004. //*******************************************************************
  1005. //
  1006. // FUNCTION: ReadDataFromFile
  1007. //
  1008. // PURPOSE: Read data from a file.
  1009. //
  1010. // PARAMETERS: lpszFileName - name of file containing the data to be read
  1011. // ppbData - receives the data that is read
  1012. // pcbData - receives the size of the data that is read
  1013. //
  1014. // RETURNS: HRESULT
  1015. //
  1016. // HISTORY:
  1017. // 96/12/16 markdu Created.
  1018. //
  1019. //*******************************************************************
  1020. HRESULT ReadDataFromFile(
  1021. LPCSTR lpszFileName,
  1022. PBYTE* ppbData,
  1023. PDWORD pcbData)
  1024. {
  1025. HRESULT hr = hrSuccess;
  1026. BOOL fRet;
  1027. HANDLE hFile = 0;
  1028. DWORD cbFile;
  1029. DWORD cbData;
  1030. PBYTE pbData = 0;
  1031. if ((NULL == ppbData) || (NULL == pcbData)) {
  1032. return(ResultFromScode(MAPI_E_INVALID_PARAMETER));
  1033. }
  1034. // Open the file and find out how big it is
  1035. if (INVALID_HANDLE_VALUE == (hFile = CreateFile(
  1036. lpszFileName,
  1037. GENERIC_READ,
  1038. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1039. NULL,
  1040. OPEN_EXISTING,
  1041. 0,
  1042. NULL))) {
  1043. hr = ResultFromScode(MAPI_E_DISK_ERROR);
  1044. goto error;
  1045. }
  1046. cbData = GetFileSize(hFile, NULL);
  1047. if (0xFFFFFFFF == cbData) {
  1048. hr = ResultFromScode(MAPI_E_DISK_ERROR);
  1049. goto error;
  1050. }
  1051. if (NULL == (pbData = (BYTE *)LocalAlloc(LMEM_ZEROINIT, cbData))) {
  1052. hr = ResultFromScode(MAPI_E_NOT_ENOUGH_MEMORY);
  1053. goto error;
  1054. }
  1055. if (! ReadFile(
  1056. hFile, // handle of file to read
  1057. pbData, // address of buffer that receives data
  1058. cbData, // number of bytes to read
  1059. &cbFile, // address of number of bytes read
  1060. NULL)) { // address of structure for data
  1061. hr = ResultFromScode(MAPI_E_DISK_ERROR);
  1062. goto error;
  1063. }
  1064. if (cbData != cbFile) {
  1065. hr = ResultFromScode(MAPI_E_CALL_FAILED);
  1066. goto error;
  1067. }
  1068. *ppbData = pbData;
  1069. *pcbData = cbData;
  1070. out:
  1071. if (hFile) {
  1072. CloseHandle(hFile);
  1073. }
  1074. return(hr);
  1075. error:
  1076. // BUGBUG some of the GetLastError calls above may not have worked.
  1077. if (hrSuccess == hr) {
  1078. hr = ResultFromScode(MAPI_E_CALL_FAILED);
  1079. }
  1080. goto out;
  1081. }
  1082. LPAB_DIALOG_PANE_PARAMS GetLParamFromPropSheetPage(PROPSHEETPAGE *ps) {
  1083. LONG lparam;
  1084. LPAB_DIALOG_PANE_PARAMS lpABDialogPaneParams;
  1085. ULONG i;
  1086. lpABDialogPaneParams = (LPAB_DIALOG_PANE_PARAMS)(ps->lParam);
  1087. if (lpABDialogPaneParams->dwSentry != LPARAM_SENTRY) {
  1088. // Assume that CryptUI has passed us a wrapped lparam/cert pair
  1089. // typedef struct tagCRYPTUI_INITDIALOG_STRUCT {
  1090. // LPARAM lParam;
  1091. // PCCERT_CONTEXT pCertContext;
  1092. // } CRYPTUI_INITDIALOG_STRUCT, *PCRYPTUI_INITDIALOG_STRUCT;
  1093. PCRYPTUI_INITDIALOG_STRUCT pCryptUIInitDialog = (PCRYPTUI_INITDIALOG_STRUCT)lpABDialogPaneParams;
  1094. lpABDialogPaneParams = (LPAB_DIALOG_PANE_PARAMS )pCryptUIInitDialog->lParam;
  1095. if (lpABDialogPaneParams->dwSentry != LPARAM_SENTRY) {
  1096. // Bad lparam
  1097. return(NULL);
  1098. }
  1099. }
  1100. return(lpABDialogPaneParams);
  1101. }
  1102. INT_PTR CALLBACK ViewPageAddressBook(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  1103. {
  1104. BOOL fTrust;
  1105. HANDLE hGraphic;
  1106. DWORD i;
  1107. PCCERT_CONTEXT pccert;
  1108. PROPSHEETPAGE * ps;
  1109. WCHAR rgwch[200];
  1110. UINT rguiStrings[7];
  1111. LPAB_DIALOG_PANE_PARAMS lpABDialogPaneParams;
  1112. PROPSHEETPAGE * lpps;
  1113. switch ( msg ) {
  1114. case WM_INITDIALOG:
  1115. // Get access to the parameters
  1116. lpps = (PROPSHEETPAGE *)lParam;
  1117. lpABDialogPaneParams = GetLParamFromPropSheetPage(lpps);
  1118. if (! lpABDialogPaneParams) {
  1119. return(FALSE);
  1120. }
  1121. SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)lpABDialogPaneParams);
  1122. return TRUE;
  1123. case WM_NOTIFY:
  1124. switch (((NMHDR FAR *) lParam)->code) {
  1125. case PSN_SETACTIVE:
  1126. break;
  1127. case PSN_APPLY:
  1128. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE);
  1129. break;
  1130. case PSN_KILLACTIVE:
  1131. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  1132. return TRUE;
  1133. case PSN_RESET:
  1134. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE);
  1135. break;
  1136. }
  1137. case WM_COMMAND:
  1138. if (LOWORD(wParam) == IDC_ADD_TO_ADDRESS_BOOK) {
  1139. HRESULT hr = ResultFromScode(MAPI_E_CALL_FAILED);
  1140. lpABDialogPaneParams = (LPAB_DIALOG_PANE_PARAMS)GetWindowLongPtr(hwndDlg, DWLP_USER);
  1141. if (lpABDialogPaneParams) {
  1142. hr = HrAddCertsToWAB(hwndDlg, lpABDialogPaneParams->lpWABObject,
  1143. lpABDialogPaneParams->lpAdrBook,
  1144. lpABDialogPaneParams->hCryptProv,
  1145. lpABDialogPaneParams->rgCertContext,
  1146. lpABDialogPaneParams->cCertContexts,
  1147. lpABDialogPaneParams->iLeafCert,
  1148. lpABDialogPaneParams->lpDisplayName,
  1149. lpABDialogPaneParams->lpEmailAddress);
  1150. }
  1151. return TRUE;
  1152. }
  1153. else if (LOWORD(wParam) == IDHELP) {
  1154. return TRUE;
  1155. }
  1156. break;
  1157. }
  1158. return FALSE;
  1159. }
  1160. //*******************************************************************
  1161. //
  1162. // FUNCTION: CertFileDisplay
  1163. //
  1164. // PURPOSE: Display the certificate properties of a pkcs7 file
  1165. //
  1166. // PARAMETERS: hwnd = parent window handle
  1167. // lpWABObject -> wab object
  1168. // lpAdrBook -> Adrbook object
  1169. // lpFileName -> Cert filename
  1170. //
  1171. // RETURNS: HRESULT
  1172. //
  1173. //*******************************************************************
  1174. HRESULT CertFileDisplay(HWND hwnd,
  1175. LPWABOBJECT lpWABObject,
  1176. LPADRBOOK lpAdrBook,
  1177. LPTSTR lpFileName) {
  1178. HCRYPTPROV hCryptProvider = 0;
  1179. HRESULT hr;
  1180. CERT_CONTEXT CertContext;
  1181. LPBYTE lpBuf = NULL;
  1182. ULONG cbData = 0, cCert;
  1183. HCRYPTMSG hMsg = NULL;
  1184. PCERT_CONTEXT * rgCertContext = NULL;
  1185. DWORD dwIssuerFlags = 0;
  1186. ULONG i, j;
  1187. PCCERT_CONTEXT pcCertContextTarget = NULL, pcCertContextIssuer;
  1188. PCERT_INFO pCertInfoTarget = NULL;
  1189. HCERTSTORE hCertStoreMsg = NULL;
  1190. BOOL fFound = FALSE, fIssuer;
  1191. PROPSHEETPAGE PSPage;
  1192. TCHAR szTitle[MAX_RESOURCE_STRING + 1];
  1193. TCHAR szABPaneTitle[MAX_RESOURCE_STRING + 1];
  1194. AB_DIALOG_PANE_PARAMS ABDialogPaneParams;
  1195. PCERT_INFO pCertInfo;
  1196. LPTSTR lpDisplayName = NULL, lpEmailAddress = NULL;
  1197. LPTSTR rgPurposes[1] = {(LPTSTR)&cszOID_PKIX_KP_EMAIL_PROTECTION};
  1198. // Get the crypt provider context
  1199. if (! CryptAcquireContext(
  1200. &hCryptProvider,
  1201. NULL,
  1202. NULL,
  1203. PROV_RSA_FULL,
  1204. CRYPT_VERIFYCONTEXT)) {
  1205. hr = GetLastError();
  1206. goto exit;
  1207. }
  1208. // Read the data from the file.
  1209. if (hr = ReadDataFromFile(lpFileName, &lpBuf, &cbData)) {
  1210. goto exit;
  1211. }
  1212. if (! (hMsg = CryptMsgOpenToDecode(
  1213. PKCS_7_ASN_ENCODING,
  1214. 0, // dwFlags
  1215. 0, // dwMsgType
  1216. hCryptProvider,
  1217. NULL, // pRecipientInfo (not supported)
  1218. NULL))) { // pStreamInfo (not supported)
  1219. hr = GetLastError();
  1220. DebugTrace("CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING) -> 0x%08x\n", GetScode(hr));
  1221. goto exit;
  1222. }
  1223. if (! CryptMsgUpdate(hMsg, lpBuf, cbData, TRUE)) {
  1224. hr = GetLastError();
  1225. DebugTrace("CryptMsgUpdate -> 0x%08x\n", GetScode(hr));
  1226. goto exit;
  1227. }
  1228. cbData = sizeof(cCert);
  1229. if (! CryptMsgGetParam(
  1230. hMsg,
  1231. CMSG_CERT_COUNT_PARAM, // dwParamType
  1232. 0, // dwIndex
  1233. (void *)&cCert,
  1234. &cbData)) { // pcbData
  1235. hr = GetLastError();
  1236. DebugTrace("CryptMsgGetParam(CMSG_CERT_COUNT_PARAM) -> 0x%08x\n", GetScode(hr));
  1237. goto exit;
  1238. }
  1239. if (cbData != sizeof(cCert)) {
  1240. hr = ResultFromScode(MAPI_E_CALL_FAILED);
  1241. goto exit;
  1242. }
  1243. // Look for cert that's a "Leaf" node.
  1244. // Unfortunately, there is no easy way to tell, so we'll have
  1245. // to loop through each cert, checking to see if it is an issuer of any other cert
  1246. // in the message. If it is not an issuer of any other cert, it must be the leaf cert.
  1247. //
  1248. if (! (hCertStoreMsg = CertOpenStore(
  1249. CERT_STORE_PROV_MSG,
  1250. X509_ASN_ENCODING,
  1251. hCryptProvider,
  1252. CERT_STORE_NO_CRYPT_RELEASE_FLAG,
  1253. hMsg))) {
  1254. hr = GetLastError();
  1255. DebugTrace("CertOpenStore(msg) -> %x\n", hr);
  1256. goto exit;
  1257. } else {
  1258. if (! (rgCertContext = LocalAlloc(LPTR, cCert * sizeof(PCERT_CONTEXT)))) {
  1259. DebugTrace("LocalAlloc of cert table -> %u\n", GetLastError());
  1260. hr = ResultFromScode(MAPI_E_NOT_ENOUGH_MEMORY);
  1261. goto exit;
  1262. }
  1263. // Enumerate all certs on this message
  1264. i = 0;
  1265. while (pcCertContextTarget = CertEnumCertificatesInStore(hCertStoreMsg,
  1266. pcCertContextTarget)) {
  1267. rgCertContext[i] = (PCERT_CONTEXT)CertDuplicateCertificateContext(
  1268. pcCertContextTarget);
  1269. #ifdef DEBUG
  1270. DebugTraceCertContextName(rgCertContext[i], "Found Cert:");
  1271. #endif
  1272. i++;
  1273. };
  1274. // Now we've got a table full of certs
  1275. for (i = 0; i < cCert; i++) {
  1276. pCertInfoTarget = rgCertContext[i]->pCertInfo;
  1277. fIssuer = FALSE;
  1278. for (j = 0; j < cCert; j++) {
  1279. if (i != j) {
  1280. dwIssuerFlags = 0;
  1281. if (pcCertContextIssuer = CertGetIssuerCertificateFromStore(hCertStoreMsg,
  1282. rgCertContext[j],
  1283. NULL,
  1284. &dwIssuerFlags)) {
  1285. // Found an issuer
  1286. // Is it the same as the target?
  1287. fIssuer = CertCompareCertificate(X509_ASN_ENCODING,
  1288. pCertInfoTarget, // target
  1289. pcCertContextIssuer->pCertInfo); // test issuer
  1290. CertFreeCertificateContext(pcCertContextIssuer);
  1291. if (fIssuer) {
  1292. // This test cert is issued by the target, so
  1293. // we know that Target is NOT a leaf cert
  1294. break;
  1295. } // else, loop back to the enumerate where the test cert context will be freed.
  1296. }
  1297. }
  1298. }
  1299. if (! fIssuer) {
  1300. DebugTrace("Found a Cert which is not an issuer.\n");
  1301. #ifdef DEBUG
  1302. DebugTraceCertContextName(rgCertContext[i], "Non-issuer cert:");
  1303. #endif
  1304. // What is the email and display name of the leaf cert?
  1305. pCertInfo = rgCertContext[i]->pCertInfo;
  1306. GetAttributeString(&ABDialogPaneParams.lpDisplayName,
  1307. pCertInfo->Subject.pbData,
  1308. pCertInfo->Subject.cbData,
  1309. szOID_COMMON_NAME);
  1310. GetAttributeString(&ABDialogPaneParams.lpEmailAddress,
  1311. pCertInfo->Subject.pbData,
  1312. pCertInfo->Subject.cbData,
  1313. szOID_RSA_emailAddr);
  1314. ABDialogPaneParams.lpWABObject = lpWABObject;
  1315. ABDialogPaneParams.lpAdrBook = lpAdrBook;
  1316. ABDialogPaneParams.hCryptProv = hCryptProvider;
  1317. ABDialogPaneParams.rgCertContext = rgCertContext;
  1318. ABDialogPaneParams.cCertContexts = cCert;
  1319. ABDialogPaneParams.iLeafCert = i;
  1320. ABDialogPaneParams.dwSentry = LPARAM_SENTRY;
  1321. memset(&PSPage, 0, sizeof(PROPSHEETPAGE));
  1322. PSPage.dwSize = sizeof(PSPage);
  1323. PSPage.dwFlags = 0; // PSP_HASHELP;
  1324. PSPage.hInstance = hInst;
  1325. PSPage.pszTemplate = MAKEINTRESOURCE(IDD_CERTPROP_ADDRESS_BOOK);
  1326. PSPage.hIcon = 0;
  1327. LoadString(hInst, idsAddToABPaneTitle, szABPaneTitle, sizeof(szABPaneTitle));
  1328. PSPage.pszTitle = szABPaneTitle;
  1329. PSPage.pfnDlgProc = ViewPageAddressBook;
  1330. PSPage.lParam = (LPARAM)&ABDialogPaneParams; // (DWORD) &viewhelp;
  1331. PSPage.pfnCallback = 0;
  1332. PSPage.pcRefParent = NULL;
  1333. {
  1334. CERT_VIEWPROPERTIES_STRUCT_A cvps = {0};
  1335. // Fill in the cert view struct
  1336. cvps.dwSize = sizeof(CERT_VIEWPROPERTIES_STRUCT);
  1337. cvps.hwndParent = hwnd;
  1338. cvps.hInstance = hInst;
  1339. cvps.dwFlags = CM_ADD_CERT_STORES; // Look in rghstoreCAs
  1340. LoadString(hInst, idsCertificateViewTitle, szTitle, sizeof(szTitle));
  1341. cvps.szTitle = szTitle;
  1342. cvps.pCertContext = rgCertContext[i];
  1343. cvps.nStartPage = iAddToWAB; // show add to WAB page first
  1344. cvps.arrayPurposes = rgPurposes;
  1345. cvps.cArrayPurposes = 1;
  1346. cvps.cStores = 1; // Count of other stores to search
  1347. cvps.rghstoreCAs = &hCertStoreMsg; // Array of other stores to search
  1348. cvps.hprov = hCryptProvider; // Provider to use for verification
  1349. cvps.cArrayPropSheetPages = 1;
  1350. cvps.arrayPropSheetPages = &PSPage;
  1351. if (! CertViewPropertiesA(&cvps)) {
  1352. hr = GetLastError();
  1353. }
  1354. }
  1355. fFound = TRUE;
  1356. break; // done with loop
  1357. }
  1358. }
  1359. // Free the table of certs
  1360. for (i = 0; i < cCert; i++) {
  1361. if (rgCertContext[i]) {
  1362. CertFreeCertificateContext(rgCertContext[i]);
  1363. }
  1364. }
  1365. LocalFree((LPVOID)rgCertContext);
  1366. if (! fFound) {
  1367. // Didn't find a cert that isn't an issuer. Fail.
  1368. hr = ResultFromScode(MAPI_E_NOT_FOUND);
  1369. goto exit;
  1370. }
  1371. }
  1372. exit:
  1373. if (hCryptProvider) {
  1374. CryptReleaseContext(hCryptProvider, 0);
  1375. }
  1376. return(hr);
  1377. }
  1378. /* DebugTrapFn -------------------------------------------------------------- */
  1379. #ifdef DEBUG
  1380. #if defined(WIN32) && !defined(_MAC)
  1381. typedef struct {
  1382. char * sz1;
  1383. char * sz2;
  1384. UINT rgf;
  1385. int iResult;
  1386. } MBContext;
  1387. DWORD WINAPI MessageBoxFnThreadMain(MBContext *pmbc)
  1388. {
  1389. pmbc->iResult = MessageBoxA(NULL, pmbc->sz1, pmbc->sz2,
  1390. pmbc->rgf | MB_SETFOREGROUND);
  1391. return(0);
  1392. }
  1393. int MessageBoxFn(char *sz1, char *sz2, UINT rgf)
  1394. {
  1395. HANDLE hThread;
  1396. DWORD dwThreadId;
  1397. MBContext mbc;
  1398. mbc.sz1 = sz1;
  1399. mbc.sz2 = sz2;
  1400. mbc.rgf = rgf;
  1401. mbc.iResult = IDRETRY;
  1402. MessageBoxFnThreadMain(&mbc);
  1403. return(mbc.iResult);
  1404. }
  1405. #else
  1406. #define MessageBoxFn(sz1, sz2, rgf) MessageBoxA(NULL, sz1, sz2, rgf)
  1407. #endif
  1408. void FAR CDECL DebugTrapFn(int fFatal, char *pszFile, int iLine, char *pszFormat, ...) {
  1409. char sz[512];
  1410. va_list vl;
  1411. #if defined(WIN16) || defined(WIN32)
  1412. int id;
  1413. #endif
  1414. lstrcpyA(sz, "++++ WAB Debug Trap (");
  1415. // _strdate(sz + lstrlenA(sz));
  1416. // lstrcatA(sz, " ");
  1417. // _strtime(sz + lstrlenA(sz));
  1418. lstrcatA(sz, ")\n");
  1419. DebugTrace(sz);
  1420. va_start(vl, pszFormat);
  1421. wvsprintfA(sz, pszFormat, vl);
  1422. va_end(vl);
  1423. wsprintfA(sz + lstrlenA(sz), "\n[File %s, Line %d]\n\n", pszFile, iLine);
  1424. DebugTrace(sz);
  1425. #if defined(DOS)
  1426. _asm { int 3 }
  1427. #endif
  1428. #if defined(WIN16) || defined(WIN32)
  1429. /* Hold down control key to prevent MessageBox */
  1430. if ( GetAsyncKeyState(VK_CONTROL) >= 0 )
  1431. {
  1432. UINT uiFlags = MB_ABORTRETRYIGNORE;
  1433. if (fFatal)
  1434. uiFlags |= MB_DEFBUTTON1;
  1435. else
  1436. uiFlags |= MB_DEFBUTTON3;
  1437. #ifdef WIN16
  1438. uiFlags |= MB_ICONEXCLAMATION | MB_SYSTEMMODAL;
  1439. #else
  1440. uiFlags |= MB_ICONSTOP | MB_TASKMODAL;
  1441. #endif
  1442. #ifndef MAC
  1443. id = MessageBoxFn(sz, "WAB Debug Trap", uiFlags);
  1444. if (id == IDABORT)
  1445. *((LPBYTE)NULL) = 0;
  1446. else if (id == IDRETRY)
  1447. DebugBreak();
  1448. #endif // MAC
  1449. }
  1450. #endif
  1451. }
  1452. #endif
  1453. /*
  1454. * DebugTrace -- printf to the debugger console or debug output file
  1455. * Takes printf style arguments.
  1456. * Expects newline characters at the end of the string.
  1457. */
  1458. #ifdef DEBUG
  1459. VOID FAR CDECL DebugTrace(LPSTR lpszFmt, ...) {
  1460. va_list marker;
  1461. TCHAR String[1100];
  1462. va_start(marker, lpszFmt);
  1463. wvsprintf(String, lpszFmt, marker);
  1464. OutputDebugString(String);
  1465. }
  1466. #endif
  1467. #ifdef DEBUG
  1468. //*******************************************************************
  1469. void DebugTraceCertContextName(PCCERT_CONTEXT pcCertContext, LPTSTR lpDescription) {
  1470. LPTSTR lpName = NULL;
  1471. PCERT_INFO pCertInfo = pcCertContext->pCertInfo;
  1472. #ifdef OLD_STUFF
  1473. GetAttributeString(
  1474. &lpName,
  1475. pCertInfo->Subject.pbData,
  1476. pCertInfo->Subject.cbData,
  1477. szOID_COMMON_NAME);
  1478. if (! lpName) {
  1479. GetAttributeString(
  1480. &lpName,
  1481. pCertInfo->Subject.pbData,
  1482. pCertInfo->Subject.cbData,
  1483. szOID_ORGANIZATION_NAME);
  1484. }
  1485. DebugTrace("%s %s\n", lpDescription, lpName ? lpName : "<unknown>");
  1486. if (lpName) {
  1487. LocalFree(lpName);
  1488. }
  1489. #endif // OLD_STUFF
  1490. }
  1491. #endif