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.

2797 lines
84 KiB

  1. #include "pch.hxx"
  2. #include "demand.h"
  3. #include <string.h>
  4. #include <shellapi.h>
  5. #include <commctrl.h>
  6. #include <limits.h>
  7. //WIn64 macros
  8. #ifdef _WIN64
  9. #if defined (_AMD64_) || defined (_IA64_)
  10. #define ALIGNTYPE LARGE_INTEGER
  11. #else
  12. #define ALIGNTYPE DWORD
  13. #endif
  14. #define ALIGN ((ULONG) (sizeof(ALIGNTYPE) - 1))
  15. #define LcbAlignLcb(lcb) (((lcb) + ALIGN) & ~ALIGN)
  16. #define PbAlignPb(pb) ((LPBYTE) ((((DWORD) (pb)) + ALIGN) & ~ALIGN))
  17. #define MYALIGN ((POINTER_64_INT) (sizeof(ALIGNTYPE) - 1))
  18. #define MyPbAlignPb(pb) ((LPBYTE) ((((POINTER_64_INT) (pb)) + MYALIGN) & ~MYALIGN))
  19. #else //!WIN64
  20. #define LcbAlignLcb(lcb) (lcb)
  21. #define PbAlignPb(pb) (pb)
  22. #define MyPbAlignPb(pb) (pb)
  23. #endif
  24. #define ARRAYSIZE(_rg) (sizeof(_rg)/sizeof(_rg[0]))
  25. #define szOID_MICROSOFT_Encryption_Key_Preference "1.3.6.1.4.1.311.16.4"
  26. typedef struct {
  27. DWORD unused;
  28. CERT_NAME_BLOB Issuer;
  29. CRYPT_INTEGER_BLOB SerialNumber;
  30. } CRYPT_RECIPIENT_ID, * PCRYPT_RECIPIENT_ID;
  31. #if 0
  32. // From mssip.h
  33. // SPC_LINK_STRUCT
  34. // pvStructInfo points to SPC_LINK.
  35. //
  36. typedef BYTE SPC_UUID[16];
  37. typedef struct _SPC_SERIALIZED_OBJECT
  38. {
  39. SPC_UUID ClassId;
  40. CRYPT_DATA_BLOB SerializedData;
  41. } SPC_SERIALIZED_OBJECT, *PSPC_SERIALIZED_OBJECT;
  42. typedef struct _SPC_LINK
  43. {
  44. DWORD dwLinkChoice;
  45. union
  46. {
  47. LPWSTR pwszUrl;
  48. SPC_SERIALIZED_OBJECT Moniker;
  49. LPWSTR pwszFile;
  50. };
  51. } SPC_LINK, *PSPC_LINK;
  52. #define SPC_URL_LINK_CHOICE 1
  53. #define SPC_MONIKER_LINK_CHOICE 2
  54. #define SPC_FILE_LINK_CHOICE 3
  55. #endif
  56. #ifndef WIN16
  57. #include "wintrust.h"
  58. #endif // !WIN16
  59. #ifdef MAC
  60. #include <stdio.h>
  61. EXTERN_C INT CALLBACK CreateDate(LPSYSTEMTIME lpst, CHAR * szOutStr, BOOL fNoYear);
  62. EXTERN_C INT CreateTime(LPSYSTEMTIME lpst, CHAR *szOutStr, BOOL fNoSeconds);
  63. HRESULT TdxFormatMessageVa (IN LPCSTR rgchFormat, OUT CHAR * rgchBuffer, OUT ULONG * pucReqSize, va_list marker);
  64. #endif // MAC
  65. extern HINSTANCE HinstDll;
  66. /////////////////////////////////////////////////////////
  67. #ifndef MAC
  68. BOOL IsWin95()
  69. {
  70. BOOL f;
  71. OSVERSIONINFOA ver;
  72. ver.dwOSVersionInfoSize = sizeof(ver);
  73. f = GetVersionExA(&ver);
  74. return !f || (ver.dwPlatformId == 1);
  75. }
  76. #endif // !MAC
  77. #ifndef WIN16
  78. LRESULT MySendDlgItemMessageW(HWND hwnd, int id, UINT msg, WPARAM w, LPARAM l)
  79. {
  80. char rgch[4096];
  81. LPTV_INSERTSTRUCTW ptvinsW;
  82. TV_INSERTSTRUCTA tvins;
  83. if (msg == LB_ADDSTRING) {
  84. WideCharToMultiByte(CP_ACP, 0, (LPWSTR) l, -1, rgch, sizeof(rgch),
  85. NULL, NULL);
  86. l = (LPARAM) rgch;
  87. }
  88. else if (msg == TVM_INSERTITEMW) {
  89. msg = TVM_INSERTITEMA;
  90. ptvinsW = (LPTV_INSERTSTRUCTW) l;
  91. memcpy(&tvins, ptvinsW, sizeof(tvins));
  92. WideCharToMultiByte(CP_ACP, 0, ptvinsW->item.pszText, -1, rgch,
  93. sizeof(rgch), NULL, NULL);
  94. tvins.item.pszText = rgch;
  95. l = (LPARAM) &tvins;
  96. }
  97. return SendDlgItemMessageA(hwnd, id, msg, w, l);
  98. }
  99. BOOL MySetDlgItemTextW(HWND hwnd, int id, LPCWSTR pwsz)
  100. {
  101. char rgch[4096];
  102. WideCharToMultiByte(CP_ACP, 0, pwsz, -1, rgch, sizeof(rgch), NULL, NULL);
  103. return SetDlgItemTextA(hwnd, id, rgch);
  104. }
  105. UINT MyGetDlgItemTextW(HWND hwnd, int id, LPWSTR pwsz, int nMax)
  106. {
  107. UINT cch;
  108. char rgch[4096];
  109. cch = GetDlgItemTextA(hwnd, id, rgch, ARRAYSIZE(rgch)-1);
  110. rgch[cch+1] = 0;
  111. cch = MultiByteToWideChar(CP_ACP, 0, rgch, cch+1, pwsz, nMax);
  112. return cch;
  113. }
  114. DWORD MyFormatMessageW(DWORD dwFlags, LPCVOID pbSource, DWORD dwMessageId,
  115. DWORD dwLangId, LPWSTR lpBuffer, DWORD nSize,
  116. va_list * args)
  117. {
  118. DWORD cch;
  119. int i;
  120. LPSTR pchDest;
  121. DWORD_PTR * pdw;
  122. LPWSTR pwchOut;
  123. char rgchSource[128];
  124. DWORD_PTR rgdwArgs[10];
  125. int cArgs = 10;
  126. #ifdef MAC
  127. HRESULT hr;
  128. #endif // MAC
  129. if (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)) {
  130. #ifdef DEBUG
  131. DebugBreak();
  132. #endif // DEBUG
  133. return 0;
  134. }
  135. //
  136. // We need to figure out how many arguments are in the array.
  137. // All Arrays are to be terminated by -1 in order for this to work.
  138. //
  139. pdw = (DWORD_PTR *) args;
  140. for (i=0; i<cArgs; i++) {
  141. if (pdw[i] == 0xffffffff) {
  142. cArgs = i-1;
  143. break;
  144. }
  145. if (pdw[i] <= 0xffff) {
  146. rgdwArgs[i] = pdw[i];
  147. }
  148. else {
  149. cch = wcslen((LPWSTR) pdw[i]);
  150. rgdwArgs[i] = (DWORD_PTR) malloc((cch+1));
  151. WideCharToMultiByte(CP_ACP, 0, (LPWSTR) pdw[i], -1,
  152. (LPSTR) rgdwArgs[i], cch+1, NULL, NULL);
  153. }
  154. }
  155. if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
  156. WideCharToMultiByte(CP_ACP, 0, (LPWSTR) pbSource, -1,
  157. rgchSource, sizeof(rgchSource), NULL, NULL);
  158. pbSource = rgchSource;
  159. }
  160. #ifdef MAC
  161. dwLangId; // Unused
  162. dwMessageId; // Unused
  163. hr = TdxFormatMessageVa ((LPCSTR) pbSource, NULL, &cch, (va_list) rgdwArgs);
  164. if (FAILED(hr))
  165. {
  166. return 0;
  167. }
  168. pchDest = (LPSTR) LocalAlloc(LMEM_FIXED, cch + 1);
  169. if (NULL == pchDest)
  170. {
  171. return 0;
  172. }
  173. hr = TdxFormatMessageVa ((LPCSTR) pbSource, pchDest, &cch, (va_list) rgdwArgs);
  174. if (FAILED(hr))
  175. {
  176. LocalFree(pchDest);
  177. return 0;
  178. }
  179. #else // !MAC
  180. cch = FormatMessageA(dwFlags | FORMAT_MESSAGE_ALLOCATE_BUFFER, pbSource,
  181. dwMessageId, dwLangId, (LPSTR) &pchDest, 0,
  182. (va_list *) rgdwArgs);
  183. #endif // MAC
  184. if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
  185. cch = MultiByteToWideChar(CP_ACP, 0, pchDest, -1, NULL, 0);
  186. pwchOut = (LPWSTR) LocalAlloc(LMEM_FIXED, (cch+1)*sizeof(WCHAR));
  187. cch = MultiByteToWideChar(CP_ACP, 0, pchDest, -1, pwchOut, cch);
  188. *((LPWSTR *) lpBuffer) = pwchOut;
  189. }
  190. else {
  191. cch = MultiByteToWideChar(CP_ACP, 0, pchDest, -1, lpBuffer, nSize);
  192. }
  193. for (i=0; i<cArgs; i++) {
  194. if (rgdwArgs[i] > 0xffff) {
  195. free((LPVOID) rgdwArgs[i]);
  196. }
  197. }
  198. LocalFree(pchDest);
  199. return cch;
  200. }
  201. int MyLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int cbBuffer)
  202. {
  203. DWORD cch;
  204. char rgch[256];
  205. #ifndef MAC
  206. if (!FIsWin95) {
  207. return LoadStringW(hInstance, uID, lpBuffer, cbBuffer);
  208. }
  209. #endif // !MAC
  210. cch = LoadStringA(hInstance, uID, rgch, sizeof(rgch));
  211. cch = MultiByteToWideChar(CP_ACP, 0, rgch, -1, lpBuffer, cbBuffer);
  212. return cch;
  213. }
  214. #endif // !WIN16
  215. BOOL MyCryptAcquireContextW(HCRYPTPROV * phProv, LPCWSTR pszContainer,
  216. LPCWSTR pszProvider, DWORD dwProvType, DWORD dwFlags)
  217. {
  218. char rgch1[256];
  219. char rgch2[256];
  220. if (pszContainer != NULL) {
  221. WideCharToMultiByte(CP_ACP, 0, pszContainer, -1, rgch1, ARRAYSIZE(rgch1),
  222. NULL, NULL);
  223. pszContainer = (LPWSTR) rgch1;
  224. }
  225. if (pszProvider != NULL) {
  226. WideCharToMultiByte(CP_ACP, 0, pszProvider, -1, rgch2, ARRAYSIZE(rgch2),
  227. NULL, NULL);
  228. pszProvider = (LPWSTR) rgch2;
  229. }
  230. return CryptAcquireContextA(phProv, (LPCSTR) pszContainer, (LPCSTR) pszProvider,
  231. dwProvType, dwFlags);
  232. }
  233. BOOL MyWinHelpW(HWND hWndMain, LPCWSTR szHelp, UINT uCommand, ULONG_PTR dwData)
  234. {
  235. char rgch[4096];
  236. WideCharToMultiByte(CP_ACP, 0, szHelp, -1, rgch, ARRAYSIZE(rgch), NULL, NULL);
  237. return WinHelpA(hWndMain, rgch, uCommand, dwData);
  238. }
  239. ////////////////////////////////////////////////////////////////
  240. DWORD TruncateToWindowA(HWND hwndDlg, int id, LPSTR psz)
  241. {
  242. int cch = strlen(psz);
  243. int cchMax;
  244. int cchMid;
  245. int cchMin;
  246. HDC hdc;
  247. HFONT hfontOld;
  248. HFONT hfontNew;
  249. HWND hwnd;
  250. SIZE siz;
  251. SIZE sizDots;
  252. RECT rt;
  253. TEXTMETRICA tmA;
  254. hwnd = GetDlgItem(hwndDlg, id);
  255. hdc = GetDC(hwnd);
  256. hfontNew = (HFONT) SendMessage(hwnd, WM_GETFONT, NULL, NULL);
  257. if (NULL == hfontNew) {
  258. goto Error;
  259. }
  260. hfontOld = (HFONT) SelectObject(hdc, hfontNew);
  261. GetTextMetricsA(hdc, &tmA);
  262. GetWindowRect(hwnd, &rt);
  263. rt.right -= rt.left;
  264. GetTextExtentPointA(hdc, psz, cch, &siz);
  265. if (rt.right < siz.cx) {
  266. GetTextExtentPointA(hdc, "...", 3, &sizDots);
  267. rt.right -= sizDots.cx;
  268. for (cchMin=0, cchMax=cch, cchMid = (cchMin + cchMax + 1)/2;
  269. cchMin < cchMax;
  270. cchMid = (cchMin + cchMax + 1)/2) {
  271. GetTextExtentPointA(hdc, psz, cchMid, &siz);
  272. if (rt.right == siz.cx) {
  273. break;
  274. }
  275. else if (rt.right > siz.cx) {
  276. cchMin = cchMid;
  277. }
  278. else {
  279. cchMax = cchMid-1;
  280. }
  281. }
  282. // Make certain that we don't overflow the buffer.
  283. if (cchMin + 3 > cch) { // 3 = number of characters in "...".
  284. cchMin = cch - 3;
  285. }
  286. StrCpyNA(&psz[cchMin], "...", cch+1-cchMin);
  287. }
  288. SelectObject(hdc, hfontOld);
  289. Error:
  290. ReleaseDC(hwnd, hdc);
  291. return TRUE;
  292. }
  293. DWORD TruncateToWindowW(HWND hwndDlg, int id, WCHAR * pwsz)
  294. {
  295. if (FIsWin95) {
  296. DWORD cch;
  297. char rgch[4096];
  298. cch = wcslen(pwsz)+1;
  299. WideCharToMultiByte(CP_ACP, 0, pwsz, -1, rgch, sizeof(rgch), NULL, NULL);
  300. TruncateToWindowA(hwndDlg, id, rgch);
  301. MultiByteToWideChar(CP_ACP, 0, rgch, -1, pwsz, cch);
  302. return TRUE;
  303. }
  304. #ifndef WIN16
  305. #ifndef MAC
  306. int cch = wcslen(pwsz);
  307. int cchMax;
  308. int cchMid;
  309. int cchMin;
  310. HDC hdc;
  311. HFONT hfontOld;
  312. HFONT hfontNew;
  313. HWND hwnd;
  314. SIZE siz;
  315. SIZE sizDots;
  316. RECT rt;
  317. TEXTMETRICW tmW;
  318. hwnd = GetDlgItem(hwndDlg, id);
  319. hdc = GetDC(hwnd);
  320. hfontNew = (HFONT) SendMessage(hwnd, WM_GETFONT, NULL, NULL);
  321. hfontOld = (HFONT) SelectObject(hdc, hfontNew);
  322. GetTextMetricsW(hdc, &tmW);
  323. GetWindowRect(hwnd, &rt);
  324. rt.right -= rt.left;
  325. GetTextExtentPointW(hdc, pwsz, cch, &siz);
  326. if (rt.right < siz.cx) {
  327. GetTextExtentPointW(hdc, L"...", 3, &sizDots);
  328. rt.right -= sizDots.cx;
  329. for (cchMin=0, cchMax=cch, cchMid = (cchMin + cchMax + 1)/2;
  330. cchMin < cchMax;
  331. cchMid = (cchMin + cchMax + 1)/2) {
  332. GetTextExtentPointW(hdc, pwsz, cchMid, &siz);
  333. if (rt.right == siz.cx) {
  334. break;
  335. }
  336. else if (rt.right > siz.cx) {
  337. cchMin = cchMid;
  338. }
  339. else {
  340. cchMax = cchMid-1;
  341. }
  342. }
  343. // Make certain that we don't overflow the buffer.
  344. if (cchMin + 3 > cch) { // 3 = number of characters in L"...".
  345. cchMin = cch - 3;
  346. }
  347. StrCpyNW(&pwsz[cchMin], L"...", cch+1-cchMin);
  348. }
  349. SelectObject(hdc, hfontOld);
  350. ReleaseDC(hwnd, hdc);
  351. #endif // !MAC
  352. #endif // !WIN16
  353. return TRUE;
  354. }
  355. ////////////////////////////////////////////////////////////////////
  356. #if 0
  357. // From authcode.h
  358. //+-------------------------------------------------------------------------
  359. // SPC_SP_AGENCY_INFO_STRUCT
  360. // pvStructInfo points to SPC_SP_AGENCY_INFO.
  361. //
  362. typedef struct _SPC_IMAGE {
  363. PSPC_LINK pImageLink;
  364. CRYPT_DATA_BLOB Bitmap;
  365. CRYPT_DATA_BLOB Metafile;
  366. CRYPT_DATA_BLOB EnhancedMetafile;
  367. CRYPT_DATA_BLOB GifFile;
  368. } SPC_IMAGE, *PSPC_IMAGE;
  369. typedef struct _SPC_SP_AGENCY_INFO {
  370. PSPC_LINK pPolicyInformation;
  371. LPWSTR pwszPolicyDisplayText;
  372. PSPC_IMAGE pLogoImage;
  373. PSPC_LINK pLogoLink;
  374. } SPC_SP_AGENCY_INFO, *PSPC_SP_AGENCY_INFO;
  375. #endif // 0
  376. ///////////////////////////////////////////////////////
  377. BOOL LoadStringInWindow(HWND hwnd, UINT idCtrl, HMODULE hmod, UINT idString)
  378. {
  379. WCHAR rgwch[1024];
  380. if (FIsWin95) {
  381. LoadStringA(hmod, idString, (LPSTR) rgwch, sizeof(rgwch));
  382. SetDlgItemTextA(hwnd, idCtrl, (LPSTR)rgwch);
  383. }
  384. #ifndef WIN16
  385. #ifndef MAC
  386. else {
  387. LoadStringW(hmod, idString, rgwch, sizeof(rgwch)/sizeof(rgwch[0]));
  388. SetDlgItemText(hwnd, idCtrl, rgwch);
  389. }
  390. #endif // !MAC
  391. #endif // !WIN16
  392. return TRUE;
  393. }
  394. BOOL LoadStringsInWindow(HWND hwnd, UINT idCtrl, HMODULE hmod, UINT *pidStrings)
  395. {
  396. BOOL fRet = FALSE;
  397. if (FIsWin95) {
  398. UINT cchOut;
  399. UINT cbOut;
  400. CHAR * pszOut;
  401. cbOut = 1024 * sizeof(CHAR);
  402. pszOut = (CHAR *) malloc(cbOut);
  403. if (NULL == pszOut) {
  404. goto ret;
  405. }
  406. for (*pszOut = '\0', cchOut = 1; *pidStrings != UINT_MAX; pidStrings++) {
  407. UINT cchBuff;
  408. CHAR rgchBuff[1024];
  409. cchBuff = LoadStringA(hmod, *pidStrings, rgchBuff, sizeof(rgchBuff));
  410. if (0 == cchBuff) {
  411. goto ErrorA;
  412. }
  413. cchOut += cchBuff;
  414. if (cchOut > (cbOut / sizeof(CHAR))) {
  415. CHAR * pszNew;
  416. cbOut *= 2;
  417. pszNew = (CHAR *) realloc(pszOut, cbOut);
  418. if (NULL == pszNew) {
  419. goto ErrorA;
  420. }
  421. pszOut = pszNew;
  422. }
  423. StrCatBuffA(pszOut, rgchBuff, cbOut/sizeof(CHAR));
  424. }
  425. SetDlgItemTextA(hwnd, idCtrl, pszOut);
  426. fRet = TRUE;
  427. ErrorA:
  428. free(pszOut);
  429. }
  430. #if !defined( MAC ) && !defined( WIN16 )
  431. else {
  432. UINT cwchOut;
  433. UINT cbOut;
  434. WCHAR * pwszOut;
  435. cbOut = 1024 * sizeof(WCHAR);
  436. pwszOut = (WCHAR *) malloc(cbOut);
  437. if (NULL == pwszOut) {
  438. goto ret;
  439. }
  440. for (*pwszOut = L'\0', cwchOut = 1; *pidStrings != UINT_MAX; pidStrings++) {
  441. UINT cwchBuff;
  442. WCHAR rgwchBuff[1024];
  443. cwchBuff = LoadStringW(hmod, *pidStrings, rgwchBuff, sizeof(rgwchBuff) / sizeof(WCHAR));
  444. if (0 == cwchBuff) {
  445. goto ErrorW;
  446. }
  447. cwchOut += cwchBuff;
  448. if (cwchOut > (cbOut / sizeof(WCHAR))) {
  449. WCHAR * pwszNew;
  450. cbOut *= 2;
  451. pwszNew = (WCHAR *) realloc(pwszOut, cbOut);
  452. if (NULL == pwszNew) {
  453. goto ErrorW;
  454. }
  455. pwszOut = pwszNew;
  456. }
  457. StrCatBuffW(pwszOut, rgwchBuff,cbOut/sizeof(WCHAR));
  458. }
  459. SetDlgItemTextW(hwnd, idCtrl, pwszOut);
  460. fRet = TRUE;
  461. ErrorW:
  462. free(pwszOut);
  463. }
  464. #endif // !MAC && !WIN16
  465. ret:
  466. return fRet;
  467. }
  468. ///////////////////////////////////////////////////////
  469. const WCHAR RgwchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  470. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  471. const CHAR RgchHex[] = {'0', '1', '2', '3', '4', '5', '6', '7',
  472. '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  473. #if 0
  474. LPWSTR FindURL(PCCERT_CONTEXT pccert)
  475. {
  476. DWORD cbInfo;
  477. PCERT_EXTENSION pExt;
  478. PSPC_SP_AGENCY_INFO pInfo;
  479. LPWSTR pwsz;
  480. pExt = CertFindExtension("1.3.6.1.4.311.2.1.10", pccert->pCertInfo->cExtension, pccert->pCertInfo->rgExtension);
  481. if (pExt == NULL) {
  482. return NULL;
  483. }
  484. CryptDecodeObject(X509_ASN_ENCODING, (LPCSTR) 2000, pExt->Value.pbData, pExt->Value.cbData, 0, NULL, &cbInfo);
  485. if (cbInfo == 0) {
  486. return NULL;
  487. }
  488. pInfo = (PSPC_SP_AGENCY_INFO) malloc(cbInfo);
  489. if (!CryptDecodeObject(X509_ASN_ENCODING, (LPCSTR) 2000, pExt->Value.pbData, pExt->Value.cbData, 0, pInfo, &cbInfo)) {
  490. free (pInfo);
  491. return NULL;
  492. }
  493. if (pInfo->pPolicyInformation->dwLinkChoice != SPC_URL_LINK_CHOICE) {
  494. free (pInfo);
  495. return NULL;
  496. }
  497. #ifndef WIN16
  498. pwsz = _wcsdup(pInfo->pPolicyInformation->pwszUrl);
  499. #else
  500. pwsz = _strdup(pInfo->pPolicyInformation->pwszUrl);
  501. #endif // !WIN16
  502. free (pInfo);
  503. return pwsz;
  504. }
  505. #endif // 0
  506. BOOL FormatAlgorithm(HWND hwnd, UINT id, PCCERT_CONTEXT pccert)
  507. {
  508. int cch;
  509. LPWSTR pszMsg;
  510. LPSTR psz = pccert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId;
  511. LPWSTR pwsz;
  512. DWORD_PTR rgdw[3];
  513. #ifdef MAC
  514. CHAR rgch[17];
  515. #endif // MAC
  516. WCHAR rgwch[17];
  517. rgdw[2] = (DWORD) -1; // Sentinal Value
  518. rgdw[1] = pccert->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData * 8;
  519. if (strcmp(psz, szOID_RSA_RSA) == 0) {
  520. rgdw[0] = (DWORD_PTR) L"RSA";
  521. rgdw[1] &= 0xffffff80; // M00BUG
  522. #ifdef MAC
  523. wnsprintf(rgch, ARRAYSIZE(rgch), "%d", rgdw[1]);
  524. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, rgch, -1, rgwch, sizeof(rgwch) / sizeof(rgwch[0]));
  525. #else // !MAC
  526. #ifndef WIN16
  527. _ltow((LONG) rgdw[1], rgwch, 10);
  528. #else
  529. _ltoa(rgdw[1], rgwch, 10);
  530. #endif // !WIN16
  531. #endif // MAC
  532. rgdw[1] = (DWORD_PTR) rgwch;
  533. }
  534. else {
  535. cch = strlen(psz)+1;
  536. pwsz = (LPWSTR) malloc((cch+1)*sizeof(WCHAR));
  537. if (pwsz == NULL) {
  538. return FALSE;
  539. }
  540. MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, psz, cch, pwsz, cch+1);
  541. SetDlgItemText(hwnd, id, pwsz);
  542. free(pwsz);
  543. return TRUE;
  544. }
  545. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY |
  546. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  547. L"%1 (%2 bits)", 0, 0, (LPWSTR) &pszMsg, 0, (va_list *) rgdw);
  548. SetDlgItemText(hwnd, id, pszMsg);
  549. #ifndef WIN16
  550. LocalFree((LPVOID) pszMsg);
  551. #else
  552. LocalFree((HLOCAL) pszMsg);
  553. #endif // !WIN16
  554. return TRUE;
  555. }
  556. BOOL FormatBinary(HWND hwnd, UINT id, LPBYTE pb, DWORD cb)
  557. {
  558. DWORD i;
  559. LPWSTR pwch;
  560. pwch = (LPWSTR) malloc( (cb*2+1)*sizeof(WCHAR));
  561. if (pwch == NULL) {
  562. return FALSE;
  563. }
  564. for (i=0; i < cb; i++, pb++) {
  565. pwch[i*2] = RgwchHex[(*pb & 0xf0) >> 4];
  566. pwch[i*2+1] = RgwchHex[*pb & 0x0f];
  567. }
  568. pwch[i*2] = 0;
  569. SetDlgItemText(hwnd, id, pwch);
  570. free(pwch);
  571. return TRUE;
  572. }
  573. //// FormatCPS
  574. //
  575. // Description:
  576. // Look for a Certificate Policy Statment in the certificate.
  577. // We recognize as CPSs the following items:
  578. // 1. What ever PKIX comes up with
  579. // 2. The magic Verisign one
  580. //
  581. BOOL FormatCPS(HWND hwnd, UINT id, PCCERT_CONTEXT pccert)
  582. {
  583. DWORD cb;
  584. BOOL f;
  585. PCERT_EXTENSION pExt;
  586. LPWSTR pwsz;
  587. pExt = CertFindExtension("2.5.29.32", pccert->pCertInfo->cExtension,
  588. pccert->pCertInfo->rgExtension);
  589. if (pExt != NULL) {
  590. cb = 0;
  591. f = CryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, pExt->pszObjId,
  592. pExt->Value.pbData, pExt->Value.cbData, 0, &cb);
  593. if (f && (cb > 0)) {
  594. pwsz = (LPWSTR) malloc(cb * sizeof(WCHAR));
  595. CryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, pExt->pszObjId,
  596. pExt->Value.pbData, pExt->Value.cbData,
  597. pwsz, &cb);
  598. SetDlgItemText(hwnd, id, pwsz);
  599. free(pwsz);
  600. }
  601. return TRUE;
  602. }
  603. return FALSE;
  604. }
  605. BOOL FormatDate(HWND hwnd, UINT id, FILETIME ft)
  606. {
  607. int cch;
  608. int cch2;
  609. LPWSTR pwsz;
  610. SYSTEMTIME st;
  611. #ifdef MAC
  612. CHAR rgch[256];
  613. #else // !MAC
  614. LPSTR psz;
  615. #endif // MAC
  616. if (!FileTimeToSystemTime(&ft, &st)) {
  617. return FALSE;
  618. }
  619. #ifdef MAC
  620. cch = CreateDate(&st, rgch, FALSE);
  621. pwsz = (LPWSTR) malloc((cch + 2)*sizeof(WCHAR));
  622. if (pwsz == NULL) {
  623. return FALSE;
  624. }
  625. cch2 = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, rgch, -1, pwsz, cch + 2);
  626. if (0 == cch2)
  627. {
  628. free(pwsz);
  629. return FALSE;
  630. }
  631. pwsz[cch2++] = L' ';
  632. cch = CreateTime(&st, rgch, FALSE);
  633. pwsz = (LPWSTR) realloc(pwsz, (cch + cch2 + 1)*sizeof(WCHAR));
  634. if (pwsz == NULL) {
  635. return FALSE;
  636. }
  637. cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, rgch, -1, pwsz + cch2, cch + 1);
  638. if (0 == cch)
  639. {
  640. free(pwsz);
  641. return FALSE;
  642. }
  643. SetDlgItemText(hwnd, id, pwsz);
  644. #else // !MAC
  645. if (FIsWin95) {
  646. cch = (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) +
  647. GetDateFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 5);
  648. psz = (LPSTR) malloc(cch+5);
  649. if (psz == NULL) {
  650. return FALSE;
  651. }
  652. cch2 = GetDateFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL, psz, cch);
  653. cch2 -= 1;
  654. psz[cch2++] = ' ';
  655. GetTimeFormatA(LOCALE_USER_DEFAULT, 0, &st, NULL,
  656. &psz[cch2], cch-cch2);
  657. SetDlgItemTextA(hwnd, id, psz);
  658. free(psz);
  659. return TRUE;
  660. }
  661. cch = (GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) +
  662. GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, NULL, 0) + 5);
  663. pwsz = (LPWSTR) malloc((cch+5)*sizeof(WCHAR));
  664. if (pwsz == NULL) {
  665. return FALSE;
  666. }
  667. cch2 = GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, pwsz, cch);
  668. cch2 -= 1;
  669. pwsz[cch2++] = ' ';
  670. GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, &pwsz[cch2], cch-cch2);
  671. #ifndef WIN16
  672. SetDlgItemTextW(hwnd, id, pwsz);
  673. #else
  674. SetDlgItemText(hwnd, id, pwsz);
  675. #endif // !WIN16
  676. #endif // MAC
  677. free(pwsz);
  678. return TRUE;
  679. }
  680. BOOL FormatIssuer(HWND hwnd, UINT id, PCCERT_CONTEXT pccert, DWORD dwFlags)
  681. {
  682. DWORD cch;
  683. LPWSTR psz;
  684. cch = CertNameToStrW(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Issuer,
  685. dwFlags | CERT_NAME_STR_CRLF_FLAG,
  686. NULL, 0);
  687. psz = (LPWSTR) malloc(cch*sizeof(TCHAR));
  688. CertNameToStrW(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Issuer,
  689. dwFlags | CERT_NAME_STR_CRLF_FLAG,
  690. psz, cch);
  691. SetDlgItemText(hwnd, id, psz);
  692. free(psz);
  693. return TRUE;
  694. }
  695. BOOL FormatSerialNo(HWND hwnd, UINT id, PCCERT_CONTEXT pccert)
  696. {
  697. DWORD i;
  698. CRYPT_INTEGER_BLOB * pblob;
  699. LPBYTE pb;
  700. WCHAR rgwch[128];
  701. pblob = &pccert->pCertInfo->SerialNumber;
  702. for (i=0, pb = &pblob->pbData[pblob->cbData-1];
  703. i < pblob->cbData; i++, pb--) {
  704. rgwch[i*2] = RgwchHex[(*pb & 0xf0) >> 4];
  705. rgwch[i*2+1] = RgwchHex[*pb & 0x0f];
  706. }
  707. rgwch[i*2] = 0;
  708. TruncateToWindowW(hwnd, id, rgwch);
  709. SetDlgItemText(hwnd, id, rgwch);
  710. return TRUE;
  711. }
  712. BOOL FormatSubject(HWND hwnd, UINT id, PCCERT_CONTEXT pccert, DWORD dwFlags)
  713. {
  714. DWORD cch;
  715. LPWSTR psz;
  716. cch = CertNameToStrW(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Subject,
  717. dwFlags | CERT_NAME_STR_CRLF_FLAG,
  718. NULL, 0);
  719. psz = (LPWSTR) malloc(cch*sizeof(WCHAR));
  720. CertNameToStrW(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Subject,
  721. dwFlags | CERT_NAME_STR_CRLF_FLAG,
  722. psz, cch);
  723. SetDlgItemText(hwnd, id, psz);
  724. free(psz);
  725. return TRUE;
  726. }
  727. BOOL FormatThumbprint(HWND hwnd, UINT id, PCCERT_CONTEXT pccert)
  728. {
  729. DWORD cb;
  730. DWORD i;
  731. BYTE rgb[20];
  732. WCHAR rgwch[61];
  733. WCHAR * pwch;
  734. cb = sizeof(rgb);
  735. if (!CertGetCertificateContextProperty(pccert, CERT_MD5_HASH_PROP_ID,
  736. rgb, &cb)) {
  737. return FALSE;
  738. }
  739. for (i=0, pwch = rgwch; i<cb; i++, pwch += 2) {
  740. pwch[0] = RgwchHex[(rgb[i] & 0xf0) >> 4];
  741. pwch[1] = RgwchHex[rgb[i] & 0x0f];
  742. if (((i % 4) == 3) && (i != cb-1)) {
  743. pwch[2] = ':';
  744. pwch++;
  745. }
  746. }
  747. *pwch = 0;
  748. TruncateToWindowW(hwnd, id, rgwch);
  749. SetDlgItemText(hwnd, id, rgwch);
  750. return TRUE;
  751. }
  752. BOOL FormatValidity(HWND hwnd, UINT id, PCCERT_CONTEXT pccert)
  753. {
  754. DWORD_PTR rgdw[3];
  755. WCHAR rgwchFormat[128];
  756. WCHAR rgwchNotAfter[128];
  757. WCHAR rgwchNotBefore[128];
  758. WCHAR rgwchValidity[256];
  759. SYSTEMTIME stNotAfter;
  760. SYSTEMTIME stNotBefore;
  761. rgdw[2] = (DWORD) -1; // Sentinal Value
  762. FileTimeToSystemTime(&pccert->pCertInfo->NotBefore, &stNotBefore);
  763. FileTimeToSystemTime(&pccert->pCertInfo->NotAfter, &stNotAfter);
  764. if (FIsWin95) {
  765. LoadStringA(HinstDll, IDS_VALIDITY_FORMAT,
  766. (LPSTR) rgwchFormat, sizeof(rgwchFormat));
  767. #ifdef MAC
  768. CreateDate(&stNotBefore, (LPSTR) rgwchNotBefore, FALSE);
  769. CreateDate(&stNotAfter, (LPSTR) rgwchNotAfter, FALSE);
  770. _snprintf((LPSTR) rgwchValidity, sizeof(rgwchNotAfter),
  771. (LPSTR) rgwchFormat, rgwchNotBefore, rgwchNotAfter);
  772. #else // !MAC
  773. GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stNotBefore,
  774. NULL, (LPSTR) rgwchNotBefore, sizeof(rgwchNotBefore));
  775. GetDateFormatA(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stNotAfter,
  776. NULL, (LPSTR) rgwchNotAfter, sizeof(rgwchNotAfter));
  777. rgdw[0] = (DWORD_PTR) rgwchNotBefore;
  778. rgdw[1] = (DWORD_PTR) rgwchNotAfter;
  779. FormatMessageA(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  780. rgwchFormat, 0, 0,
  781. (LPSTR) rgwchValidity, sizeof(rgwchValidity),
  782. (va_list *) rgdw);
  783. #endif // MAC
  784. SetDlgItemTextA(hwnd, id, (LPSTR) rgwchValidity);
  785. return TRUE;
  786. }
  787. #ifndef MAC
  788. GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stNotBefore,
  789. NULL, rgwchNotBefore, sizeof(rgwchNotBefore)/sizeof(WCHAR));
  790. GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stNotAfter,
  791. NULL, rgwchNotAfter, sizeof(rgwchNotAfter)/sizeof(WCHAR));
  792. LoadString(HinstDll, IDS_VALIDITY_FORMAT, rgwchFormat,
  793. sizeof(rgwchFormat)/sizeof(WCHAR));
  794. rgdw[0] = (DWORD_PTR) rgwchNotBefore;
  795. rgdw[1] = (DWORD_PTR) rgwchNotAfter;
  796. FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  797. rgwchFormat, 0, 0,
  798. rgwchValidity, sizeof(rgwchValidity)/sizeof(WCHAR),
  799. (va_list *) rgdw);
  800. SetDlgItemText(hwnd, id, rgwchValidity);
  801. #endif // !MAC
  802. return TRUE;
  803. }
  804. ////////////////////////////////////////////////////////////////////
  805. //+-------------------------------------------------------------------------
  806. // Find the szOID_COMMON_NAME extension.
  807. //
  808. // If found, allocates and converts to a WCHAR string
  809. //
  810. // Returned WCHAR string needs to be CoTaskMemFree'ed.
  811. //--------------------------------------------------------------------------
  812. static LPWSTR GetCommonNameExtension(
  813. IN PCCERT_CONTEXT pCert
  814. )
  815. {
  816. LPWSTR pwsz = NULL;
  817. PCERT_INFO pCertInfo = pCert->pCertInfo;
  818. PCERT_NAME_VALUE pNameValue = NULL;
  819. PCERT_EXTENSION pExt;
  820. pExt = CertFindExtension(
  821. szOID_COMMON_NAME,
  822. pCertInfo->cExtension,
  823. pCertInfo->rgExtension
  824. );
  825. if (pExt) {
  826. DWORD cbInfo = 0;
  827. PCERT_RDN_VALUE_BLOB pValue;
  828. DWORD dwValueType;
  829. DWORD cwsz;
  830. CryptDecodeObject(
  831. X509_ASN_ENCODING,
  832. X509_NAME_VALUE,
  833. pExt->Value.pbData,
  834. pExt->Value.cbData,
  835. 0, // dwFlags
  836. NULL, // pNameValue
  837. &cbInfo
  838. );
  839. if (cbInfo == 0) goto CommonReturn;
  840. if (NULL == (pNameValue = (PCERT_NAME_VALUE) /*CoTaskMemAlloc(cbInfo)))*/ malloc(cbInfo)))
  841. goto CommonReturn;
  842. if (!CryptDecodeObject(
  843. X509_ASN_ENCODING,
  844. X509_NAME_VALUE,
  845. pExt->Value.pbData,
  846. pExt->Value.cbData,
  847. 0, // dwFlags
  848. pNameValue,
  849. &cbInfo)) goto CommonReturn;
  850. dwValueType = pNameValue->dwValueType;
  851. pValue = &pNameValue->Value;
  852. cwsz = CertRDNValueToStrW(
  853. dwValueType,
  854. pValue,
  855. NULL, // pwsz
  856. 0 // cwsz
  857. );
  858. if (cwsz > 1) {
  859. pwsz = (LPWSTR) /*CoTaskMemAlloc(cwsz * sizeof(WCHAR))*/ malloc(cwsz*sizeof(WCHAR));
  860. if (pwsz)
  861. CertRDNValueToStrW(
  862. dwValueType,
  863. pValue,
  864. pwsz,
  865. cwsz
  866. );
  867. }
  868. }
  869. CommonReturn:
  870. if (pNameValue)
  871. /* CoTaskMemFree(pNameValue);*/ free(pNameValue);
  872. return pwsz;
  873. }
  874. //+-------------------------------------------------------------------------
  875. // Searches the name attributes for the first specified ObjId.
  876. //
  877. // If found, allocates and converts to a WCHAR string
  878. //
  879. // Returned WCHAR string needs to be CoTaskMemFree'ed.
  880. //--------------------------------------------------------------------------
  881. static LPWSTR GetRDNAttrWStr(
  882. IN LPCSTR pszObjId,
  883. IN PCERT_NAME_BLOB pNameBlob
  884. )
  885. {
  886. LPWSTR pwsz = NULL;
  887. PCERT_NAME_INFO pNameInfo = NULL;
  888. PCERT_RDN_ATTR pRDNAttr;
  889. DWORD cbInfo = 0;
  890. CryptDecodeObject(
  891. X509_ASN_ENCODING,
  892. X509_NAME,
  893. pNameBlob->pbData,
  894. pNameBlob->cbData,
  895. 0, // dwFlags
  896. NULL, // pNameInfo
  897. &cbInfo
  898. );
  899. if (cbInfo == 0) goto CommonReturn;
  900. if (NULL == (pNameInfo = (PCERT_NAME_INFO) /*CoTaskMemAlloc(cbInfo)*/ malloc(cbInfo)))
  901. goto CommonReturn;
  902. if (!CryptDecodeObject(
  903. X509_ASN_ENCODING,
  904. X509_NAME,
  905. pNameBlob->pbData,
  906. pNameBlob->cbData,
  907. 0, // dwFlags
  908. pNameInfo,
  909. &cbInfo)) goto CommonReturn;
  910. pRDNAttr = CertFindRDNAttr(pszObjId, pNameInfo);
  911. if (pRDNAttr) {
  912. PCERT_RDN_VALUE_BLOB pValue = &pRDNAttr->Value;
  913. DWORD dwValueType = pRDNAttr->dwValueType;
  914. DWORD cwsz;
  915. cwsz = CertRDNValueToStrW(
  916. dwValueType,
  917. pValue,
  918. NULL, // pwsz
  919. 0 // cwsz
  920. );
  921. if (cwsz > 1) {
  922. pwsz = (LPWSTR) /*CoTaskMemAlloc(cwsz * sizeof(WCHAR))*/ malloc(cwsz * sizeof(WCHAR));
  923. if (pwsz)
  924. CertRDNValueToStrW(
  925. dwValueType,
  926. pValue,
  927. pwsz,
  928. cwsz
  929. );
  930. }
  931. }
  932. CommonReturn:
  933. if (pNameInfo)
  934. /*CoTaskMemFree(pNameInfo);*/ free(pNameInfo);
  935. return pwsz;
  936. }
  937. LPWSTR PrettySubject(PCCERT_CONTEXT pccert)
  938. {
  939. DWORD cb;
  940. DWORD cch;
  941. BOOL f;
  942. LPWSTR pwsz;
  943. //
  944. // If the user has put a friendly name onto a certificate, then we
  945. // should display that as the pretty name for the certificate.
  946. //
  947. f = CertGetCertificateContextProperty(pccert, CERT_FRIENDLY_NAME_PROP_ID,
  948. NULL, &cb);
  949. // cb includes terminating NULL
  950. if (f && (cb > sizeof(TCHAR))) {
  951. pwsz = (LPWSTR) malloc(cb);
  952. if (NULL != pwsz) {
  953. CertGetCertificateContextProperty(pccert, CERT_FRIENDLY_NAME_PROP_ID,
  954. pwsz, &cb);
  955. return pwsz;
  956. }
  957. }
  958. pwsz = GetCommonNameExtension(pccert);
  959. if (pwsz != NULL) {
  960. return pwsz;
  961. }
  962. pwsz = GetRDNAttrWStr(szOID_COMMON_NAME, &pccert->pCertInfo->Subject);
  963. if (pwsz != NULL) {
  964. return pwsz;
  965. }
  966. pwsz = GetRDNAttrWStr(szOID_RSA_emailAddr, &pccert->pCertInfo->Subject);
  967. if (pwsz != NULL) {
  968. return pwsz;
  969. }
  970. cch = CertNameToStr(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Subject,
  971. CERT_SIMPLE_NAME_STR, NULL, 0);
  972. pwsz = (LPTSTR) malloc(cch*sizeof(TCHAR));
  973. if (pwsz != NULL) {
  974. CertNameToStr(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Subject,
  975. CERT_SIMPLE_NAME_STR, pwsz, cch);
  976. }
  977. return pwsz;
  978. }
  979. LPWSTR PrettyIssuer(PCCERT_CONTEXT pccert)
  980. {
  981. DWORD cch;
  982. LPWSTR pwsz;
  983. // pwsz = GetCommonNameExtension(pccert);
  984. // if (pwsz != NULL) {
  985. // return pwsz;
  986. // }
  987. pwsz = GetRDNAttrWStr(szOID_COMMON_NAME, &pccert->pCertInfo->Issuer);
  988. if (pwsz != NULL) {
  989. return pwsz;
  990. }
  991. cch = CertNameToStr(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Issuer,
  992. CERT_SIMPLE_NAME_STR, NULL, 0);
  993. pwsz = (LPTSTR) malloc(cch*sizeof(TCHAR));
  994. CertNameToStr(CRYPT_ASN_ENCODING, &pccert->pCertInfo->Issuer,
  995. CERT_SIMPLE_NAME_STR, pwsz, cch);
  996. return pwsz;
  997. }
  998. LPWSTR PrettySubjectIssuer(PCCERT_CONTEXT pccert)
  999. {
  1000. int cwsz;
  1001. LPWSTR pwsz;
  1002. LPWSTR pwszIssuer;
  1003. LPWSTR pwszSubject;
  1004. pwszSubject = PrettySubject(pccert);
  1005. if (NULL == pwszSubject) {
  1006. return NULL;
  1007. }
  1008. pwszIssuer = PrettyIssuer(pccert);
  1009. if (NULL == pwszIssuer) {
  1010. free(pwszSubject);
  1011. return NULL;
  1012. }
  1013. cwsz = wcslen(pwszSubject) + wcslen(pwszIssuer) + 20;
  1014. pwsz = (LPWSTR) malloc(cwsz*sizeof(WCHAR));
  1015. StrCpyNW(pwsz, pwszSubject, cwsz);
  1016. #ifndef WIN16
  1017. StrCatBuffW(pwsz, L" (", cwsz);
  1018. StrCatBuffW(pwsz, pwszIssuer, cwsz);
  1019. StrCatBuffW(pwsz, L")", cwsz);
  1020. #else
  1021. StrCatBuffW(pwsz, " (", cwsz);
  1022. StrCatBuffW(pwsz, pwszIssuer, cwsz);
  1023. StrCatBuffW(pwsz, ")", cwsz);
  1024. #endif
  1025. free(pwszSubject);
  1026. free(pwszIssuer);
  1027. return pwsz;
  1028. }
  1029. #ifndef MAC
  1030. BOOL OnContextHelp(HWND /*hwnd*/, UINT uMsg, WPARAM wParam, LPARAM lParam,
  1031. HELPMAP const * rgCtxMap)
  1032. {
  1033. if (uMsg == WM_HELP) {
  1034. LPHELPINFO lphi = (LPHELPINFO) lParam;
  1035. if (lphi->iContextType == HELPINFO_WINDOW) { // must be for a control
  1036. #ifndef WIN16
  1037. WinHelp ((HWND)lphi->hItemHandle, L"iexplore.hlp", HELP_WM_HELP,
  1038. (ULONG_PTR)(LPVOID)rgCtxMap);
  1039. #else
  1040. WinHelp ((HWND)lphi->hItemHandle, "iexplore.hlp", HELP_WM_HELP,
  1041. (ULONG_PTR)(LPVOID)rgCtxMap);
  1042. #endif // !WIN16
  1043. }
  1044. return (TRUE);
  1045. }
  1046. else if (uMsg == WM_CONTEXTMENU) {
  1047. #ifndef WIN16
  1048. WinHelp ((HWND) wParam, L"iexplore.hlp", HELP_CONTEXTMENU,
  1049. (ULONG_PTR)(LPVOID)rgCtxMap);
  1050. #else
  1051. WinHelp ((HWND) wParam, "iexplore.hlp", HELP_CONTEXTMENU,
  1052. (ULONG_PTR)(LPVOID)rgCtxMap);
  1053. #endif // !WIN16
  1054. return (TRUE);
  1055. }
  1056. return FALSE;
  1057. }
  1058. #endif // MAC
  1059. /////////////////////////////////////////////////////////////////////////
  1060. //// GetFriendlyNameOfCertA
  1061. //
  1062. // Description:
  1063. // This routine is an exported routine which can be used to get
  1064. // a friendly name from a certificate. The function uses the
  1065. // buffer supplied by the caller to store the formated name in.
  1066. // This is the ANSI half of the function pair.
  1067. //
  1068. DWORD GetFriendlyNameOfCertA(PCCERT_CONTEXT pccert, LPSTR pch, DWORD cch)
  1069. {
  1070. DWORD cch2;
  1071. LPWSTR pwsz;
  1072. //
  1073. // Now do the normal pretty printing functionality. This allocates and
  1074. // returns a buffer to the caller (us).
  1075. //
  1076. pwsz = PrettySubject(pccert);
  1077. if (NULL == pwsz) {
  1078. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1079. return 0;
  1080. }
  1081. //
  1082. // Convert the returned string from a Unicode string to an ANSI string
  1083. //
  1084. cch2 = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, NULL, 0, NULL, NULL);
  1085. if ((pch != NULL) && (cch2 <= cch)) {
  1086. cch2 = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, pch, cch, NULL, NULL);
  1087. }
  1088. else if (pch != NULL) {
  1089. SetLastError(ERROR_MORE_DATA);
  1090. }
  1091. free(pwsz);
  1092. return cch2;
  1093. }
  1094. //// GetFriendlyNameOfCertW
  1095. //
  1096. // Description:
  1097. // This routine is an exported routine which can be used to get
  1098. // a friendly name from a certificate. The function uses the
  1099. // buffer supplied by the caller to store the formated name in.
  1100. // This is the UNICODE half of the function pair.
  1101. //
  1102. DWORD GetFriendlyNameOfCertW(PCCERT_CONTEXT pccert, LPWSTR pwch, DWORD cwch)
  1103. {
  1104. DWORD cwch2;
  1105. LPWSTR pwsz;
  1106. //
  1107. // Now do the normal pretty printing functionality. This allocates and
  1108. // returns a buffer to the caller (us).
  1109. //
  1110. pwsz = PrettySubject(pccert);
  1111. if (NULL == pwsz) {
  1112. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1113. return 0;
  1114. }
  1115. cwch2 = wcslen(pwsz) + 1;
  1116. //
  1117. // Duplicate the string into the provided buffer.
  1118. //
  1119. if ((pwch != NULL) && (cwch2 <= cwch)) {
  1120. StrCpyNW(pwch, pwsz, cwch);
  1121. }
  1122. else if (pwch != NULL) {
  1123. SetLastError(ERROR_MORE_DATA);
  1124. }
  1125. free(pwsz);
  1126. return cwch2;
  1127. }
  1128. const BYTE mpchfLegalForURL[] =
  1129. {
  1130. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
  1131. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1132. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16
  1133. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1134. 0x00, 0x11, 0x00, 0x11, 0x01, 0x01, 0x01, 0x01, // 32
  1135. 0x01, 0x11, 0x01, 0x01, 0x11, 0x01, 0x11, 0x01,
  1136. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 48
  1137. 0x01, 0x01, 0x11, 0x01, 0x00, 0x01, 0x00, 0x11,
  1138. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 64
  1139. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  1140. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 80
  1141. 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01,
  1142. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 96
  1143. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  1144. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 112
  1145. 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00,
  1146. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 128
  1147. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1148. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 144
  1149. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1150. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 160
  1151. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1152. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 176
  1153. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1154. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 192
  1155. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1156. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 208
  1157. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1158. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 224
  1159. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1160. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 240
  1161. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1162. };
  1163. const char szURLSep[] = ":";
  1164. const char szURLCloseBrace[] = ">";
  1165. const char chURLOpenBrace = '<';
  1166. // ordered by match probability and string length
  1167. const char g_szURLDefaultPrefixs[] =
  1168. "http" "\0"
  1169. "file" "\0"
  1170. "ftp" "\0"
  1171. "news" "\0"
  1172. "mailto" "\0"
  1173. "https" "\0"
  1174. "gopher" "\0"
  1175. "telnet" "\0"
  1176. "nntp" "\0"
  1177. "wais" "\0"
  1178. "prospero\0\0";
  1179. LPSTR g_pszURLPrefixs = (LPSTR) g_szURLDefaultPrefixs;
  1180. #define cchURLPrefixMost 28
  1181. BOOL g_fLoadBrowserRegistry = 1;
  1182. TCHAR g_szBrowser[MAX_PATH];
  1183. COLORREF g_crLink = RGB(0, 0, 255);
  1184. /*
  1185. * NoteRecognizeURLs
  1186. *
  1187. * Purpose:
  1188. * Change the charformat of text in the richedit control
  1189. * for text that begins with http: ftp: or other.
  1190. *
  1191. * Arguments:
  1192. * HWND A handle to the richedit control
  1193. * fLoadBrowserRegistry Should we read the registry ?
  1194. *
  1195. * Returns:
  1196. * VOID That would be nothing
  1197. *
  1198. * Notes:
  1199. *
  1200. * g_fLoadBrowserRegistry must be true on the first call
  1201. * this may change g_szBrowser, g_crLink, and or g_pszURLPrefixs
  1202. * g_pszURLPrefixs must equal g_szURLDefaultPrefixs, and must not be NULL
  1203. *
  1204. * if g_szBrowser, the path to the browser, is not found in the registry,
  1205. * it will be defaulted to one of three things: !, url.dll, or iexplore
  1206. *
  1207. */
  1208. VOID RecognizeURLs(HWND hwndRE)
  1209. {
  1210. int isz;
  1211. LONG cchBrace;
  1212. LONG cpBraceSearch;
  1213. LONG cpMatch;
  1214. LONG cpSep;
  1215. LONG cpEnd;
  1216. LPSTR pch;
  1217. CHARRANGE chrgSave;
  1218. FINDTEXTEX ft;
  1219. TEXTRANGEA tr;
  1220. CHARFORMATA cf;
  1221. char szBuff[MAX_PATH]; // szBuff must be at least cchURLPrefixMost
  1222. LPSTR szT;
  1223. LPARAM lNotifSuppression;
  1224. #if MAX_PATH < cchURLPrefixMost
  1225. #error MAX_PATH < cchURLPrefixMost
  1226. #endif
  1227. if (g_fLoadBrowserRegistry) {
  1228. // INT cch; // signed to compare against 0
  1229. // hopefully we will not have to re-read
  1230. // from the registry again, but a winini change
  1231. // will force another read - see mlview shell.c
  1232. g_fLoadBrowserRegistry = 0;
  1233. #if 0
  1234. // if they change the default charformat
  1235. // compute the hex stored color ref
  1236. cch = GetMailRegistryString(imkeyURLColor, NULL, g_szBrowser, sizeof(g_szBrowser));
  1237. if (cch > 0) {
  1238. LPTSTR psz = g_szBrowser;
  1239. g_crLink = 0;
  1240. for (; cch > 0; --cch, psz++) {
  1241. g_crLink *= 16;
  1242. if (*psz <= '9')
  1243. g_crLink += *psz - TEXT('0');
  1244. else if (*psz <= 'F')
  1245. g_crLink += *psz - TEXT('A') + 10;
  1246. else
  1247. g_crLink += *psz - TEXT('a') + 10;
  1248. }
  1249. }
  1250. #endif // 0
  1251. #if 0
  1252. // grab the path to their browser, and
  1253. // set the disable flag if appropriate
  1254. cch = GetMailRegistryString(imkeyBrowser, NULL, g_szBrowser, sizeof(g_szBrowser));
  1255. if (cch <= 0) {
  1256. #endif // 0
  1257. #ifndef MAC
  1258. StrCpyN(g_szBrowser, TEXT("c:\\inetsrv\\iexplore\\iexplore.exe"), ARRAYSIZE(g_szBrowser));
  1259. #else // MAC
  1260. StrCpyN(g_szBrowser, TEXT(":MSIE:APPL"), ARRAYSIZE(g_szBrowser));
  1261. #endif // !MAC
  1262. #if 0
  1263. }
  1264. #endif // 0
  1265. }
  1266. // Prepare a few local variables for use
  1267. szT = szBuff;
  1268. cf.cbSize = sizeof(cf);
  1269. ft.chrg.cpMin = 0;
  1270. ft.chrg.cpMax = -1; // search the entire message body
  1271. ft.lpstrText = (LPTSTR) szURLSep; // for a colon
  1272. tr.lpstrText = szBuff;
  1273. cf.cbSize = sizeof(cf);
  1274. cf.dwMask = CFM_LINK;
  1275. cf.dwEffects = 0;
  1276. cpBraceSearch = 0;
  1277. SendMessage(hwndRE, EM_EXGETSEL, 0, (LPARAM) &chrgSave);
  1278. SendMessage(hwndRE, EM_HIDESELECTION, TRUE, FALSE);
  1279. lNotifSuppression = SendMessage(hwndRE,EM_GETEVENTMASK,0,0);
  1280. SendMessage(hwndRE, EM_SETEVENTMASK, (WPARAM) 0, 0);
  1281. // remove existing link bits so that the user does not
  1282. // get hosed when he/she saves text that was mistakenly marked
  1283. // as linked ... gee, this SCF_ALL flag is a big perf win
  1284. SendMessage(hwndRE, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf);
  1285. // loop all the way to the bottom of the note
  1286. // one iteration per find of a potential match
  1287. // when we locate a colon
  1288. for (;;) {
  1289. LONG cpLast = 0;
  1290. // find the colon
  1291. cpSep = (LONG) SendMessage(hwndRE, EM_FINDTEXTEX, 0, (LPARAM) &ft);
  1292. if (cpSep < 0)
  1293. break;
  1294. cpEnd = ft.chrgText.cpMax;
  1295. ft.chrg.cpMin = cpEnd;
  1296. // make sure the word to the left of the colon
  1297. // is present and of a reasonable size
  1298. cpMatch = (LONG) SendMessage(hwndRE, EM_FINDWORDBREAK, WB_MOVEWORDLEFT, ft.chrgText.cpMin);
  1299. if (cpMatch == cpSep)
  1300. continue;
  1301. // sender of message is just being a jerk
  1302. // so, do a quick check to avoid pathological cases
  1303. if (cpMatch < cpSep - cchURLPrefixMost) {
  1304. ft.chrg.cpMin = (LONG) SendMessage(hwndRE, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, cpSep);
  1305. // Assert(ft.chrg.cpMin > cpSep);
  1306. continue;
  1307. }
  1308. // pull the text of the keyword out into szBuff
  1309. // to compare against our word list ... also grab
  1310. // the character to the left in case we are
  1311. // enclosed in matching braces
  1312. cchBrace = 0;
  1313. tr.chrg.cpMin = cpMatch - cchBrace;
  1314. tr.chrg.cpMax = cpSep;
  1315. if (!SendMessage(hwndRE, EM_GETTEXTRANGE, 0, (LPARAM) &tr))
  1316. goto end;
  1317. // compare to each word in our list
  1318. for (isz = 0; g_pszURLPrefixs[isz]; isz+=lstrlenA(g_pszURLPrefixs+isz)+1) {
  1319. if (0 == lstrcmpiA(szBuff + cchBrace, &g_pszURLPrefixs[isz]))
  1320. goto match;
  1321. }
  1322. continue;
  1323. match:
  1324. ft.chrgText.cpMin = cpMatch;
  1325. cpLast = cpEnd; // assume that we will stop after the colon
  1326. // check to see if this is the brace character
  1327. if (cchBrace && chURLOpenBrace == szBuff[0]) {
  1328. FINDTEXTEX ft;
  1329. LONG cpBraceClose;
  1330. ft.chrg.cpMin = max(cpEnd, cpBraceSearch);
  1331. ft.chrg.cpMax = cpEnd + MAX_PATH;
  1332. ft.lpstrText = (LPTSTR) szURLCloseBrace;
  1333. cpBraceClose = (LONG) SendMessage(hwndRE, EM_FINDTEXTEX, 0, (LPARAM) &ft);
  1334. if (cpBraceClose >= 0) {
  1335. tr.chrg.cpMin = cpEnd;
  1336. tr.chrg.cpMax = cpEnd + 1;
  1337. if (!SendMessage(hwndRE, EM_GETTEXTRANGE, 0, (LPARAM) &tr) || ' ' == szBuff[0])
  1338. goto end;
  1339. cpLast = cpEnd = ft.chrgText.cpMin;
  1340. cpBraceSearch = cpLast + 1;
  1341. goto end;
  1342. }
  1343. else {
  1344. cpBraceSearch = ft.chrg.cpMax;
  1345. }
  1346. }
  1347. // loop through chunks of the URL in
  1348. // steps of sizeof(szBuff) looking for a terminator
  1349. // set cpLast to the last terminator byte that is legal according to us
  1350. for (;;) {
  1351. tr.chrg.cpMin = cpLast = cpEnd;
  1352. tr.chrg.cpMax = cpEnd + sizeof(szBuff) - 1;
  1353. if (!SendMessage(hwndRE, EM_GETTEXTRANGE, 0, (LPARAM) &tr))
  1354. goto end;
  1355. for (pch = szBuff; *pch; pch++, cpEnd++) {
  1356. const BYTE fb = mpchfLegalForURL[*pch];
  1357. #ifdef DBCS
  1358. if (!fb || FGLeadByte(*pch))
  1359. #else // DBCS
  1360. if (!fb)
  1361. #endif // DBCS
  1362. {
  1363. goto end;
  1364. }
  1365. if(!(fb & 0x10)) {
  1366. cpLast = cpEnd + 1;
  1367. }
  1368. }
  1369. }
  1370. end:
  1371. if (cpLast == cpSep + 1) // hmmm... just "http:" then terminator
  1372. continue; // must have argument to be legal
  1373. // select the entire URL including the http colon,
  1374. // mark it as linked, and change the charformat if appropriate
  1375. ft.chrgText.cpMax = cpLast;
  1376. SendMessage(hwndRE, EM_EXSETSEL, 0, (LPARAM) &ft.chrgText);
  1377. cf.dwMask = CFM_LINK | CFM_UNDERLINE | CFM_COLOR;
  1378. if (((LONG)g_crLink) < 0)
  1379. cf.dwMask &= ~CFM_UNDERLINE; /* high bit turns off underline */
  1380. if (((LONG)g_crLink) & 0x40000000)
  1381. cf.dwMask &= ~CFM_COLOR; /* next bit turns off color */
  1382. cf.dwEffects = CFE_LINK | CFE_UNDERLINE;
  1383. cf.crTextColor = g_crLink;
  1384. SendMessage(hwndRE, EM_SETCHARFORMAT, SCF_SELECTION,
  1385. (LPARAM) &cf);
  1386. // no need to re-search through the URL
  1387. // so, just advance past the last totally cool URL character
  1388. ft.chrg.cpMin = cpLast + 1;
  1389. } // end loop through richedit text
  1390. SendMessage(hwndRE, EM_EXSETSEL, 0, (LPARAM) &chrgSave);
  1391. SendMessage(hwndRE, EM_HIDESELECTION, FALSE, FALSE);
  1392. SendMessage(hwndRE, EM_SETEVENTMASK, (WPARAM) 0, (LPARAM) lNotifSuppression);
  1393. return;
  1394. }
  1395. #ifndef MAC
  1396. /*
  1397. * FNoteDlgNotifyLink
  1398. *
  1399. * Purpose:
  1400. * Handle the user clicking on a link
  1401. *
  1402. * Arguments:
  1403. * hwndDlg Parent dialog
  1404. * penlink Link notification structure
  1405. * szURL URL to launch
  1406. *
  1407. * Returns:
  1408. * BOOL TRUE if we processed message, else FALSE
  1409. */
  1410. BOOL FNoteDlgNotifyLink(HWND hwndDlg, ENLINK * penlink, LPSTR szURL)
  1411. {
  1412. // BOOL fShift;
  1413. LONG cch, cchBuffer;
  1414. TEXTRANGEA tr;
  1415. char szCmd[2*MAX_PATH + 2];
  1416. #ifdef MAC
  1417. BOOL fPickedBrowser = FALSE;
  1418. #endif
  1419. HCURSOR hcursor;
  1420. // eat the double click - just activate on single click
  1421. if (WM_LBUTTONDBLCLK == penlink->msg) {
  1422. return TRUE;
  1423. }
  1424. // if we got this far, we are enabled so assert that the path
  1425. // does not explicitly say we should be disabled
  1426. // below this point, we return true meaning that
  1427. // we handled this message, and richedit should do nothing
  1428. hcursor = SetCursor(LoadCursorA(NULL, (LPSTR) IDC_WAIT));
  1429. #ifndef MAC
  1430. // prepare szCmd for use as the parameter to execution
  1431. // AssertSz(sizeof(szCmd) > sizeof(g_szBrowser), "cat may overwrite");
  1432. wnsprintfA(szCmd, ARRAYSIZE(szCmd), "%s ", g_szBrowser);
  1433. cch = lstrlenA(szCmd);
  1434. tr.chrg.cpMin = penlink->chrg.cpMin;
  1435. tr.chrg.cpMax = min((LONG) (tr.chrg.cpMin + sizeof(szCmd) - cch - 1), penlink->chrg.cpMax);
  1436. cchBuffer = ARRAYSIZE(szCmd) - cch;
  1437. tr.lpstrText = &szCmd[cch];
  1438. #else
  1439. cch = 0;
  1440. szCmd[0] = TEXT('\0');
  1441. tr.chrg.cpMin = penlink->chrg.cpMin;
  1442. tr.chrg.cpMax = min((LONG) (tr.chrg.cpMin + sizeof(szCmd) - cch - 1), penlink->chrg.cpMax);
  1443. cchBuffer = ARRAYSIZE(szCmd) - cch;
  1444. tr.lpstrText = szCmd;
  1445. #endif
  1446. // add the web path to the command line
  1447. if (szURL) {
  1448. cch = lstrlenA(szURL);
  1449. StrCpyNA(tr.lpstrText, szURL, cchBuffer);
  1450. }
  1451. else {
  1452. cch = (LONG) SendMessage(penlink->nmhdr.hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM) &tr);
  1453. }
  1454. if (cch > 0)
  1455. #ifndef MAC
  1456. {
  1457. HINSTANCE hinst;
  1458. UINT ui;
  1459. #if defined(WIN32) && !defined(MAC)
  1460. SetProcessWorkingSetSize(GetCurrentProcess(), 0xffffffff, 0xffffffff);
  1461. #endif
  1462. // execute the browser, however the current operating system wants to ...
  1463. hinst = ShellExecuteA(hwndDlg, NULL, tr.lpstrText, NULL, NULL, SW_SHOWNORMAL);
  1464. if ((UINT_PTR) hinst > 32) {
  1465. SetCursor(hcursor);
  1466. return TRUE;
  1467. }
  1468. // the operating system failed to launch the browser, let me try ...
  1469. ui = WinExec(szCmd, SW_SHOW);
  1470. if (ui < 32) {
  1471. // perhaps they moved or deleted their executable regardless
  1472. // of the error, we will just browse for a path
  1473. // this is currently by design
  1474. MessageBeep(MB_OK);
  1475. SetCursor(hcursor);
  1476. return FALSE;
  1477. }
  1478. }
  1479. SetCursor(hcursor);
  1480. return TRUE;
  1481. #else // MAC
  1482. {
  1483. HWND hwndActive;
  1484. ProcessSerialNumber psn;
  1485. AppleEvent aeEvent = { 0 };
  1486. AppleEvent aeReply = { 0 };
  1487. AEAddressDesc aedAddr = { 0 };
  1488. AEEventClass aecOpenURL = 'WWW!';
  1489. AEEventID aeidOpenURL = 'OURL';
  1490. OSErr errLaunch = icPrefNotFoundErr;
  1491. OSType ostBrowser;
  1492. OSType ostType;
  1493. SCODE sc = S_OK;
  1494. TCHAR szCaption[MAX_PATH];
  1495. // Prompt the user to see if we can open the URL safely
  1496. hwndActive = GetActiveWindow();
  1497. if (!GetWindowText(hwndActive, szCaption,
  1498. (sizeof(szCaption) / sizeof(TCHAR)))) {
  1499. szCaption[0] = TEXT('\0');
  1500. }
  1501. if (!FIsSafeURL(hwndActive, tr.lpstrText, szCaption)) {
  1502. goto Exit;
  1503. }
  1504. // See if we have an Internet Config instance
  1505. if (INST(picinstIConfig) != NULL) {
  1506. ICAppSpec icappHelper = { 0 };
  1507. ICAttr icattr;
  1508. LONG lSize;
  1509. Str255 strHelper = kICHelper;
  1510. TCHAR* pchHelper;
  1511. TCHAR* pchURL;
  1512. // Locate the end of the Helper string and add the protocol
  1513. // from the URL
  1514. pchHelper = strHelper + (sizeof(kICHelper) - 1);
  1515. pchURL = tr.lpstrText;
  1516. while ((*pchURL != TEXT('\0')) && (*pchURL != TEXT(':'))) {
  1517. *pchHelper = *pchURL;
  1518. pchURL++;
  1519. pchHelper++;
  1520. strHelper[0]++;
  1521. }
  1522. // Call Internet Config to see if we have a helper for this
  1523. // protocol defined
  1524. lSize = sizeof(ICAppSpec);
  1525. errLaunch = (OSErr)ICGetPref(INST(picinstIConfig), strHelper,
  1526. &icattr, (LPBYTE)&icappHelper,
  1527. &lSize);
  1528. if (errLaunch == noErr) {
  1529. // Got a helper application, extract the information needed
  1530. // to launch the correct helper with a GURL event
  1531. ostBrowser = icappHelper.fCreator;
  1532. aecOpenURL = 'GURL';
  1533. aeidOpenURL = 'GURL';
  1534. }
  1535. }
  1536. // If we do not have an error at this point that means that Internet
  1537. // Config found the helper. Otherwise, we need to look in the
  1538. // standard preferences for the browser.
  1539. if (errLaunch != noErr) {
  1540. // Create a Mac OSType from the browser string
  1541. if (!FMacSignatureFromMacInfo(g_szBrowser, NULL, &ostBrowser,
  1542. &ostType)) {
  1543. goto Exit;
  1544. }
  1545. }
  1546. // If Exchange is the designated helper we want to avoid the expense
  1547. // of using AppleEvents
  1548. if (ostBrowser != 'EXCH') {
  1549. // Set up the AppleEvent
  1550. errLaunch = AECreateDesc(typeApplSignature, &ostBrowser,
  1551. sizeof(OSType), &aedAddr);
  1552. if (errLaunch != noErr) {
  1553. goto CleanupAEvent;
  1554. }
  1555. // Create the AppleEvent to send to the web browser
  1556. errLaunch = AECreateAppleEvent(aecOpenURL, aeidOpenURL, &aedAddr,
  1557. kAutoGenerateReturnID,
  1558. kAnyTransactionID, &aeEvent);
  1559. if (errLaunch != noErr) {
  1560. goto CleanupAEvent;
  1561. }
  1562. // Add the URL as the direct parameter
  1563. errLaunch = AEPutParamPtr(&aeEvent, keyDirectObject, typeChar,
  1564. tr.lpstrText, _tcslen(tr.lpstrText));
  1565. if (errLaunch != noErr) {
  1566. goto CleanupAEvent;
  1567. }
  1568. // Get a running instance of the browser so that we have something
  1569. // to actually process our event and send it the open command.
  1570. errLaunch = ErrLaunchCreatorEx(ostBrowser,
  1571. launchContinue | launchUseMinimum,
  1572. &aeEvent,
  1573. kAEWaitReply | kAEAlwaysInteract,
  1574. &aeReply, NULL, &psn);
  1575. if (errLaunch != noErr) {
  1576. #if 0
  1577. // If we could not launch the browser because it was not
  1578. // found, we need to try and choose a browser to use,
  1579. // otherwise we just ignore the error and fail gracefully.
  1580. if ((errLaunch == fnfErr) && (!fPickedBrowser)) {
  1581. fPickedBrowser = TRUE;
  1582. SetCursor(hcursor);
  1583. goto pick;
  1584. }
  1585. #endif // 0
  1586. goto CleanupAEvent;
  1587. }
  1588. ErrSetFrontProcess(&psn);
  1589. CleanupAEvent:
  1590. AEDisposeDesc(&aeEvent);
  1591. AEDisposeDesc(&aeReply);
  1592. AEDisposeDesc(&aedAddr);
  1593. }
  1594. else {
  1595. LPIEDATA pieData = NULL;
  1596. LPTSTR pszURL = NULL;
  1597. LONG iProtocol;
  1598. ULONG cchText;
  1599. // Allocate a buffer to store the URL in
  1600. cchText = _tcslen(tr.lpstrText)+1;
  1601. pszURL = PvAlloc((cchText * sizeof(TCHAR)),
  1602. fZeroFill);
  1603. if (pszURL == NULL) {
  1604. goto CleanupIEData;
  1605. }
  1606. StrCpyN(pszURL, tr.lpstrText, cchText);
  1607. // Make sure this is a protocol supported by Exchange
  1608. for (iProtocol = 0; iProtocol < g_lNumIESupProtocols; iProtocol++) {
  1609. if (_tcsncmp(pszURL, g_iesupMac[iProtocol].szProtocol,
  1610. _tcslen(g_iesupMac[iProtocol].szProtocol)) == 0) {
  1611. // Found a match
  1612. break;
  1613. }
  1614. }
  1615. if (iProtocol == g_lNumIESupProtocols) {
  1616. // No match found
  1617. goto CleanupIEData;
  1618. }
  1619. // Create the appropriate IEDATA structure
  1620. pieData = PvAlloc(sizeof(IEDATA), fZeroFill);
  1621. if (pieData == NULL) {
  1622. goto CleanupIEData;
  1623. }
  1624. pieData->szURL = pszURL;
  1625. pieData->idxProtocol = iProtocol;
  1626. // Post an internal message to ourselves to actually do the
  1627. // processing
  1628. PostMessage(INST(hwndCentral), EXIE_OPENURL, 0, (LPARAM)pieData);
  1629. goto Exit;
  1630. CleanupIEData:
  1631. if (pszURL != NULL) {
  1632. FreePv(pszURL);
  1633. }
  1634. if (pieData != NULL) {
  1635. FreePv(pieData);
  1636. }
  1637. }
  1638. }
  1639. Exit:
  1640. SetCursor(hcursor);
  1641. return TRUE;
  1642. #endif // !MAC
  1643. }
  1644. #endif // !MAC
  1645. /////////////////////////////////////////////////////////////////////////
  1646. //
  1647. // This code provides the first cut of the Verisign Cert Policy Statement
  1648. // implemenation code. This should be replaced in the next version by
  1649. // the correct version of this code. It is suppose to read a multi-
  1650. // language file and pick up the correct version according to
  1651. // the machine's lanaguage
  1652. //
  1653. #ifndef WIN16
  1654. WCHAR RgwchVerisign[] =
  1655. L"This certificate incorporates by reference, and its use is strictly subject "
  1656. L"to, the VeriSign Certification Practice Statement (CPS), available in the "
  1657. L"VeriSign repository at: https://www.verisign.com by E-mail at "
  1658. L"[email protected]; or by mail at VeriSign, Inc., 1390 Shorebird "
  1659. L"Way, Mountain View, CA 94043 USA Copyright (c)1997 VeriSign, Inc. All "
  1660. L"Rights Reserved. CERTAIN WARRANTIES DISCLAIMED AND LIABILITY LIMITED.\n"
  1661. L"\n"
  1662. L"WARNING: USE OF THIS CERTIFICATE IS STRICTLY SUBJECT TO THE VERISIGN "
  1663. L"CERTIFICATION PRACTICE STATEMENT. THE ISSUING AUTHORITY DISCLAIMS CERTAIN "
  1664. L"IMPLIED AND EXPRESS WARRANTIES, INCLUDING WARRANTIES OF MERCHANTABILITY OR "
  1665. L"FITNESS FOR A PARTICULAR PURPOSE, AND WILL NOT BE LIABLE FOR CONSEQUENTIAL, "
  1666. L"PUNITIVE, AND CERTAIN OTHER DAMAGES. SEE THE CPS FOR DETAILS.\n"
  1667. L"\n"
  1668. L"Contents of the VeriSign registered nonverifiedSubjectAttribute extension "
  1669. L"value shall not be considered as information confirmed by the IA.";
  1670. #else
  1671. WCHAR RgwchVerisign[] =
  1672. "This certificate incorporates by reference, and its use is strictly subject "
  1673. "to, the VeriSign Certification Practice Statement (CPS), available in the "
  1674. "VeriSign repository at: https://www.verisign.com; by E-mail at "
  1675. "[email protected]; or by mail at VeriSign, Inc., 1390 Shorebird "
  1676. "Way, Mountain View, CA 94043 USA Copyright (c)1997 VeriSign, Inc. All "
  1677. "Rights Reserved. CERTAIN WARRANTIES DISCLAIMED AND LIABILITY LIMITED.\n"
  1678. "\n"
  1679. "WARNING: USE OF THIS CERTIFICATE IS STRICTLY SUBJECT TO THE VERISIGN "
  1680. "CERTIFICATION PRACTICE STATEMENT. THE ISSUING AUTHORITY DISCLAIMS CERTAIN "
  1681. "IMPLIED AND EXPRESS WARRANTIES, INCLUDING WARRANTIES OF MERCHANTABILITY OR "
  1682. "FITNESS FOR A PARTICULAR PURPOSE, AND WILL NOT BE LIABLE FOR CONSEQUENTIAL, "
  1683. "PUNITIVE, AND CERTAIN OTHER DAMAGES. SEE THE CPS FOR DETAILS.\n"
  1684. "\n"
  1685. "Contents of the VeriSign registered nonverifiedSubjectAttribute extension "
  1686. "value shall not be considered as information confirmed by the IA.";
  1687. #endif // !WIN16
  1688. BOOL WINAPI FormatVerisignExtension(
  1689. DWORD /*dwCertEncodingType*/, DWORD /*dwFormatType*/, DWORD /*dwFormatStrType*/,
  1690. void * /*pFormatStruct*/, LPCSTR /*lpszStructType*/, const BYTE * /*pbEncoded*/,
  1691. DWORD /*cbEncoded*/, void * pbFormat, DWORD * pcbFormat)
  1692. {
  1693. if (pbFormat == NULL) {
  1694. *pcbFormat = sizeof(RgwchVerisign);
  1695. return TRUE;
  1696. }
  1697. if (*pcbFormat < sizeof(RgwchVerisign)) {
  1698. *pcbFormat = sizeof(RgwchVerisign);
  1699. return FALSE;
  1700. }
  1701. memcpy(pbFormat, RgwchVerisign, sizeof(RgwchVerisign));
  1702. return TRUE;
  1703. }
  1704. BOOL WINAPI FormatPKIXEmailProtection(
  1705. DWORD /*dwCertEncodingType*/, DWORD /*dwFormatType*/, DWORD /*dwFormatStrType*/,
  1706. void * /*pFormatStruct*/, LPCSTR /*lpszStructType*/, const BYTE * /*pbEncoded*/,
  1707. DWORD /*cbEncoded*/, void * pbFormat, DWORD * pcbFormat)
  1708. {
  1709. DWORD cch;
  1710. WCHAR rgwch[256];
  1711. cch = LoadString(HinstDll, IDS_EMAIL_DESC, rgwch, sizeof(rgwch)/sizeof(WCHAR));
  1712. if (pbFormat == NULL) {
  1713. *pcbFormat = (cch+1)*sizeof(WCHAR);
  1714. return TRUE;
  1715. }
  1716. if (*pcbFormat < (cch+1)*sizeof(WCHAR)) {
  1717. *pcbFormat = (cch+1)*sizeof(WCHAR);
  1718. return FALSE;
  1719. }
  1720. memcpy(pbFormat, rgwch, (cch+1)*sizeof(WCHAR));
  1721. return TRUE;
  1722. }
  1723. /////////////////////////////////////////////////////////////////////////////
  1724. //
  1725. // This is an encoder which should really be in crypt32 -- however I don't
  1726. // want to force a drop of crypt32 just to get it.
  1727. //
  1728. BOOL WINAPI
  1729. EncodeAttrSequence(DWORD /*dwType*/, LPCSTR /*lpszStructType*/,
  1730. const void * pv, LPBYTE pbEncode, DWORD * pcbEncode)
  1731. {
  1732. DWORD cb;
  1733. DWORD dw;
  1734. BOOL fRet;
  1735. DWORD i;
  1736. PCRYPT_ATTRIBUTES pattrs = (PCRYPT_ATTRIBUTES) pv;
  1737. LPBYTE pb = NULL;
  1738. CRYPT_SEQUENCE_OF_ANY seq = {0};
  1739. UNALIGNED void * pAttr = NULL;
  1740. //
  1741. // Allocate something to hold the result of each attribute's encoding
  1742. //
  1743. seq.rgValue = (PCRYPT_DER_BLOB) malloc(pattrs->cAttr *
  1744. sizeof(CRYPT_DER_BLOB));
  1745. if (seq.rgValue == NULL) {
  1746. dw = ERROR_NOT_ENOUGH_MEMORY;
  1747. goto ErrorExit;
  1748. }
  1749. //
  1750. // Now encode each of the attributes in turn
  1751. //
  1752. for (i=0; i<pattrs->cAttr; i++) {
  1753. pAttr =((UNALIGNED void *) &(pattrs->rgAttr[i]));
  1754. if (!CryptEncodeObject(X509_ASN_ENCODING, PKCS_ATTRIBUTE,
  1755. pAttr, NULL, &cb) || (cb == 0)) {
  1756. fRet = FALSE;
  1757. goto Clean;
  1758. }
  1759. pb = (LPBYTE) malloc(LcbAlignLcb(cb));
  1760. if (!CryptEncodeObject(X509_ASN_ENCODING, PKCS_ATTRIBUTE,
  1761. pAttr, pb, &cb)) {
  1762. fRet = FALSE;
  1763. goto Clean;
  1764. }
  1765. seq.cValue = i+1;
  1766. seq.rgValue[i].cbData = cb;
  1767. seq.rgValue[i].pbData = pb;
  1768. pb = NULL;
  1769. }
  1770. //
  1771. // Now lets encode the sequence
  1772. //
  1773. fRet = CryptEncodeObject(X509_ASN_ENCODING, X509_SEQUENCE_OF_ANY,
  1774. &seq, pbEncode, pcbEncode);
  1775. Clean:
  1776. for (i=0; i<seq.cValue; i++) free(seq.rgValue[i].pbData);
  1777. if (seq.rgValue != NULL) free(seq.rgValue);
  1778. if (pb != NULL) free(pb);
  1779. return fRet;
  1780. ErrorExit:
  1781. SetLastError(dw);
  1782. fRet = FALSE;
  1783. goto Clean;
  1784. }
  1785. BOOL WINAPI
  1786. DecodeAttrSequence(DWORD /*dwType*/, LPCSTR /*lpszStructType*/,
  1787. const BYTE * pbEncoded, DWORD cbEncoded,
  1788. DWORD /*dwFlags*/, void * pvStruct,
  1789. DWORD * pcbStruct)
  1790. {
  1791. DWORD cb;
  1792. DWORD cbMax = 0;
  1793. DWORD cbOut;
  1794. BOOL fRet = FALSE;
  1795. DWORD i;
  1796. DWORD i1;
  1797. PCRYPT_ATTRIBUTE pattr = NULL;
  1798. PCRYPT_ATTRIBUTES pattrs = (PCRYPT_ATTRIBUTES) pvStruct;
  1799. LPBYTE pbOut = NULL;
  1800. PCRYPT_SEQUENCE_OF_ANY pseq = NULL;
  1801. #ifdef _WIN64
  1802. UNALIGNED CRYPT_ATTR_BLOB *pVal = NULL;
  1803. #endif
  1804. //
  1805. // Decode the top level sequence
  1806. //
  1807. if (!CryptDecodeObject(X509_ASN_ENCODING, X509_SEQUENCE_OF_ANY,
  1808. pbEncoded, cbEncoded, 0, NULL, &cb)) {
  1809. goto Exit;
  1810. }
  1811. pseq = (PCRYPT_SEQUENCE_OF_ANY) malloc(cb);
  1812. if (pseq == NULL) {
  1813. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1814. goto Exit;
  1815. }
  1816. if (!CryptDecodeObject(X509_ASN_ENCODING, X509_SEQUENCE_OF_ANY,
  1817. pbEncoded, cbEncoded, 0, pseq, &cb)) {
  1818. goto Exit;
  1819. }
  1820. //
  1821. // Decode each attribute for length
  1822. //
  1823. cbOut = sizeof(CRYPT_ATTRIBUTES);
  1824. for (i=0; i<pseq->cValue; i++) {
  1825. if (!CryptDecodeObject(X509_ASN_ENCODING, PKCS_ATTRIBUTE,
  1826. pseq->rgValue[i].pbData,
  1827. pseq->rgValue[i].cbData, 0, NULL, &cb)) {
  1828. fRet = FALSE;
  1829. goto Exit;
  1830. }
  1831. cb = LcbAlignLcb(cb);
  1832. if (cb > cbMax) cbMax = cb;
  1833. cbOut += cb;
  1834. }
  1835. if (pvStruct == NULL) {
  1836. *pcbStruct = cbOut;
  1837. fRet = TRUE;
  1838. goto Exit;
  1839. }
  1840. if (*pcbStruct < cbOut) {
  1841. *pcbStruct = cbOut;
  1842. SetLastError(ERROR_MORE_DATA);
  1843. goto Exit;
  1844. }
  1845. //
  1846. // Now we are going to actually try and compute the real data.
  1847. //
  1848. // First we need a buffer to put each attribute in as we are looking at it
  1849. //
  1850. pattr = (PCRYPT_ATTRIBUTE) malloc(LcbAlignLcb(cbMax));
  1851. if (pattr == NULL) {
  1852. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1853. goto Exit;
  1854. }
  1855. pattrs->cAttr = pseq->cValue;
  1856. pattrs->rgAttr = (PCRYPT_ATTRIBUTE) (((LPBYTE) pvStruct) +
  1857. sizeof(CRYPT_ATTRIBUTES));
  1858. pbOut = ((LPBYTE) pvStruct + LcbAlignLcb(sizeof(CRYPT_ATTRIBUTES) +
  1859. pseq->cValue * sizeof(CRYPT_ATTRIBUTE)));
  1860. for (i=0; i<pseq->cValue; i++) {
  1861. //
  1862. // Decode one attribute
  1863. //
  1864. cb = cbMax;
  1865. if (!CryptDecodeObject(X509_ASN_ENCODING, PKCS_ATTRIBUTE,
  1866. pseq->rgValue[i].pbData, pseq->rgValue[i].cbData,
  1867. 0, pattr, &cb)) {
  1868. goto Exit;
  1869. }
  1870. //
  1871. // Copy to real output buffer
  1872. //
  1873. pattrs->rgAttr[i].pszObjId = (LPSTR) pbOut;
  1874. cb = lstrlenA(pattr->pszObjId) + 1;
  1875. memcpy(pbOut, pattr->pszObjId, cb);
  1876. pbOut += LcbAlignLcb(cb);
  1877. pattrs->rgAttr[i].cValue = pattr->cValue;
  1878. pattrs->rgAttr[i].rgValue = (PCRYPT_ATTR_BLOB) pbOut;
  1879. pbOut += LcbAlignLcb(sizeof(CRYPT_ATTR_BLOB) * pattr->cValue);
  1880. for (i1=0; i1<pattr->cValue; i1++) {
  1881. #ifndef _WIN64
  1882. pattrs->rgAttr[i].rgValue[i1].cbData = pattr->rgValue[i1].cbData;
  1883. pattrs->rgAttr[i].rgValue[i1].pbData = pbOut;
  1884. #else
  1885. pVal = &(pattrs->rgAttr[i].rgValue[i1]);
  1886. pVal->cbData = pattr->rgValue[i1].cbData;
  1887. pVal->pbData = pbOut;
  1888. #endif //_WIN64
  1889. memcpy(pbOut, pattr->rgValue[i1].pbData, pattr->rgValue[i1].cbData);
  1890. pbOut += LcbAlignLcb(pattr->rgValue[i1].cbData);
  1891. }
  1892. }
  1893. fRet = TRUE;
  1894. Exit:
  1895. if (pattr != NULL) free(pattr);
  1896. if (pseq != NULL) free(pseq);
  1897. return fRet;
  1898. }
  1899. // OIDs 1.3.6.1.4.1.311.16.4
  1900. BOOL WINAPI EncodeRecipientID(DWORD dwType, LPCSTR /*lpszStructType*/,
  1901. const void * pv, LPBYTE pbEncode,
  1902. DWORD * pcbEncode)
  1903. {
  1904. DWORD cbInt;
  1905. BOOL f;
  1906. LPBYTE pbInt = NULL;
  1907. CRYPT_RECIPIENT_ID * prid = (CRYPT_RECIPIENT_ID *) pv;
  1908. CRYPT_DER_BLOB rgValue[2];
  1909. CRYPT_SEQUENCE_OF_ANY seq = {0, rgValue};
  1910. if (prid->unused != 0) {
  1911. SetLastError(ERROR_INVALID_PARAMETER);
  1912. return FALSE;
  1913. }
  1914. f = CryptEncodeObject(dwType, X509_MULTI_BYTE_INTEGER,
  1915. &prid->SerialNumber, NULL, &cbInt);
  1916. if (!f) goto ExitHere;
  1917. pbInt = (LPBYTE) malloc(cbInt);
  1918. if (pbInt == NULL) {
  1919. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1920. f = FALSE;
  1921. goto ExitHere;
  1922. }
  1923. f = CryptEncodeObject(dwType, X509_MULTI_BYTE_INTEGER,
  1924. &prid->SerialNumber, pbInt, &cbInt);
  1925. seq.cValue = 2;
  1926. seq.rgValue[0].cbData = prid->Issuer.cbData;
  1927. seq.rgValue[0].pbData = prid->Issuer.pbData;
  1928. seq.rgValue[1].cbData = cbInt;
  1929. seq.rgValue[1].pbData = pbInt;
  1930. f = CryptEncodeObject(dwType, X509_SEQUENCE_OF_ANY, &seq,
  1931. pbEncode, pcbEncode);
  1932. ExitHere:
  1933. if (pbInt != NULL) free(pbInt);
  1934. return f;
  1935. }
  1936. BOOL WINAPI DecodeRecipientID(DWORD dwType, LPCSTR /*lpszStructType*/,
  1937. const BYTE * pbEncoded, DWORD cbEncoded,
  1938. DWORD dwFlags, void * pvStruct, DWORD * pcbStruct)
  1939. {
  1940. DWORD cb;
  1941. DWORD cbOut;
  1942. BOOL fRet = FALSE;
  1943. CRYPT_INTEGER_BLOB * pInt = NULL;
  1944. CRYPT_RECIPIENT_ID * prid = (CRYPT_RECIPIENT_ID *) pvStruct;
  1945. CRYPT_SEQUENCE_OF_ANY * pseq = NULL;
  1946. // Decode the top level sequence first
  1947. fRet = CryptDecodeObjectEx(dwType, X509_SEQUENCE_OF_ANY, pbEncoded,
  1948. cbEncoded, dwFlags | CRYPT_ENCODE_ALLOC_FLAG,
  1949. NULL, &pseq, &cb);
  1950. if (!fRet) {
  1951. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1952. goto Exit;
  1953. }
  1954. // Assert(pseq->cValue == 2);
  1955. // Decode integer
  1956. fRet = CryptDecodeObjectEx(dwType, X509_MULTI_BYTE_INTEGER,
  1957. pseq->rgValue[1].pbData, pseq->rgValue[1].cbData,
  1958. dwFlags | CRYPT_ENCODE_ALLOC_FLAG, NULL,
  1959. &pInt, &cb);
  1960. if (!fRet) {
  1961. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1962. goto Exit;
  1963. }
  1964. // Compute length needed for the return value
  1965. cbOut = (sizeof(CRYPT_RECIPIENT_ID) + pseq->rgValue[0].cbData +
  1966. pInt->cbData);
  1967. if ((*pcbStruct < cbOut) || (pvStruct == NULL)) {
  1968. *pcbStruct = cbOut;
  1969. SetLastError(ERROR_MORE_DATA);
  1970. fRet = (pvStruct == NULL);
  1971. goto Exit;
  1972. }
  1973. // Now copy the data over
  1974. prid->unused = 0;
  1975. prid->Issuer.cbData = pseq->rgValue[0].cbData;
  1976. prid->Issuer.pbData = sizeof(*prid) + (LPBYTE) prid;
  1977. memcpy(prid->Issuer.pbData, pseq->rgValue[0].pbData, prid->Issuer.cbData);
  1978. prid->SerialNumber.cbData = pInt->cbData;
  1979. prid->SerialNumber.pbData = prid->Issuer.pbData + prid->Issuer.cbData;
  1980. memcpy(prid->SerialNumber.pbData, pInt->pbData, pInt->cbData);
  1981. fRet = TRUE;
  1982. Exit:
  1983. if (pInt != NULL) LocalFree(pInt);
  1984. if (pseq != NULL) LocalFree(pseq);
  1985. return fRet;
  1986. }
  1987. ////////////////////////////////////////////////////////////////////////////
  1988. extern const GUID rgguidActions[] = {
  1989. CERT_CERTIFICATE_ACTION_VERIFY
  1990. };
  1991. #define REGSTR_PATH_SERVICES "System\\CurrentControlSet\\Services"
  1992. #ifdef NT5BUILD
  1993. #else // NT5BUILD
  1994. const char SzRegPath[] = REGSTR_PATH_SERVICES "\\WinTrust\\TrustProviders\\Email Trust";
  1995. const char SzActionIds[] = "$ActionIDs";
  1996. const char SzDllName[] = "$DLL";
  1997. #endif // !NT5BUILD
  1998. extern const GUID GuidCertValidate = CERT_CERTIFICATE_ACTION_VERIFY;
  1999. #ifndef MAC
  2000. STDAPI DllRegisterServer(void)
  2001. {
  2002. #ifdef NT5BUILD
  2003. HRESULT hr = S_OK;
  2004. #else // !NT5BUILD
  2005. DWORD dwDisposition;
  2006. HKEY hkey;
  2007. UINT cchSystemDir;
  2008. BOOL fIsWinNt = FALSE; // M00BUG
  2009. HRESULT hr = S_OK;
  2010. LPSTR psz;
  2011. CHAR rgchLibName[] = "cryptdlg.dll";
  2012. CHAR rgchPathName[MAX_PATH + sizeof(rgchLibName)];
  2013. #endif // NT5BUILD
  2014. //
  2015. // First we register the funny one time function which is currently
  2016. // hard-coded to go to a fixed verisign statement. This should be removed
  2017. // if we can get a general purpose one running.
  2018. //
  2019. #ifndef WIN16
  2020. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2021. CRYPT_OID_FORMAT_OBJECT_FUNC,
  2022. "2.5.29.32",
  2023. L"cryptdlg.dll",
  2024. "FormatVerisignExtension")) {
  2025. return E_FAIL;
  2026. }
  2027. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2028. CRYPT_OID_FORMAT_OBJECT_FUNC,
  2029. szOID_PKIX_KP_EMAIL_PROTECTION,
  2030. L"cryptdlg.dll",
  2031. "FormatPKIXEmailProtection")) {
  2032. return E_FAIL;
  2033. }
  2034. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2035. CRYPT_OID_ENCODE_OBJECT_FUNC,
  2036. "1.3.6.1.4.1.311.16.1.1",
  2037. L"cryptdlg.dll",
  2038. "EncodeAttrSequence")) {
  2039. return E_FAIL;
  2040. }
  2041. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2042. CRYPT_OID_DECODE_OBJECT_FUNC,
  2043. "1.3.6.1.4.1.311.16.1.1",
  2044. L"cryptdlg.dll",
  2045. "DecodeAttrSequence")) {
  2046. return E_FAIL;
  2047. }
  2048. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2049. CRYPT_OID_ENCODE_OBJECT_FUNC,
  2050. szOID_MICROSOFT_Encryption_Key_Preference,
  2051. L"cryptdlg.dll", "EncodeRecipientID")) {
  2052. return E_FAIL;
  2053. }
  2054. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2055. CRYPT_OID_DECODE_OBJECT_FUNC,
  2056. szOID_MICROSOFT_Encryption_Key_Preference,
  2057. L"cryptdlg.dll", "DecodeRecipientID")) {
  2058. return E_FAIL;
  2059. }
  2060. #else
  2061. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2062. CRYPT_OID_FORMAT_OBJECT_FUNC,
  2063. "2.5.29.32",
  2064. "cryptdlg.dll",
  2065. "FormatVerisignExtension")) {
  2066. return E_FAIL;
  2067. }
  2068. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2069. CRYPT_OID_FORMAT_OBJECT_FUNC,
  2070. szOID_PKIX_KP_EMAIL_PROTECTION,
  2071. "cryptdlg.dll",
  2072. "FormatPKIXEmailProtection")) {
  2073. return E_FAIL;
  2074. }
  2075. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2076. CRYPT_OID_ENCODE_OBJECT_FUNC,
  2077. "1.3.6.1.4.1.311.16.1.1",
  2078. "cryptdlg.dll",
  2079. "EncodeAttrSequence")) {
  2080. return E_FAIL;
  2081. }
  2082. if (!CryptRegisterOIDFunction(X509_ASN_ENCODING,
  2083. CRYPT_OID_DECODE_OBJECT_FUNC,
  2084. "1.3.6.1.4.1.311.16.1.1",
  2085. "cryptdlg.dll",
  2086. "DecodeAttrSequence")) {
  2087. return E_FAIL;
  2088. }
  2089. #endif // !WIN16
  2090. #ifdef NT5BUILD
  2091. CRYPT_REGISTER_ACTIONID regdata;
  2092. regdata.cbStruct = sizeof(regdata);
  2093. regdata.sInitProvider.cbStruct = sizeof(regdata.sInitProvider);
  2094. regdata.sInitProvider.pwszDLLName = L"Cryptdlg.dll";
  2095. regdata.sInitProvider.pwszFunctionName = L"CertTrustInit";
  2096. regdata.sObjectProvider.cbStruct = sizeof(regdata.sObjectProvider);
  2097. regdata.sObjectProvider.pwszDLLName = NULL;
  2098. regdata.sObjectProvider.pwszFunctionName = NULL;
  2099. regdata.sSignatureProvider.cbStruct = sizeof(regdata.sSignatureProvider);
  2100. regdata.sSignatureProvider.pwszDLLName = NULL;
  2101. regdata.sSignatureProvider.pwszFunctionName = NULL;
  2102. regdata.sCertificateProvider.cbStruct = sizeof(regdata.sCertificateProvider);
  2103. regdata.sCertificateProvider.pwszDLLName = WT_PROVIDER_DLL_NAME;
  2104. regdata.sCertificateProvider.pwszFunctionName = WT_PROVIDER_CERTTRUST_FUNCTION;
  2105. regdata.sCertificatePolicyProvider.cbStruct = sizeof(regdata.sCertificatePolicyProvider);
  2106. regdata.sCertificatePolicyProvider.pwszDLLName = L"Cryptdlg.dll";
  2107. regdata.sCertificatePolicyProvider.pwszFunctionName = L"CertTrustCertPolicy";
  2108. regdata.sFinalPolicyProvider.cbStruct = sizeof(regdata.sFinalPolicyProvider);
  2109. regdata.sFinalPolicyProvider.pwszDLLName = L"Cryptdlg.dll";
  2110. regdata.sFinalPolicyProvider.pwszFunctionName = L"CertTrustFinalPolicy";
  2111. regdata.sTestPolicyProvider.cbStruct = sizeof(regdata.sTestPolicyProvider);
  2112. regdata.sTestPolicyProvider.pwszDLLName = NULL;
  2113. regdata.sTestPolicyProvider.pwszFunctionName = NULL;
  2114. regdata.sCleanupProvider.cbStruct = sizeof(regdata.sCleanupProvider);
  2115. regdata.sCleanupProvider.pwszDLLName = L"Cryptdlg.dll";
  2116. regdata.sCleanupProvider.pwszFunctionName = L"CertTrustCleanup";
  2117. WintrustAddActionID((GUID *) &GuidCertValidate, 0, &regdata);
  2118. #else // !NT5BUILD
  2119. //
  2120. // Next register the fact that we are also a wintrust provider for
  2121. // validating certificates
  2122. //
  2123. hr = RegCreateKeyExA(HKEY_LOCAL_MACHINE, SzRegPath, 0, NULL,
  2124. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
  2125. &hkey, &dwDisposition);
  2126. if (hr != ERROR_SUCCESS) {
  2127. goto RetHere;
  2128. }
  2129. // BUGBUG Win95 does not support REG_EXPAND_SZ, so we must do it
  2130. if (fIsWinNt) {
  2131. psz = "%SystemRoot%\\system32\\cryptdlg.dll";
  2132. }
  2133. else {
  2134. // Compose the path as <system_dir>\cryptdlg.dll
  2135. #ifndef WIN16
  2136. cchSystemDir = GetSystemDirectoryA(rgchPathName, MAX_PATH);
  2137. #else
  2138. cchSystemDir = GetSystemDirectory(rgchPathName, MAX_PATH);
  2139. #endif // !WIN16
  2140. if (cchSystemDir == 0) {
  2141. hr = E_FAIL;
  2142. goto RetHere;
  2143. }
  2144. else if (cchSystemDir > MAX_PATH) {
  2145. hr = ERROR_INSUFFICIENT_BUFFER;
  2146. goto RetHere;
  2147. }
  2148. rgchPathName[cchSystemDir] = '\\'; // system dir can't be a root
  2149. StrCpyN(&rgchPathName[cchSystemDir+1], rgchLibName, ARRAYSIZE(rgchPathName)-(cchSystemDir+1));
  2150. psz = rgchPathName;
  2151. }
  2152. #ifndef WIN16
  2153. hr = RegSetValueExA(hkey, SzDllName, 0, fIsWinNt ? REG_EXPAND_SZ : REG_SZ,
  2154. (LPBYTE) psz, strlen(psz)+1);
  2155. #else
  2156. hr = RegSetValueExA(hkey, SzDllName, 0, REG_SZ, (LPBYTE) psz, strlen(psz)+1);
  2157. #endif // !WIN16
  2158. if (hr != ERROR_SUCCESS) {
  2159. goto RetHere;
  2160. }
  2161. hr = RegSetValueExA(hkey, SzActionIds, 0, REG_BINARY,
  2162. (LPBYTE) rgguidActions, sizeof(rgguidActions));
  2163. if (hr != ERROR_SUCCESS) {
  2164. goto RetHere;
  2165. }
  2166. RetHere:
  2167. // NB - Don't do RegCloseKey on these hkey's since we want to be small
  2168. // and this code is only ever called by REGSRV32.EXE, so we don't
  2169. // care about a minor leak.
  2170. #endif // NT5BUILD
  2171. return hr;
  2172. }
  2173. STDAPI DllUnregisterServer(void)
  2174. {
  2175. #ifndef NT5BUILD
  2176. DWORD dw;
  2177. HKEY hkey;
  2178. #endif // NT5BUILD
  2179. HRESULT hr = S_OK;
  2180. //
  2181. // Unregister the formatting routine we wrote
  2182. //
  2183. if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING,
  2184. CRYPT_OID_FORMAT_OBJECT_FUNC,
  2185. "2.5.29.32")) {
  2186. if (ERROR_FILE_NOT_FOUND != GetLastError()) {
  2187. hr = E_FAIL;
  2188. }
  2189. }
  2190. if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING,
  2191. CRYPT_OID_FORMAT_OBJECT_FUNC,
  2192. szOID_PKIX_KP_EMAIL_PROTECTION)) {
  2193. if (ERROR_FILE_NOT_FOUND != GetLastError()) {
  2194. hr = E_FAIL;
  2195. }
  2196. }
  2197. if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING,
  2198. CRYPT_OID_ENCODE_OBJECT_FUNC,
  2199. "1.3.6.1.4.1.311.16.1.1")) {
  2200. if (ERROR_FILE_NOT_FOUND != GetLastError()) {
  2201. hr = E_FAIL;
  2202. }
  2203. }
  2204. if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING,
  2205. CRYPT_OID_DECODE_OBJECT_FUNC,
  2206. "1.3.6.1.4.1.311.16.1.1")) {
  2207. if (ERROR_FILE_NOT_FOUND != GetLastError()) {
  2208. hr = E_FAIL;
  2209. }
  2210. }
  2211. if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING,
  2212. CRYPT_OID_ENCODE_OBJECT_FUNC,
  2213. szOID_MICROSOFT_Encryption_Key_Preference)) {
  2214. if (ERROR_FILE_NOT_FOUND != GetLastError()) {
  2215. hr = E_FAIL;
  2216. }
  2217. }
  2218. if (!CryptUnregisterOIDFunction(X509_ASN_ENCODING,
  2219. CRYPT_OID_DECODE_OBJECT_FUNC,
  2220. szOID_MICROSOFT_Encryption_Key_Preference)) {
  2221. if (ERROR_FILE_NOT_FOUND != GetLastError()) {
  2222. hr = E_FAIL;
  2223. }
  2224. }
  2225. #ifdef NT5BUILD
  2226. WintrustRemoveActionID((GUID *) &GuidCertValidate);
  2227. #else // !NT5BUILD
  2228. //
  2229. // Now unregister the WinTrust provider
  2230. //
  2231. hr = RegCreateKeyExA(HKEY_LOCAL_MACHINE, SzRegPath, 0, NULL,
  2232. REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dw);
  2233. if (FAILED(hr)) {
  2234. goto RetHere;
  2235. }
  2236. RegDeleteValueA(hkey, SzDllName);
  2237. RegDeleteValueA(hkey, SzActionIds);
  2238. RetHere:
  2239. // NB - Don't do RegCloseKey on these hkey's since we want to be small
  2240. // and this code is only ever called by REGSRV32.EXE, so we don't
  2241. // care about a minor leak.
  2242. #endif // NT5BUILD
  2243. return hr;
  2244. }
  2245. #else // MAC
  2246. /***
  2247. *wchar_t *wcsstr(string1, string2) - search for string2 in string1
  2248. * (wide strings)
  2249. *
  2250. *Purpose:
  2251. * finds the first occurrence of string2 in string1 (wide strings)
  2252. *
  2253. *Entry:
  2254. * wchar_t *string1 - string to search in
  2255. * wchar_t *string2 - string to search for
  2256. *
  2257. *Exit:
  2258. * returns a pointer to the first occurrence of string2 in
  2259. * string1, or NULL if string2 does not occur in string1
  2260. *
  2261. *Uses:
  2262. *
  2263. *Exceptions:
  2264. *
  2265. *******************************************************************************/
  2266. wchar_t * __cdecl WchCryptDlgWcsStr (
  2267. const wchar_t * wcs1,
  2268. const wchar_t * wcs2
  2269. )
  2270. {
  2271. wchar_t *cp = (wchar_t *) wcs1;
  2272. wchar_t *s1, *s2;
  2273. while (*cp)
  2274. {
  2275. s1 = cp;
  2276. s2 = (wchar_t *) wcs2;
  2277. while ( *s1 && *s2 && !(*s1-*s2) )
  2278. s1++, s2++;
  2279. if (!*s2)
  2280. return(cp);
  2281. cp++;
  2282. }
  2283. return(NULL);
  2284. }
  2285. #endif // !MAC
  2286. ///////////////////////////////////////////////////////////////////////
  2287. LPVOID PVCryptDecode(LPCSTR szOid, DWORD cbEncode, LPBYTE pbEncode)
  2288. {
  2289. DWORD cbData;
  2290. BOOL f;
  2291. LPVOID pv;
  2292. f = CryptDecodeObject(X509_ASN_ENCODING, szOid, pbEncode, cbEncode,
  2293. 0, NULL, &cbData);
  2294. if (!f) {
  2295. return NULL;
  2296. }
  2297. pv = malloc(cbData);
  2298. if (pv == NULL) {
  2299. return NULL;
  2300. }
  2301. f = CryptDecodeObject(X509_ASN_ENCODING, szOid, pbEncode, cbEncode,
  2302. 0, pv, &cbData);
  2303. if (!f) {
  2304. free(pv);
  2305. return NULL;
  2306. }
  2307. return pv;
  2308. }
  2309. void * __cdecl operator new(size_t cb )
  2310. {
  2311. LPVOID lpv = 0;
  2312. lpv = malloc(cb);
  2313. if (lpv)
  2314. {
  2315. memset(lpv, 0, cb);
  2316. }
  2317. return lpv;
  2318. }
  2319. void __cdecl operator delete(LPVOID pv )
  2320. {
  2321. free(pv);
  2322. }