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.

3320 lines
94 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: transapi.cxx
  7. //
  8. // Contents: API's for internal use
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 4-26-96 JohannP (Johann Posch) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <trans.h>
  18. #include "oinet.hxx"
  19. #include <shlwapi.h>
  20. #include <shlwapip.h>
  21. #include <winineti.h>
  22. #include "datasnif.hxx"
  23. #include <winver.h>
  24. #include <mshtml.h>
  25. PerfDbgTag(tagTransApi, "Urlmon", "Log Trans API", DEB_DATA);
  26. static char szMimeKey[] = "MIME\\Database\\Content Type\\";
  27. const ULONG ulMimeKeyLen = ((sizeof(szMimeKey)/sizeof(char))-1);
  28. LPCSTR pszDocObject = "DocObject";
  29. LPCSTR pszInprocServer = "InprocServer32";
  30. LPCSTR pszLocalServer = "LocalServer32";
  31. #define INTERNET_SETTING_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
  32. extern LPSTR g_pszUserAgentString;
  33. extern BYTE g_bShortcircuitKnownProtocols;
  34. HMODULE g_hLibPluginOcx = NULL;
  35. HRESULT GetClassDocFileBuffer(LPVOID pbuffer, DWORD dwSize, CLSID *pclsid);
  36. // borrow from urlmon\download to check if Doc Object handler is installed
  37. // need CLocalComponentInfo & IsControlLocallyInstalled
  38. #ifndef unix
  39. #include "..\download\cdl.h"
  40. #else
  41. #include "../download/cdl.h"
  42. #endif /* unix */
  43. // DocFile properties and constants for extracting CodeBase property
  44. #define DOCFILE_NUMPROPERTIES 3
  45. #define DOCFILE_PROPID_CODEBASE 3
  46. #define DOCFILE_PROPID_MAJORVERSION 4
  47. #define DOCFILE_PROPID_MINORVERSION 5
  48. //
  49. // this new apis should be made public
  50. //
  51. STDAPI URLDownloadW(IUnknown *pUnk, LPCWSTR pwzURL, DWORD pBindInfo, IBindStatusCallback *pBSCB, DWORD dwReserved);
  52. STDAPI URLDownloadA(IUnknown *pUnk, LPCSTR pszURL, DWORD pBindInfo, IBindStatusCallback *pBSCB, DWORD dwReserved);
  53. #define CF_INGNORE_SLASH 0x00000001 //ignore slash when comparing urls
  54. typedef enum tagCLSCTXEX
  55. {
  56. /*
  57. // ole default class context values
  58. CLSCTX_INPROC_SERVER = 0x0001,
  59. CLSCTX_INPROC_HANDLER = 0x0002,
  60. CLSCTX_LOCAL_SERVER = 0x0004,
  61. CLSCTX_INPROC_SERVER16 = 0x0008,
  62. CLSCTX_REMOTE_SERVER = 0x0010,
  63. CLSCTX_INPROC_HANDLER16 = 0x0020,
  64. CLSCTX_INPROC_SERVERX86 = 0x0040,
  65. CLSCTX_INPROC_HANDLERX86 = 0x0080
  66. */
  67. // new class context values used in GetClassFileOrMime
  68. CLSCTX_INPROC_DOCOBJECT = 0x0100,
  69. CLSCTX_LOCAL_DOCOBJECT = 0x0200,
  70. CLSCTX_INPROC_CONTROL = 0x0400,
  71. CLSCTX_INPROC_X_CONTROL = 0x0800,
  72. CLSCTX_INPROC_PLUGIN = 0x1000
  73. } CLSCTXEX;
  74. #define CLSCTX_DOCOBJECT (CLSCTX_INPROC_DOCOBJECT|CLSCTX_LOCAL_DOCOBJECT)
  75. const GUID CLSID_PluginHost =
  76. {
  77. 0x25336921, 0x03F9, 0x11cf, {0x8F, 0xD0, 0x00, 0xAA, 0x00, 0x68, 0x6F, 0x13}
  78. };
  79. const GUID CLSID_MsHtml =
  80. {
  81. 0x25336920, 0x03F9, 0x11cf, {0x8F, 0xD0, 0x00, 0xAA, 0x00, 0x68, 0x6F, 0x13}
  82. };
  83. const GUID FMTID_CodeBase =
  84. {
  85. 0xfe2d9191, 0x7fba, 0x11d0, {0xb3, 0xc2, 0x00, 0xa0, 0xc9, 0x0a, 0xea, 0x82}
  86. };
  87. //+---------------------------------------------------------------------------
  88. //
  89. // Function: GetClsIDInfo
  90. //
  91. // Synopsis:
  92. //
  93. // Arguments: [pclsid] -- class id
  94. // [ClsCtxIn] -- unused
  95. // [pClsCtx] -- class context of class passed in
  96. //
  97. // Returns: S_OK on success
  98. // E_OUTOFMEMORY
  99. // E_FAIL
  100. //
  101. // History: 7-20-96 JohannP (Johann Posch) Created
  102. //
  103. // Notes:
  104. //
  105. //----------------------------------------------------------------------------
  106. HRESULT GetClsIDInfo(CLSID *pclsid, DWORD ClsCtxIn, DWORD *pClsCtx)
  107. {
  108. DEBUG_ENTER((DBG_TRANSDAT,
  109. Hresult,
  110. "GetClsIDInfo",
  111. "%#x, %#x, %#x",
  112. pclsid, ClsCtxIn, pClsCtx
  113. ));
  114. PerfDbgLog(tagTransApi, NULL, "+GetClsIDInfo");
  115. HRESULT hr = E_FAIL;
  116. TransAssert(( pClsCtx && pclsid && !IsEqualGUID(*pclsid, CLSID_NULL) ));
  117. LPSTR pszCls = StringAFromCLSID(pclsid);
  118. if (!pszCls)
  119. {
  120. hr = E_OUTOFMEMORY;
  121. *pClsCtx = 0;
  122. }
  123. else
  124. {
  125. CHAR szCLSID[CLSIDSTR_MAX + 8];
  126. HKEY hClsRegEntry;
  127. CHAR szValue[64];
  128. long lSize;
  129. DWORD dwClsCtx = 0;
  130. strcpy(szCLSID, "CLSID\\");
  131. strcat(szCLSID, pszCls);
  132. if (RegOpenKey(HKEY_CLASSES_ROOT, szCLSID, &hClsRegEntry) == ERROR_SUCCESS)
  133. {
  134. lSize = 64;
  135. HKEY hkeySrv32;
  136. if( RegOpenKey(hClsRegEntry, pszInprocServer, &hkeySrv32)
  137. == ERROR_SUCCESS)
  138. {
  139. dwClsCtx |= CLSCTX_INPROC;
  140. RegCloseKey(hkeySrv32);
  141. }
  142. lSize = 64;
  143. if (RegQueryValue(hClsRegEntry, pszLocalServer, szValue, &lSize) == ERROR_SUCCESS)
  144. {
  145. dwClsCtx |= CLSCTX_LOCAL_SERVER;
  146. }
  147. lSize = 64;
  148. if (RegQueryValue(hClsRegEntry, pszDocObject, szValue, &lSize) == ERROR_SUCCESS)
  149. {
  150. dwClsCtx |= CLSCTX_INPROC_DOCOBJECT;
  151. }
  152. RegCloseKey(hClsRegEntry);
  153. }
  154. if (dwClsCtx)
  155. {
  156. hr = S_OK;
  157. *pClsCtx = dwClsCtx;
  158. }
  159. delete pszCls;
  160. }
  161. PerfDbgLog1(tagTransApi, NULL, "-GetClsIDInfo (hr:%lx)", hr);
  162. DEBUG_LEAVE(hr);
  163. return hr;
  164. }
  165. //+---------------------------------------------------------------------------
  166. //
  167. // Function: FindFileExtension
  168. //
  169. // Synopsis:
  170. //
  171. // Arguments: [pszFileName] --
  172. //
  173. // Returns:
  174. //
  175. // History: 2-09-96 JohannP (Johann Posch) Created
  176. //
  177. // Notes:
  178. //
  179. //----------------------------------------------------------------------------
  180. LPSTR FindFileExtension(LPSTR pszFileName)
  181. {
  182. DEBUG_ENTER((DBG_TRANSDAT,
  183. String,
  184. "FindFileExtension",
  185. "%.80q",
  186. pszFileName
  187. ));
  188. PerfDbgLog1(tagTransApi, NULL, "+FindFileExtension (szFileName:%s)", pszFileName);
  189. LPSTR pStr = NULL;
  190. if (pszFileName)
  191. {
  192. LPSTR lpF = pszFileName + strlen(pszFileName);
  193. if (lpF)
  194. {
  195. while (lpF >= pszFileName)
  196. {
  197. if (*lpF=='.')
  198. {
  199. pStr = lpF;
  200. break;
  201. }
  202. if (*lpF=='/')
  203. {
  204. break;
  205. }
  206. lpF--;
  207. }
  208. }
  209. }
  210. PerfDbgLog1(tagTransApi, NULL, "-FindFileExtension (pStr:%s)", pStr);
  211. DEBUG_LEAVE(pStr);
  212. return pStr;
  213. }
  214. //+---------------------------------------------------------------------------
  215. //
  216. // Function: IsDocFile
  217. //
  218. // Synopsis:
  219. //
  220. // Arguments: [pBuffer] --
  221. //
  222. // Returns: S_OK buffer is begin of docfile
  223. // S_FALSE not begin of docfile
  224. // E_INVALIDARG arguments incorrect
  225. //
  226. // History: 2-09-96 JohannP (Johann Posch) Created
  227. //
  228. // Notes:
  229. //
  230. //----------------------------------------------------------------------------
  231. HRESULT IsDocFile(LPVOID pBuffer, DWORD cbSize)
  232. {
  233. DEBUG_ENTER((DBG_TRANSDAT,
  234. Hresult,
  235. "IsDocFile",
  236. "%#x, %#x",
  237. pBuffer, cbSize
  238. ));
  239. PerfDbgLog(tagTransApi, NULL, "+IsDocFile");
  240. HRESULT hr;
  241. // The byte combination that identifies that a file is a storage of
  242. // some kind
  243. BYTE SIGSTG[] = {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1};
  244. BYTE CBSIGSTG = sizeof(SIGSTG);
  245. TransAssert(((pBuffer != NULL) && (cbSize != 0) ));
  246. if (!pBuffer || (cbSize == 0))
  247. {
  248. hr = E_INVALIDARG;
  249. }
  250. else
  251. {
  252. hr = (!memcmp(pBuffer, SIGSTG, CBSIGSTG)) ? S_OK : S_FALSE;
  253. }
  254. PerfDbgLog1(tagTransApi, NULL, "-IsDocFile (hr:%lx)", hr);
  255. DEBUG_LEAVE(hr);
  256. return hr;
  257. }
  258. //+---------------------------------------------------------------------------
  259. //
  260. // Function: GetMimeFromExt
  261. //
  262. // Synopsis:
  263. //
  264. // Arguments: [pszExt] --
  265. // [pszMime] --
  266. // [cbMime] --
  267. //
  268. // Returns:
  269. //
  270. // History: 4-23-96 JohannP (Johann Posch) Created
  271. //
  272. // Notes:
  273. //
  274. //----------------------------------------------------------------------------
  275. HRESULT GetMimeFromExt(LPSTR pszExt, LPSTR pszMime, DWORD *pcbMime)
  276. {
  277. DEBUG_ENTER((DBG_TRANSDAT,
  278. Hresult,
  279. "GetMimeFromExt",
  280. "%.80q, %.80q, %#x",
  281. pszExt, pszMime, pcbMime
  282. ));
  283. PerfDbgLog1(tagTransApi, NULL, "+GetMimeFromExt (szExt:%s)", pszExt);
  284. HRESULT hr = E_FAIL;
  285. *pszMime = '\0';
  286. TransAssert((pszExt[0] == '.'));
  287. // the entry begins with '.' so it may be a file extension
  288. // query the value (which is the ProgID)
  289. HKEY hMimeKey = NULL;
  290. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, pszExt, 0, KEY_QUERY_VALUE, &hMimeKey) == ERROR_SUCCESS)
  291. {
  292. DWORD dwType = 1;
  293. if (RegQueryValueEx(hMimeKey, szContent, NULL, &dwType, (LPBYTE)pszMime, pcbMime) == ERROR_SUCCESS)
  294. {
  295. hr = NOERROR;
  296. }
  297. RegCloseKey(hMimeKey);
  298. }
  299. PerfDbgLog2(tagTransApi, NULL, "-GetMimeFromExt (pszMime:%s, hr:%lx)", pszMime, hr);
  300. DEBUG_LEAVE(hr);
  301. return hr;
  302. }
  303. //+---------------------------------------------------------------------------
  304. //
  305. // Function: GetMimeFileExtension
  306. //
  307. // Synopsis:
  308. //
  309. // Arguments: [pszMime] --
  310. // [pclsid] --
  311. //
  312. // Returns:
  313. //
  314. // History: 2-22-96 JohannP (Johann Posch) Created
  315. //
  316. // Notes: BUGBUG: needs to be optimized!
  317. //
  318. //----------------------------------------------------------------------------
  319. HRESULT GetMimeFileExtension(LPSTR pszMime, LPSTR pszExt, DWORD cbSize)
  320. {
  321. DEBUG_ENTER((DBG_TRANSDAT,
  322. Hresult,
  323. "GetMimeFileExtension",
  324. "%.80q, %.80q, %#x",
  325. pszMime, pszExt, cbSize
  326. ));
  327. PerfDbgLog1(tagTransApi, NULL, "+GetMimeFileExtension (MimeStr:%s)", pszMime);
  328. HRESULT hr = REGDB_E_CLASSNOTREG;
  329. HKEY hMimeKey = NULL;
  330. DWORD dwError;
  331. DWORD dwType;
  332. char szValue[256];
  333. DWORD dwValueLen = 256;
  334. char szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
  335. if ((pszMime == 0) || (pszExt == 0))
  336. {
  337. hr = E_INVALIDARG;
  338. }
  339. else
  340. {
  341. *pszExt = 0;
  342. strcpy(szKey, szMimeKey);
  343. strncat(szKey,pszMime, SZMIMESIZE_MAX);
  344. switch (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey))
  345. {
  346. case ERROR_SUCCESS:
  347. hr = NOERROR;
  348. break;
  349. // win32 will return file not found instead of bad key
  350. case ERROR_FILE_NOT_FOUND:
  351. case ERROR_BADKEY:
  352. hr = REGDB_E_CLASSNOTREG;
  353. break;
  354. default:
  355. hr = REGDB_E_READREGDB;
  356. break;
  357. }
  358. if (hr == NOERROR)
  359. {
  360. dwValueLen = 256;
  361. dwError = RegQueryValueEx(hMimeKey
  362. , szExtension
  363. , NULL
  364. , &dwType
  365. , (LPBYTE)szValue
  366. , &dwValueLen);
  367. if ( (dwError == ERROR_SUCCESS)
  368. && pszExt
  369. && dwValueLen
  370. && (dwValueLen <= cbSize) )
  371. {
  372. StrNCpy(pszExt, szValue, dwValueLen);
  373. }
  374. }
  375. }
  376. if (hMimeKey)
  377. {
  378. RegCloseKey(hMimeKey);
  379. }
  380. PerfDbgLog2(tagTransApi, NULL, "-GetMimeFileExtension (hr:%lx, szExt:%s)", hr, pszExt);
  381. DEBUG_LEAVE(hr);
  382. return hr;
  383. }
  384. //+---------------------------------------------------------------------------
  385. //
  386. // Function: GetClassMime
  387. //
  388. // Synopsis:
  389. //
  390. // Arguments: [pszMime] --
  391. // [pclsid] --
  392. // [fIgnoreMimeClsid] --
  393. //
  394. // Returns:
  395. //
  396. // History: 2-07-96 JohannP (Johann Posch) Created
  397. //
  398. // Notes:
  399. //
  400. //----------------------------------------------------------------------------
  401. HRESULT GetClassMime(LPSTR pszMime, CLSID *pclsid, BOOL fIgnoreMimeClsid)
  402. {
  403. DEBUG_ENTER((DBG_TRANSDAT,
  404. Hresult,
  405. "GetClassMime",
  406. "%.80q, %#x, %B",
  407. pszMime, pclsid, fIgnoreMimeClsid
  408. ));
  409. PerfDbgLog1(tagTransApi, NULL, "+GetClassMime (MimeStr:%s)", pszMime);
  410. HRESULT hr = REGDB_E_CLASSNOTREG;
  411. DWORD dwFlags = (fIgnoreMimeClsid) ? MIMEFLAGS_IGNOREMIME_CLASSID: 0;
  412. HKEY hMimeKey = NULL;
  413. DWORD dwClsCtx;
  414. DWORD dwError;
  415. DWORD dwType;
  416. char szValue[256];
  417. DWORD dwValueLen = 256;
  418. char szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
  419. if ((pszMime == 0) || (*pszMime == 0))
  420. {
  421. hr = E_INVALIDARG;
  422. }
  423. else
  424. {
  425. strcpy(szKey, szMimeKey);
  426. strcat(szKey, pszMime);
  427. switch (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey))
  428. {
  429. case ERROR_SUCCESS:
  430. hr = NOERROR;
  431. break;
  432. // win32 will return file not found instead of bad key
  433. case ERROR_FILE_NOT_FOUND:
  434. case ERROR_BADKEY:
  435. hr = REGDB_E_CLASSNOTREG;
  436. break;
  437. default:
  438. hr = REGDB_E_READREGDB;
  439. break;
  440. }
  441. if (hr == NOERROR)
  442. {
  443. // if fIgnoreMimeClsid is set, ignore the CLSID entry
  444. // in the HKCR\MIME tree.
  445. if (!fIgnoreMimeClsid)
  446. {
  447. dwError = RegQueryValueEx(hMimeKey, szClassID, NULL
  448. , &dwType, (LPBYTE)szValue, &dwValueLen);
  449. hr = REGDB_E_CLASSNOTREG;
  450. if (dwError == ERROR_SUCCESS)
  451. {
  452. WCHAR sz[256];
  453. A2W(szValue,sz,256);
  454. hr = CLSIDFromString(sz, pclsid);
  455. }
  456. if (hr == NOERROR)
  457. {
  458. goto End;
  459. }
  460. }
  461. hr = REGDB_E_CLASSNOTREG;
  462. dwValueLen = 256;
  463. dwError = RegQueryValueEx(hMimeKey
  464. , szExtension
  465. , NULL
  466. , &dwType
  467. , (LPBYTE)szValue
  468. , &dwValueLen);
  469. if (dwError == ERROR_SUCCESS)
  470. {
  471. hr = GetClassFromExt(szValue,pclsid);
  472. //class still not known
  473. // try extension
  474. }
  475. }
  476. }
  477. End:
  478. if (hMimeKey)
  479. {
  480. RegCloseKey(hMimeKey);
  481. }
  482. PerfDbgLog1(tagTransApi, NULL, "-GetClassMime (hr:%lx)", hr);
  483. DEBUG_LEAVE(hr);
  484. return hr;
  485. }
  486. //+---------------------------------------------------------------------------
  487. //
  488. // Function: GetMimeFlags
  489. //
  490. // Synopsis:
  491. //
  492. // Arguments: [pszMime] --
  493. // [pdwFlags] --
  494. //
  495. // Returns:
  496. //
  497. // History: 2-07-96 JohannP (Johann Posch) Created
  498. //
  499. // Notes:
  500. //
  501. //----------------------------------------------------------------------------
  502. HRESULT GetMimeFlags(LPCWSTR pwzMime, DWORD *pdwFlags)
  503. {
  504. DEBUG_ENTER((DBG_TRANSDAT,
  505. Hresult,
  506. "GetMimeFlags",
  507. "%.80wq, %#x",
  508. pwzMime, pdwFlags
  509. ));
  510. TransDebugOut((DEB_DATA, "API _IN GetMimeFlags (MimeStr:%ws)\n", pwzMime));
  511. HRESULT hr = E_FAIL;
  512. HKEY hMimeKey = NULL;
  513. DWORD dwError;
  514. DWORD dwType;
  515. DWORD dwFlags = 0;
  516. char szValue[256];
  517. DWORD dwValueLen = 256;
  518. char szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
  519. if ((pwzMime == 0) || (*pwzMime == 0) || !pdwFlags)
  520. {
  521. hr = E_INVALIDARG;
  522. }
  523. else
  524. {
  525. strcpy(szKey, szMimeKey);
  526. W2A(pwzMime, szKey + ulMimeKeyLen, SZMIMESIZE_MAX);
  527. *pdwFlags = 0;
  528. switch (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey))
  529. {
  530. case ERROR_SUCCESS:
  531. hr = NOERROR;
  532. break;
  533. // win32 will return file not found instead of bad key
  534. case ERROR_FILE_NOT_FOUND:
  535. case ERROR_BADKEY:
  536. hr = REGDB_E_CLASSNOTREG;
  537. break;
  538. default:
  539. hr = REGDB_E_READREGDB;
  540. break;
  541. }
  542. if (hr == NOERROR)
  543. {
  544. dwValueLen = sizeof(DWORD);
  545. dwError = RegQueryValueEx(hMimeKey, szFlags, NULL
  546. , &dwType, (LPBYTE)&dwFlags, &dwValueLen);
  547. hr = E_FAIL;
  548. if (dwError == ERROR_SUCCESS)
  549. {
  550. *pdwFlags = dwFlags;
  551. hr = NOERROR;
  552. }
  553. }
  554. }
  555. if (hMimeKey)
  556. {
  557. RegCloseKey(hMimeKey);
  558. }
  559. TransDebugOut((DEB_DATA, "API OUT GetMimeFlags (DWFLAGS:%lx, hr:%lx)\n", dwFlags, hr));
  560. DEBUG_LEAVE(hr);
  561. return hr;
  562. }
  563. //+---------------------------------------------------------------------------
  564. //
  565. // Function: GetMimeInfo
  566. //
  567. // Synopsis:
  568. //
  569. // Arguments: [pszMime] --
  570. // [pclsid] --
  571. // [pdwFlags] --
  572. // [pdwMimeFlags] --
  573. //
  574. // Returns:
  575. //
  576. // History: 2-07-96 JohannP (Johann Posch) Created
  577. //
  578. // Notes:
  579. //
  580. //----------------------------------------------------------------------------
  581. HRESULT GetMimeInfo(LPSTR pszMime, CLSID *pclsid, DWORD dwFlags, DWORD *pdwMimeFlags)
  582. {
  583. DEBUG_ENTER((DBG_TRANSDAT,
  584. Hresult,
  585. "GetMimeInfo",
  586. "%.80q, %#x, %#x, %#x",
  587. pszMime, pclsid, dwFlags, pdwMimeFlags
  588. ));
  589. PerfDbgLog1(tagTransApi, NULL, "+GetMimeInfo (MimeStr:%s)", pszMime);
  590. HRESULT hr = REGDB_E_CLASSNOTREG;
  591. BOOL fIgnoreMimeClsid = (dwFlags & MIMEFLAGS_IGNOREMIME_CLASSID);
  592. HKEY hMimeKey = NULL;
  593. DWORD dwError;
  594. DWORD dwType;
  595. char szValue[256];
  596. DWORD dwValueLen = 256;
  597. char szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
  598. if ((pszMime == 0) || (*pszMime == 0))
  599. {
  600. hr = E_INVALIDARG;
  601. }
  602. else
  603. {
  604. strcpy(szKey, szMimeKey);
  605. strcat(szKey, pszMime);
  606. switch (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey))
  607. {
  608. case ERROR_SUCCESS:
  609. hr = NOERROR;
  610. break;
  611. // win32 will return file not found instead of bad key
  612. case ERROR_FILE_NOT_FOUND:
  613. case ERROR_BADKEY:
  614. hr = REGDB_E_CLASSNOTREG;
  615. break;
  616. default:
  617. hr = REGDB_E_READREGDB;
  618. break;
  619. }
  620. if (hr == NOERROR)
  621. {
  622. // if fIgnoreMimeClsid is set, ignore the CLSID entry
  623. // in the HKCR\MIME tree.
  624. if (!fIgnoreMimeClsid)
  625. {
  626. dwError = RegQueryValueEx(hMimeKey, szClassID, NULL
  627. , &dwType, (LPBYTE)szValue, &dwValueLen);
  628. hr = REGDB_E_CLASSNOTREG;
  629. if (dwError == ERROR_SUCCESS)
  630. {
  631. WCHAR sz[256];
  632. A2W(szValue,sz,256);
  633. hr = CLSIDFromString(sz, pclsid);
  634. }
  635. if (hr == NOERROR)
  636. {
  637. goto End;
  638. }
  639. }
  640. hr = REGDB_E_CLASSNOTREG;
  641. dwValueLen = 256;
  642. dwError = RegQueryValueEx(hMimeKey
  643. , szExtension
  644. , NULL
  645. , &dwType
  646. , (LPBYTE)szValue
  647. , &dwValueLen);
  648. if (dwError == ERROR_SUCCESS)
  649. {
  650. hr = GetClassFromExt(szValue,pclsid);
  651. }
  652. if (pdwMimeFlags)
  653. {
  654. DWORD dwFlags = 0;
  655. *pdwMimeFlags = 0;
  656. dwValueLen = sizeof(DWORD);
  657. dwError = RegQueryValueEx(hMimeKey, szFlags, NULL
  658. , &dwType, (LPBYTE)&dwFlags, &dwValueLen);
  659. if (dwError == ERROR_SUCCESS)
  660. {
  661. *pdwMimeFlags = dwFlags;
  662. }
  663. }
  664. }
  665. }
  666. End:
  667. if (hMimeKey)
  668. {
  669. RegCloseKey(hMimeKey);
  670. }
  671. PerfDbgLog1(tagTransApi, NULL, "-GetMimeInfo (hr:%lx)", hr);
  672. DEBUG_LEAVE(hr);
  673. return hr;
  674. }
  675. //+---------------------------------------------------------------------------
  676. //
  677. // Method: GetClassFromExt
  678. //
  679. // Synopsis:
  680. //
  681. // Arguments: [pszExt] --
  682. // [pclsid] --
  683. //
  684. // Returns:
  685. //
  686. // History: 2-07-96 JohannP (Johann Posch) Created
  687. //
  688. // Notes:
  689. //
  690. //----------------------------------------------------------------------------
  691. HRESULT GetClassFromExt(LPSTR pszExt, CLSID *pclsid)
  692. {
  693. DEBUG_ENTER((DBG_TRANSDAT,
  694. Hresult,
  695. "GetClassFromExt",
  696. "%.80q, %#x",
  697. pszExt, pclsid
  698. ));
  699. PerfDbgLog1(tagTransApi, NULL, "+GetClassFromExt (szExt:%s)", pszExt);
  700. HRESULT hr = REGDB_E_CLASSNOTREG;
  701. HKEY hkRoot = HKEY_CLASSES_ROOT;
  702. char szFileExt[MAX_PATH];
  703. DWORD cbFileExt = sizeof(szFileExt);
  704. *pclsid = CLSID_NULL;
  705. char szProgID[MAX_PATH];
  706. LONG cbProgID = sizeof(szProgID);
  707. if (pszExt[0] == '\0')
  708. {
  709. goto End;
  710. }
  711. strcpy(szFileExt,pszExt);
  712. TransAssert((szFileExt[0] == '.'));
  713. // the entry begins with '.' so it may be a file extension
  714. // query the value (which is the ProgID)
  715. if (RegQueryValue(hkRoot, szFileExt, szProgID, &cbProgID) == ERROR_SUCCESS)
  716. {
  717. // we got the value (ProgID), now query for the CLSID
  718. // string and convert it to a CLSID
  719. char szClsid[40];
  720. LONG cbClsid = sizeof(szClsid);
  721. strcat(szProgID, "\\Clsid");
  722. if (RegQueryValue(HKEY_CLASSES_ROOT, szProgID, szClsid,&cbClsid) == ERROR_SUCCESS)
  723. {
  724. // make sure the clsid is valid
  725. cbProgID = sizeof(szProgID);
  726. char szClsidEntry[80];
  727. strcpy(szClsidEntry, "Clsid\\");
  728. strcat(szClsidEntry, szClsid);
  729. if (RegQueryValue(HKEY_CLASSES_ROOT, szClsidEntry,szProgID, &cbProgID) == ERROR_SUCCESS)
  730. {
  731. CLSID clsid;
  732. WCHAR sz[256];
  733. A2W(szClsid,sz,256);
  734. hr = CLSIDFromString(sz, pclsid);
  735. if (hr != NOERROR)
  736. {
  737. *pclsid = CLSID_NULL;
  738. hr = REGDB_E_CLASSNOTREG;
  739. }
  740. }
  741. }
  742. }
  743. End:
  744. PerfDbgLog1(tagTransApi, NULL, "-GetClassFromExt (hr:%lx)", hr);
  745. DEBUG_LEAVE(hr);
  746. return hr;
  747. }
  748. //+---------------------------------------------------------------------------
  749. //
  750. // Function: IsValidURL
  751. //
  752. // Synopsis:
  753. //
  754. // Arguments: [pBC] --
  755. // [szURL] --
  756. // [dwReserved] --
  757. //
  758. // Returns:
  759. //
  760. // History: 4-16-96 JohannP (Johann Posch) Created
  761. //
  762. // Notes:
  763. //
  764. //----------------------------------------------------------------------------
  765. STDAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
  766. {
  767. DEBUG_ENTER_API((DBG_API,
  768. Hresult,
  769. "IsValidURL",
  770. "%#x, %.80wq, %#x",
  771. pBC, szURL, dwReserved
  772. ));
  773. HRESULT hr;
  774. PerfDbgLog2(tagTransApi, NULL, "+IsValidURL(pBC:%lx, szURL:%ws)",pBC,szURL);
  775. WCHAR wzUrlStr[MAX_URL_SIZE + 1];
  776. if (szURL == NULL)
  777. {
  778. hr = E_INVALIDARG;
  779. }
  780. else if ( (ConstructURL(pBC, NULL, NULL, (LPWSTR)szURL, wzUrlStr, sizeof(wzUrlStr), CU_CANONICALIZE) == NOERROR)
  781. && IsOInetProtocol(pBC, wzUrlStr))
  782. {
  783. hr = NOERROR;
  784. }
  785. else
  786. {
  787. hr = S_FALSE;
  788. }
  789. PerfDbgLog3(tagTransApi, NULL, "-IsValidURL(pBC:%lx, szURL:%ws, hr:%lx)",pBC,szURL,hr);
  790. DEBUG_LEAVE_API(hr);
  791. return hr;
  792. }
  793. //+---------------------------------------------------------------------------
  794. //
  795. // Function: GetUrlScheme
  796. //
  797. // Synopsis:
  798. //
  799. // Arguments: pcwsz -- the URL
  800. // [szURL] --
  801. // [dwReserved] --
  802. //
  803. // Returns: URL_SCHEME_*
  804. //
  805. //----------------------------------------------------------------------------
  806. DWORD
  807. GetUrlScheme(LPCWSTR pcwzUrl)
  808. {
  809. DEBUG_ENTER((DBG_TRANSDAT,
  810. Hresult,
  811. "GetUrlScheme",
  812. "%.80wq",
  813. pcwzUrl
  814. ));
  815. if(pcwzUrl)
  816. {
  817. PARSEDURLW puW;
  818. puW.cbSize = sizeof(puW);
  819. if(SUCCEEDED(ParseURLW(pcwzUrl, &puW)))
  820. {
  821. DEBUG_LEAVE(puW.nScheme);
  822. return puW.nScheme;
  823. }
  824. }
  825. DEBUG_LEAVE(URL_SCHEME_INVALID);
  826. return URL_SCHEME_INVALID;
  827. }
  828. //+---------------------------------------------------------------------------
  829. //
  830. // Function: GetClassFileOrMime2
  831. //
  832. // Synopsis:
  833. //
  834. // Arguments: [pBC] --
  835. // [wzFilename] --
  836. // [pBuffer] --
  837. // [cbSize] --
  838. // [pwzMime] --
  839. // [dwReserved] --
  840. // [pclsid] --
  841. // [fIgnoreMimeClsid] --
  842. //
  843. // Returns:
  844. //
  845. // History: 4-16-96 JohannP (Johann Posch) Created
  846. //
  847. // Notes:
  848. //
  849. //----------------------------------------------------------------------------
  850. STDAPI GetClassFileOrMime2(LPBC pBC, LPCWSTR pwzFilename, LPVOID pBuffer, DWORD cbSize,
  851. LPCWSTR pwzMimeIn, DWORD dwReserved, CLSID *pclsid, BOOL fIgnoreMimeClsid)
  852. {
  853. DEBUG_ENTER_API((DBG_API,
  854. Hresult,
  855. "GetClassFileOrMime2",
  856. "%#x, %.80wq, %#x, %#x, %.80wq, %#x, %#x, %B",
  857. pBC, pwzFilename, pBuffer, cbSize, pwzMimeIn, dwReserved, pclsid, fIgnoreMimeClsid
  858. ));
  859. PerfDbgLog1(tagTransApi, NULL, "+GetClassFileOrMime(%lx)",pBC);
  860. HRESULT hr = REGDB_E_CLASSNOTREG;
  861. HRESULT hrPlugin = REGDB_E_CLASSNOTREG;
  862. HRESULT hrClass = REGDB_E_CLASSNOTREG;
  863. char szMime[SZMIMESIZE_MAX];
  864. char szFilename[MAX_PATH];
  865. LPSTR pszMime = NULL;
  866. LPSTR pszFilename = NULL;
  867. LPSTR pszExt = NULL;
  868. LPWSTR pwzMime = (LPWSTR)pwzMimeIn;
  869. DWORD cbMime = SZMIMESIZE_MAX;
  870. CLSID clsidPlugin = CLSID_NULL;
  871. BOOL fDocFile = FALSE;
  872. DWORD dwClsCtx = 0;
  873. DWORD dwFlags = (fIgnoreMimeClsid) ? MIMEFLAGS_IGNOREMIME_CLASSID : 0;
  874. if ( pclsid == NULL
  875. || (!pwzFilename && (!pBuffer || !cbSize) && !pwzMimeIn))
  876. {
  877. hr = E_INVALIDARG;
  878. goto errRet;
  879. }
  880. *pclsid = CLSID_NULL;
  881. //sniff data here or when setting the mime
  882. if (pBuffer && cbSize)
  883. {
  884. fDocFile = (IsDocFile(pBuffer,cbSize) == S_OK);
  885. if (fDocFile)
  886. {
  887. // do not pass the buffer - no need to sniff data
  888. hr = FindMimeFromData(pBC, pwzFilename, NULL, 0, pwzMimeIn, 0, &pwzMime, 0);
  889. }
  890. else
  891. {
  892. hr = FindMimeFromData(pBC, pwzFilename, pBuffer, cbSize, pwzMimeIn, 0, &pwzMime, 0);
  893. }
  894. }
  895. if (pwzMime)
  896. {
  897. // convert the mime
  898. W2A(pwzMime, szMime, SZMIMESIZE_MAX);
  899. pszMime = szMime;
  900. }
  901. if (pwzFilename)
  902. {
  903. W2A(pwzFilename, szFilename, MAX_PATH);
  904. pszFilename = szFilename;
  905. }
  906. // 1. find the class based on the mime
  907. if (pszMime)
  908. {
  909. if (pBC)
  910. {
  911. hr = FindMediaTypeClass(pBC, szMime, pclsid, 0);
  912. }
  913. if (hr != NOERROR)
  914. {
  915. // get the class from the mime string
  916. hr = FindMediaTypeClassInfo(pszMime, pszFilename, pclsid, &dwClsCtx, dwFlags);
  917. }
  918. }
  919. // 2. find class of docfile
  920. if ((hr != NOERROR || IsEqualGUID(*pclsid, CLSID_NULL)) && cbSize && fDocFile)
  921. {
  922. // get class from docfile
  923. hr = GetClassDocFileBuffer(pBuffer, cbSize, pclsid);
  924. }
  925. // 3. use the file to find the class
  926. if ( (hr != NOERROR)
  927. && pszFilename)
  928. {
  929. pszExt = FindFileExtension(pszFilename);
  930. // use extension and use class mapping
  931. if (pszExt != NULL)
  932. {
  933. char szMimeExt[SZMIMESIZE_MAX];
  934. DWORD cbMimeExt = SZMIMESIZE_MAX;
  935. // get the mime for the file
  936. hr = GetMimeFromExt(pszExt,szMimeExt, &cbMimeExt);
  937. if ( (hr == NOERROR)
  938. && ( (pszMime && strcmp(pszMime, szMimeExt))
  939. || !pszMime)
  940. )
  941. {
  942. hr = REGDB_E_CLASSNOTREG;
  943. if (pBC)
  944. {
  945. // check for class mapping
  946. hr = FindMediaTypeClass(pBC, szMimeExt, pclsid, 0);
  947. }
  948. if (hr != NOERROR)
  949. {
  950. // get the class from the mime string
  951. hr = FindMediaTypeClassInfo(szMimeExt, pszFilename, pclsid, &dwClsCtx, dwFlags);
  952. }
  953. }
  954. }
  955. // last call GetClassFile
  956. if ( hr != NOERROR && pwzFilename && (!pwzMime || fDocFile) )
  957. {
  958. hr = GetClassFile(pwzFilename, pclsid);
  959. }
  960. // should never need to use file to locate CLSID_HTMLDocument
  961. if (IsEqualGUID(*pclsid, CLSID_HTMLDocument))
  962. {
  963. *pclsid = CLSID_NULL;
  964. hrClass = REGDB_E_CLASSNOTREG;
  965. }
  966. }
  967. // 4. if available check the class id and
  968. // trigger check for plugin class id if needed
  969. if ( (hr == NOERROR)
  970. && !IsEqualGUID(*pclsid, CLSID_NULL))
  971. {
  972. hrClass = NOERROR;
  973. if (dwClsCtx == 0)
  974. {
  975. hr = GetClsIDInfo(pclsid, 0, &dwClsCtx);
  976. }
  977. if (hr == NOERROR)
  978. {
  979. if (dwClsCtx & CLSCTX_DOCOBJECT)
  980. {
  981. // server of class is a docobject
  982. hrPlugin = NOERROR;
  983. }
  984. else if (dwClsCtx & CLSCTX_INPROC)
  985. {
  986. // server of class is inproc
  987. // check if the class is mshtml tread it as docobject and stop
  988. // looking for plugin
  989. if (IsEqualGUID(*pclsid, CLSID_MsHtml))
  990. {
  991. hrPlugin = NOERROR;
  992. }
  993. }
  994. else if (dwClsCtx & CLSCTX_LOCAL_SERVER)
  995. {
  996. // server of class is local
  997. }
  998. }
  999. // else
  1000. // class is not properly registered
  1001. //
  1002. }
  1003. // 5. check if the download is for a plugin
  1004. // if yes get the plugin host class id
  1005. if (hrPlugin != NOERROR)
  1006. {
  1007. if (pszExt == NULL && pszFilename)
  1008. {
  1009. pszExt = FindFileExtension(pszFilename);
  1010. }
  1011. // if we have a mime and/or an extension mime check if
  1012. // this is a plugin or an ocx
  1013. if (pszExt || pszMime)
  1014. {
  1015. hrPlugin = GetPlugInClsID(pszExt, NULL, pszMime, &clsidPlugin);
  1016. }
  1017. }
  1018. else
  1019. {
  1020. hrPlugin = E_FAIL;
  1021. }
  1022. // 6. the plugin class use it
  1023. if ( (hrPlugin == NOERROR) && !(dwReserved & GETCLASSFILEORMIME_IGNOREPLUGIN))
  1024. {
  1025. *pclsid = clsidPlugin;
  1026. hr = hrPlugin;
  1027. }
  1028. // used the class found
  1029. else
  1030. {
  1031. hr = hrClass;
  1032. }
  1033. if (pwzMime != pwzMimeIn)
  1034. {
  1035. delete [] pwzMime;
  1036. }
  1037. TransAssert(( (hr != NOERROR && IsEqualGUID(*pclsid, CLSID_NULL))
  1038. || (hr == NOERROR && !IsEqualGUID(*pclsid, CLSID_NULL)) ));
  1039. errRet:
  1040. TransAssert((hr == NOERROR || hr == REGDB_E_CLASSNOTREG || hr == E_INVALIDARG));
  1041. PerfDbgLog1(tagTransApi, NULL, "-GetClassFileOrMime (hr:%lx)",hr);
  1042. DEBUG_LEAVE_API(hr);
  1043. return hr;
  1044. }
  1045. //+---------------------------------------------------------------------------
  1046. //
  1047. // Function: GetClassFileOrMime
  1048. //
  1049. // Synopsis:
  1050. //
  1051. // Arguments: [pBC] --
  1052. // [wzFilename] --
  1053. // [pBuffer] --
  1054. // [cbSize] --
  1055. // [pwzMime] --
  1056. // [dwReserved] --
  1057. // [pclsid] --
  1058. //
  1059. // Returns:
  1060. //
  1061. // History: 4-16-96 JohannP (Johann Posch) Created
  1062. //
  1063. // Notes:
  1064. //
  1065. //----------------------------------------------------------------------------
  1066. STDAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pwzFilename, LPVOID pBuffer, DWORD cbSize,
  1067. LPCWSTR pwzMimeIn, DWORD dwReserved, CLSID *pclsid)
  1068. {
  1069. DEBUG_ENTER_API((DBG_API,
  1070. Hresult,
  1071. "GetClassFileOrMime",
  1072. "%#x, %.80wq, %#x, %#x, %.80wq, %#x, %#x",
  1073. pBC, pwzFilename, pBuffer, cbSize, pwzMimeIn, dwReserved, pclsid
  1074. ));
  1075. HRESULT hr = GetClassFileOrMime2(pBC, pwzFilename, pBuffer, cbSize, pwzMimeIn,
  1076. dwReserved, pclsid, FALSE);
  1077. DEBUG_LEAVE_API(hr);
  1078. return hr;
  1079. }
  1080. //+---------------------------------------------------------------------------
  1081. //
  1082. // Function: GetClassDocFileBuffer
  1083. //
  1084. // Synopsis:
  1085. //
  1086. // Arguments: [pbuffer] --
  1087. // [dwSize] --
  1088. // [pclsid] --
  1089. //
  1090. // Returns:
  1091. //
  1092. // History: 2-28-96 JohannP (Johann Posch) Created
  1093. //
  1094. // Notes:
  1095. //
  1096. //----------------------------------------------------------------------------
  1097. HRESULT GetClassDocFileBuffer(LPVOID pbuffer, DWORD dwSize, CLSID *pclsid)
  1098. {
  1099. DEBUG_ENTER((DBG_TRANSDAT,
  1100. Hresult,
  1101. "GetClassDocFileBuffer",
  1102. "%#x, %#x, %#x",
  1103. pbuffer, dwSize, pclsid
  1104. ));
  1105. PerfDbgLog(tagTransApi, NULL, "+GetClassDocFileBuffer");
  1106. HRESULT hr = E_FAIL;
  1107. ILockBytes *pilb;
  1108. IStorage *pstg;
  1109. STATSTG stat;
  1110. HGLOBAL hGlobal = 0;
  1111. hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_NODISCARD, dwSize);
  1112. if (hGlobal)
  1113. {
  1114. memcpy(hGlobal, pbuffer, dwSize);
  1115. hr = CreateILockBytesOnHGlobal(hGlobal,FALSE,&pilb);
  1116. if (hr == NOERROR)
  1117. {
  1118. hr = StgOpenStorageOnILockBytes(pilb,NULL,STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
  1119. NULL,0,&pstg);
  1120. if (hr == NOERROR)
  1121. {
  1122. pstg->Stat(&stat, STATFLAG_NONAME);
  1123. pstg->Release();
  1124. *pclsid = stat.clsid;
  1125. }
  1126. else
  1127. {
  1128. hr = E_FAIL;
  1129. }
  1130. }
  1131. GlobalFree(hGlobal);
  1132. }
  1133. PerfDbgLog1(tagTransApi, NULL, "-GetClassDocFileBuffer (hr:%lx)", hr);
  1134. DEBUG_LEAVE(hr);
  1135. return hr;
  1136. }
  1137. HRESULT GetCodeBaseFromDocFile(LPBYTE pBuffer, ULONG ulSize, LPWSTR *pwzClassStr,
  1138. LPWSTR pwzBaseUrl, DWORD *lpdwVersionMS, DWORD *lpdwVersionLS);
  1139. //+---------------------------------------------------------------------------
  1140. //
  1141. // Method: IsHandlerAvailable
  1142. //
  1143. // Synopsis:
  1144. //
  1145. // Arguments: [pClsid] --
  1146. // [pMime] --
  1147. //
  1148. // Returns:
  1149. //
  1150. // History: 11-07-1996 JohannP (Johann Posch) Created
  1151. //
  1152. // Notes:
  1153. //
  1154. //----------------------------------------------------------------------------
  1155. HRESULT IsHandlerAvailable(LPWSTR pwzUrl, LPWSTR pwzMime, CLSID *pclsid, LPBYTE pBuffer, ULONG cbSize)
  1156. {
  1157. DEBUG_ENTER((DBG_TRANSDAT,
  1158. Hresult,
  1159. "IsHandlerAvailable",
  1160. "%.80wq, %.80wq, %#x, %#x, %#x",
  1161. pwzUrl, pwzMime, pclsid, pBuffer, cbSize
  1162. ));
  1163. PerfDbgLog(tagTransApi, NULL, "+GetCodeBaseFromDocFile");
  1164. HRESULT hr = E_FAIL, hr1;
  1165. LPWSTR szDistUnit = 0;
  1166. BOOL fIgnoreMimeClsid = FALSE, fHasHandler = FALSE, fDocFile = FALSE;
  1167. CLocalComponentInfo lci;
  1168. CHAR szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
  1169. CHAR szMime[SZMIMESIZE_MAX];
  1170. LPSTR pszUrl = 0;
  1171. W2A(pwzMime, szMime, SZMIMESIZE_MAX);
  1172. pszUrl = DupW2A(pwzUrl); // can potentially be very long
  1173. if ((pwzMime == 0) || (*pwzMime == 0))
  1174. {
  1175. hr = E_INVALIDARG;
  1176. }
  1177. else
  1178. {
  1179. HKEY hMimeKey = 0;
  1180. *pclsid = CLSID_NULL;
  1181. strcpy(szKey, szMimeKey);
  1182. strcat(szKey, szMime);
  1183. // NOTE: different handlers may be implemented in different ways, for example.
  1184. // the abscence of a CLSID does not imply the handler is bad or missing.
  1185. // check if mime type exists in "Content Type" branch
  1186. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey) == ERROR_SUCCESS)
  1187. {
  1188. fHasHandler = TRUE;
  1189. RegCloseKey(hMimeKey);
  1190. hMimeKey = 0;
  1191. }
  1192. // if not check if extension type has handler
  1193. if (!fHasHandler)
  1194. {
  1195. LPSTR pszExt = FindFileExtension(pszUrl);
  1196. // try for handler of extension
  1197. if (pszExt && *pszExt == '.')
  1198. {
  1199. hMimeKey = 0;
  1200. // there may be a handler for this extension already
  1201. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, pszExt, 0, KEY_QUERY_VALUE, &hMimeKey) == ERROR_SUCCESS)
  1202. {
  1203. fHasHandler = TRUE;
  1204. RegCloseKey(hMimeKey);
  1205. }
  1206. }
  1207. }
  1208. // we haven't found a handler yet, in case of DocFile, check if CLSID associated
  1209. // with it exists.
  1210. if (!fHasHandler && SUCCEEDED(IsDocFile(pBuffer,cbSize)))
  1211. {
  1212. DWORD dwVersionMS = 0, dwVersionLS = 0;
  1213. LPWSTR pwzCodeBase = 0;
  1214. hr1 = GetCodeBaseFromDocFile(pBuffer, cbSize, &pwzCodeBase, NULL, &dwVersionMS, &dwVersionLS);
  1215. if (pwzCodeBase) {
  1216. delete pwzCodeBase;
  1217. }
  1218. hr1 = GetClassDocFileBuffer(pBuffer, cbSize, pclsid);
  1219. if (SUCCEEDED(hr1) && !IsEqualCLSID(*pclsid, CLSID_NULL))
  1220. {
  1221. StringFromCLSID(*pclsid, &szDistUnit);
  1222. hr1 = IsControlLocallyInstalled(NULL, pclsid, szDistUnit, dwVersionMS, dwVersionLS, &lci, NULL);
  1223. if (hr1 == S_OK)
  1224. {
  1225. fHasHandler = TRUE;
  1226. }
  1227. if (szDistUnit)
  1228. {
  1229. delete szDistUnit;
  1230. }
  1231. }
  1232. }
  1233. }
  1234. if (pszUrl)
  1235. {
  1236. delete [] pszUrl;
  1237. }
  1238. if (fHasHandler)
  1239. {
  1240. hr = S_OK;
  1241. }
  1242. else
  1243. {
  1244. hr = S_FALSE;
  1245. }
  1246. DEBUG_LEAVE(hr);
  1247. return hr;
  1248. }
  1249. //+---------------------------------------------------------------------------
  1250. //
  1251. // Method: GetCodeBaseFromDocFile
  1252. //
  1253. // Synopsis:
  1254. //
  1255. // Arguments: [pBuffer] --
  1256. // [ulSize] --
  1257. // [pwzClassStr] --
  1258. //
  1259. // Returns:
  1260. //
  1261. // History: 11-07-1996 JohannP (Johann Posch) Created
  1262. //
  1263. // Notes:
  1264. //
  1265. //----------------------------------------------------------------------------
  1266. HRESULT GetCodeBaseFromDocFile(LPBYTE pBuffer, ULONG ulSize, LPWSTR *pwzClassStr,
  1267. LPWSTR pwzBaseUrl, DWORD *lpdwVersionMS, DWORD *lpdwVersionLS)
  1268. {
  1269. DEBUG_ENTER((DBG_TRANSDAT,
  1270. Hresult,
  1271. "GetCodeBaseFromDocFile",
  1272. "%#x, %#x, %#x, %.80wq, %#x, %#x",
  1273. pBuffer, ulSize, pwzClassStr, pwzBaseUrl, lpdwVersionMS, lpdwVersionLS
  1274. ));
  1275. PerfDbgLog(tagTransApi, NULL, "+GetCodeBaseFromDocFile");
  1276. HRESULT hr = E_FAIL;
  1277. ILockBytes *pilb;
  1278. IStorage *pstg;
  1279. STATSTG stat;
  1280. static ULONG cpSpec = DOCFILE_NUMPROPERTIES;
  1281. static PROPSPEC rgpSpec[DOCFILE_NUMPROPERTIES] = {
  1282. { PRSPEC_PROPID, DOCFILE_PROPID_CODEBASE },
  1283. { PRSPEC_PROPID, DOCFILE_PROPID_MAJORVERSION },
  1284. { PRSPEC_PROPID, DOCFILE_PROPID_MINORVERSION } };
  1285. PROPVARIANT rgVarDisplay[DOCFILE_NUMPROPERTIES];
  1286. if (!pwzClassStr || !lpdwVersionMS || !lpdwVersionLS)
  1287. {
  1288. hr = E_INVALIDARG;
  1289. }
  1290. else
  1291. {
  1292. HGLOBAL hGlobal = 0;
  1293. hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_NODISCARD, ulSize);
  1294. *pwzClassStr = 0;
  1295. if (hGlobal)
  1296. {
  1297. memcpy(hGlobal, pBuffer, ulSize);
  1298. hr = CreateILockBytesOnHGlobal(hGlobal,FALSE,&pilb);
  1299. if (hr == NOERROR)
  1300. {
  1301. hr = StgOpenStorageOnILockBytes(pilb,NULL,STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
  1302. NULL,0,&pstg);
  1303. if (hr == NOERROR)
  1304. {
  1305. IPropertySetStorage *ppss = 0;
  1306. hr = pstg->QueryInterface(IID_IPropertySetStorage, (void **)&ppss);
  1307. if (SUCCEEDED(hr))
  1308. {
  1309. IPropertyStorage *pps = 0;
  1310. //BUGBUG: there is potential for error here if data structure of
  1311. // PropertyStorage is not fully loaded. since we have read only access
  1312. // we should be ok.
  1313. hr = ppss->Open(FMTID_CodeBase, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, (IPropertyStorage **)&pps);
  1314. if (SUCCEEDED(hr))
  1315. {
  1316. hr = pps->ReadMultiple(cpSpec, rgpSpec, rgVarDisplay);
  1317. if (SUCCEEDED(hr))
  1318. {
  1319. *pwzClassStr = rgVarDisplay[0].pwszVal;
  1320. *lpdwVersionMS = rgVarDisplay[1].ulVal;
  1321. *lpdwVersionLS = rgVarDisplay[2].ulVal;
  1322. }
  1323. pps->Release();
  1324. }
  1325. ppss->Release();
  1326. }
  1327. pstg->Release();
  1328. }
  1329. else
  1330. {
  1331. hr = E_FAIL;
  1332. }
  1333. }
  1334. GlobalFree(hGlobal);
  1335. }
  1336. }
  1337. if (SUCCEEDED(hr) && pwzBaseUrl)
  1338. {
  1339. LPWSTR pwzNewClassStr = 0;
  1340. DWORD dwLen, dwNewLen;
  1341. HRESULT hr1;
  1342. // we do not know what the combined maximum Url length is, so as
  1343. // an upper bound we take twice the combined url's plus 10.
  1344. dwLen = 2*(lstrlenW(pwzBaseUrl) + lstrlenW(*pwzClassStr)) + 10;
  1345. pwzNewClassStr = new WCHAR[dwLen];
  1346. if (pwzNewClassStr)
  1347. {
  1348. hr1 = CoInternetCombineUrl(pwzBaseUrl, *pwzClassStr, ICU_NO_ENCODE, pwzNewClassStr, dwLen, &dwNewLen, 0);
  1349. if (SUCCEEDED(hr1) && dwNewLen)
  1350. {
  1351. delete [] *pwzClassStr;
  1352. *pwzClassStr = pwzNewClassStr;
  1353. }
  1354. else
  1355. {
  1356. delete [] pwzNewClassStr;
  1357. }
  1358. }
  1359. }
  1360. PerfDbgLog1(tagTransApi, NULL, "-GetCodeBaseFromDocFile (hr:%lx)", hr);
  1361. DEBUG_LEAVE(hr);
  1362. return hr;
  1363. }
  1364. //+---------------------------------------------------------------------------
  1365. //
  1366. // Function: UrlMkSetSessionOption
  1367. //
  1368. // Synopsis:
  1369. //
  1370. // Arguments: [dwOption] --
  1371. // [pBuffer] --
  1372. // [dwBufferLength] --
  1373. // [dwReserved] --
  1374. //
  1375. // Returns:
  1376. //
  1377. // History: 5-06-96 JohannP (Johann Posch) Created
  1378. //
  1379. // Notes:
  1380. //
  1381. //----------------------------------------------------------------------------
  1382. STDAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength, DWORD dwReserved)
  1383. {
  1384. DEBUG_ENTER_API((DBG_API,
  1385. Hresult,
  1386. "UrlMkSetSessionOption",
  1387. "%#x, %#x, %#x, %#x",
  1388. dwOption, pBuffer, dwBufferLength, dwReserved
  1389. ));
  1390. // BUGBUG - Function not threadsafe.
  1391. PerfDbgLog(tagTransApi, NULL, "+UrlMkSetSessionOption");
  1392. HRESULT hr;
  1393. switch(dwOption)
  1394. {
  1395. // Change the User Agent string for this process.
  1396. case URLMON_OPTION_USERAGENT:
  1397. {
  1398. // Validate buffer, allocate new user agent string,
  1399. // delete old if necessary, copy and reference with
  1400. // g_pszUserAgentString.
  1401. if (!(pBuffer && dwBufferLength))
  1402. {
  1403. hr = E_INVALIDARG;
  1404. break;
  1405. }
  1406. LPSTR pszTemp = new CHAR[dwBufferLength + 1];
  1407. if (!pszTemp)
  1408. {
  1409. TransAssert(pszTemp && "Allocating memory for User-Agent header failed");
  1410. hr = E_OUTOFMEMORY;
  1411. break;
  1412. }
  1413. memcpy(pszTemp, pBuffer, dwBufferLength);
  1414. pszTemp[dwBufferLength] = '\0';
  1415. if (g_pszUserAgentString)
  1416. {
  1417. delete [] g_pszUserAgentString;
  1418. }
  1419. g_pszUserAgentString = pszTemp;
  1420. hr = S_OK;
  1421. break;
  1422. }
  1423. // Refresh user agent string from registry for this process.
  1424. case URLMON_OPTION_USERAGENT_REFRESH:
  1425. {
  1426. // Refresh, delete old user agent string if necessary.
  1427. // g_pszUserAgentString references refreshed string.
  1428. LPSTR pszTemp = g_pszUserAgentString;
  1429. // NULL forces GetUserAgentString to refresh from registry.
  1430. g_pszUserAgentString = NULL;
  1431. g_pszUserAgentString = (LPSTR) GetUserAgentString();
  1432. if (!g_pszUserAgentString)
  1433. {
  1434. g_pszUserAgentString = pszTemp;
  1435. hr = S_FALSE;
  1436. break;
  1437. }
  1438. // Need to set this on the session handle also.
  1439. if (g_hSession)
  1440. InternetSetOption(g_hSession, INTERNET_OPTION_USER_AGENT,
  1441. g_pszUserAgentString, strlen(g_pszUserAgentString));
  1442. delete [] pszTemp;
  1443. hr = S_OK;
  1444. break;
  1445. }
  1446. // Set or reload proxy info from registry.
  1447. case INTERNET_OPTION_PROXY:
  1448. case INTERNET_OPTION_REFRESH:
  1449. {
  1450. // InternetSetOption does its own buffer validation.
  1451. if (InternetSetOption(NULL, dwOption, pBuffer, dwBufferLength))
  1452. {
  1453. hr = S_OK;
  1454. break;
  1455. }
  1456. hr = S_FALSE;
  1457. break;
  1458. }
  1459. default:
  1460. {
  1461. hr = E_INVALIDARG;
  1462. break;
  1463. }
  1464. }
  1465. PerfDbgLog1(tagTransApi, NULL, "-UrlMkSetSessionOption (hr:%lx)", hr);
  1466. DEBUG_LEAVE_API(hr);
  1467. return hr;
  1468. }
  1469. //+---------------------------------------------------------------------------
  1470. //
  1471. // Function: UrlMkGetSessionOption
  1472. //
  1473. // Synopsis:
  1474. //
  1475. // Arguments: [dwOption] --
  1476. // [pBuffer] --
  1477. // [dwBufferLength] --
  1478. // [dwReserved] --
  1479. //
  1480. // Returns:
  1481. //
  1482. // History: 5-06-96 JohannP (Johann Posch) Created
  1483. //
  1484. // Notes:
  1485. //
  1486. //----------------------------------------------------------------------------
  1487. STDAPI UrlMkGetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength, DWORD *pdwBufferLengthOut, DWORD dwReserved)
  1488. {
  1489. DEBUG_ENTER_API((DBG_API,
  1490. Hresult,
  1491. "UrlMkSetSessionOption",
  1492. "%#x, %#x, %#x, %#x",
  1493. dwOption, pBuffer, dwBufferLength, dwReserved
  1494. ));
  1495. PerfDbgLog(tagTransApi, NULL, "+UrlMkGetSessionOption");
  1496. HRESULT hr = E_FAIL;
  1497. if( !pdwBufferLengthOut )
  1498. {
  1499. DEBUG_LEAVE_API(E_INVALIDARG);
  1500. return E_INVALIDARG;
  1501. }
  1502. if (dwOption == URLMON_OPTION_USERAGENT)
  1503. {
  1504. // get the default user agent string
  1505. LPCSTR pszStr = GetUserAgentString();
  1506. DWORD cLen = strlen(pszStr);
  1507. *pdwBufferLengthOut = cLen + 1;
  1508. hr = E_OUTOFMEMORY;
  1509. if (cLen < dwBufferLength )
  1510. {
  1511. if( pBuffer )
  1512. {
  1513. strcpy((LPSTR)pBuffer, pszStr);
  1514. // AOL BUG 66102 - we always return E_FAIL
  1515. // hr = NOERROR;
  1516. }
  1517. else
  1518. {
  1519. hr = E_INVALIDARG;
  1520. }
  1521. }
  1522. }
  1523. else if (dwOption == URLMON_OPTION_URL_ENCODING)
  1524. {
  1525. if( !pBuffer || dwBufferLength < sizeof(DWORD) )
  1526. {
  1527. hr = E_INVALIDARG;
  1528. }
  1529. else
  1530. {
  1531. DWORD dwEncoding = URL_ENCODING_NONE;
  1532. BOOL fDefault = FALSE;
  1533. DWORD dwUrlEncodingDisableUTF8;
  1534. DWORD dwSize = sizeof(DWORD);
  1535. if( ERROR_SUCCESS == SHRegGetUSValue(
  1536. INTERNET_SETTING_KEY,
  1537. "UrlEncoding",
  1538. NULL,
  1539. (LPBYTE) &dwUrlEncodingDisableUTF8,
  1540. &dwSize,
  1541. FALSE,
  1542. (LPVOID) &fDefault,
  1543. sizeof(fDefault) ) )
  1544. {
  1545. if( dwUrlEncodingDisableUTF8)
  1546. dwEncoding = URL_ENCODING_DISABLE_UTF8;
  1547. else
  1548. dwEncoding = URL_ENCODING_ENABLE_UTF8;
  1549. }
  1550. hr = NOERROR;
  1551. *pdwBufferLengthOut = sizeof(DWORD);
  1552. memcpy(pBuffer, (LPVOID)(&dwEncoding), sizeof(DWORD));
  1553. }
  1554. }
  1555. else
  1556. {
  1557. hr = E_INVALIDARG;
  1558. }
  1559. PerfDbgLog1(tagTransApi, NULL, "-UrlMkGetSessionOption (hr:%lx)", hr);
  1560. DEBUG_LEAVE_API(hr);
  1561. return hr;
  1562. }
  1563. //+---------------------------------------------------------------------------
  1564. //
  1565. // Function: GetPlugInClsID
  1566. //
  1567. // Synopsis: load the plugin ocx; get the FindPluginByExtA address
  1568. // call the FindPluginByExtA api
  1569. //
  1570. // Arguments: [pszExt] --
  1571. // [szMime] --
  1572. // [pclsid] --
  1573. //
  1574. // Returns: NOERROR and plugin class id if file is handled by plugin
  1575. // REGDB_E_CLASSNOTREG otherwise
  1576. //
  1577. // History: 7-16-96 JohannP (Johann Posch) Created
  1578. //
  1579. // Notes:
  1580. //
  1581. //----------------------------------------------------------------------------
  1582. HRESULT GetPlugInClsID(LPSTR pszExt, LPSTR pszName, LPSTR pszMime, CLSID *pclsid)
  1583. {
  1584. DEBUG_ENTER((DBG_TRANSDAT,
  1585. Hresult,
  1586. "GetPlugInClsID",
  1587. "%.80q, %.80q, %.80q, %#x",
  1588. pszExt, pszName, pszMime, pclsid
  1589. ));
  1590. HRESULT hr = REGDB_E_CLASSNOTREG;
  1591. PerfDbgLog3(tagTransApi, NULL, "+GetPlugInClsID (pszExt:%s, pszName:%s, pszMime:%s)", pszExt, pszName, pszMime);
  1592. typedef BOOL (WINAPI * pfnFINDPLUGINBYEXT)(char *szExt, char *szName, char *szMime);
  1593. static pfnFINDPLUGINBYEXT pfnFindPlugin = NULL;
  1594. static BOOL fPluginLoaded = FALSE;
  1595. static BOOL fGotProcAddr = FALSE;
  1596. if (!fPluginLoaded)
  1597. {
  1598. g_hLibPluginOcx = LoadLibraryA("plugin.ocx");
  1599. fPluginLoaded = TRUE;
  1600. }
  1601. if (g_hLibPluginOcx != NULL)
  1602. {
  1603. if (!fGotProcAddr)
  1604. {
  1605. pfnFindPlugin = (pfnFINDPLUGINBYEXT)GetProcAddress(g_hLibPluginOcx, "FindPluginByExtA");
  1606. fGotProcAddr = TRUE;
  1607. if (pfnFindPlugin == NULL)
  1608. {
  1609. DbgLog(tagTransApi, NULL, "Failed to find entry point FindPluginByExt in plugin.ocx");
  1610. }
  1611. }
  1612. if (pfnFindPlugin && pfnFindPlugin(pszExt, pszName, pszMime))
  1613. {
  1614. hr = S_OK;
  1615. }
  1616. }
  1617. else
  1618. {
  1619. DbgLog(tagTransApi, NULL, "Failed to find plugin.ocx");
  1620. }
  1621. if (hr == S_OK)
  1622. {
  1623. *pclsid = CLSID_PluginHost;
  1624. }
  1625. PerfDbgLog1(tagTransApi, NULL, "-GetPlugInClsID (hr:%lx)", hr);
  1626. DEBUG_LEAVE(hr);
  1627. return hr;
  1628. }
  1629. //+---------------------------------------------------------------------------
  1630. //
  1631. // Function: StringAFromCLSID
  1632. //
  1633. // Synopsis: returns an ansi string of given class id
  1634. //
  1635. // Arguments: [pclsid] -- the class id
  1636. //
  1637. // Returns: pointer to class id string or
  1638. // NULL if out of memory
  1639. //
  1640. // History: 7-20-96 JohannP (Johann Posch) Created
  1641. //
  1642. // Notes: string pointer has to be deleted with delete (operator)
  1643. //
  1644. //----------------------------------------------------------------------------
  1645. LPSTR StringAFromCLSID(CLSID *pclsid)
  1646. {
  1647. DEBUG_ENTER((DBG_TRANSDAT,
  1648. Hresult,
  1649. "StringAFromCLSID",
  1650. "%#x",
  1651. pclsid
  1652. ));
  1653. LPOLESTR pwzStr;
  1654. LPSTR pszStr = NULL;
  1655. TransAssert((pclsid));
  1656. StringFromCLSID(*pclsid, &pwzStr);
  1657. if (pwzStr)
  1658. {
  1659. pszStr = SzDupWzToSz(pwzStr, TRUE);
  1660. delete pwzStr;
  1661. }
  1662. DEBUG_LEAVE(pszStr);
  1663. return pszStr;
  1664. }
  1665. //+---------------------------------------------------------------------------
  1666. //
  1667. // Function: CLSIDFromStringA
  1668. //
  1669. // Synopsis:
  1670. //
  1671. // Arguments: [pszClsid] --
  1672. // [pclsid] --
  1673. //
  1674. // Returns:
  1675. //
  1676. // History: 11-20-1996 JohannP (Johann Posch) Created
  1677. //
  1678. // Notes:
  1679. //
  1680. //----------------------------------------------------------------------------
  1681. HRESULT CLSIDFromStringA(LPSTR pszClsid, CLSID *pclsid)
  1682. {
  1683. DEBUG_ENTER((DBG_TRANSDAT,
  1684. Hresult,
  1685. "CLSIDFromStringA",
  1686. "%.80q, %#x",
  1687. pszClsid, pclsid
  1688. ));
  1689. WCHAR sz[CLSIDSTR_MAX];
  1690. A2W(pszClsid,sz,CLSIDSTR_MAX);
  1691. HRESULT hr = CLSIDFromString(sz, pclsid);
  1692. DEBUG_LEAVE(hr);
  1693. return hr;
  1694. }
  1695. #include "ocidl.h"
  1696. #ifndef unix
  1697. #include "..\urlhlink\urlhlink.h"
  1698. #else
  1699. #include "../urlhlink/urlhlink.h"
  1700. #endif /* unix */
  1701. #define IS_E_PENDING(hr) (hr == E_PENDING)
  1702. //+---------------------------------------------------------------------------
  1703. //
  1704. // Function: URLDownloadA
  1705. //
  1706. // Synopsis:
  1707. //
  1708. // Arguments: [pUnk] --
  1709. // [szURL] --
  1710. // [pBindInfo] --
  1711. // [pBSCB] --
  1712. // [dwReserved] --
  1713. //
  1714. // Returns:
  1715. //
  1716. // History: 7-27-96 JohannP (Johann Posch) Created
  1717. //
  1718. // Notes:
  1719. //
  1720. //----------------------------------------------------------------------------
  1721. STDAPI URLDownloadA(IUnknown *pUnk, LPCSTR pszURL, DWORD pBindInfo, IBindStatusCallback *pBSCB, DWORD dwReserved)
  1722. {
  1723. DEBUG_ENTER_API((DBG_API,
  1724. Hresult,
  1725. "URLDownloadA",
  1726. "%#x, %.80q, %#x, %#x, %#x",
  1727. pUnk, pszURL, pBindInfo, pBSCB, dwReserved
  1728. ));
  1729. PerfDbgLog1(tagTransApi, NULL, "+URLDownloadA (pszUrl:%s)", pszURL);
  1730. HRESULT hr = NOERROR;
  1731. LPCWSTR pwzUrl = DupA2W((LPSTR) pszURL);
  1732. if (pwzUrl)
  1733. {
  1734. hr = URLDownloadW(pUnk,pwzUrl,pBindInfo,pBSCB, 0);
  1735. }
  1736. PerfDbgLog1(tagTransApi, NULL, "-URLDownloadA (hr:%lx)", hr);
  1737. DEBUG_LEAVE_API(hr);
  1738. return hr;
  1739. }
  1740. //+---------------------------------------------------------------------------
  1741. //
  1742. // Function: URLDownloadW
  1743. //
  1744. // Synopsis:
  1745. //
  1746. // Arguments: [pUnk] --
  1747. // [pwzURL] --
  1748. // [pBindInfo] --
  1749. // [pBSCB] --
  1750. // [dwReserved] --
  1751. //
  1752. // Returns:
  1753. //
  1754. // History: 7-27-96 JohannP (Johann Posch) Created
  1755. //
  1756. // Notes:
  1757. //
  1758. //----------------------------------------------------------------------------
  1759. STDAPI URLDownloadW(IUnknown *pUnk, LPCWSTR pwzURL, DWORD pBindInfo, IBindStatusCallback *pBSCB, DWORD dwReserved)
  1760. {
  1761. DEBUG_ENTER_API((DBG_API,
  1762. Hresult,
  1763. "URLDownloadW",
  1764. "%#x, %.80wq, %#x, %#x, %#x",
  1765. pUnk, pwzURL, pBindInfo, pBSCB, dwReserved
  1766. ));
  1767. PerfDbgLog1(tagTransApi, NULL, "+URLDownloadW (pwzUrl:%ws)", pwzURL);
  1768. HRESULT hr;
  1769. IOleObject * pOleObject = 0;
  1770. IServiceProvider * pServiceProvider = 0;
  1771. IMoniker * pmkr = 0;
  1772. IBindCtx * pBndCtx = 0;
  1773. IBindHost * pBindHost = 0;
  1774. IStream * pstrm = 0;
  1775. // Don't bother if we don't have a caller...
  1776. if( pUnk )
  1777. {
  1778. // By convention the we give the caller first crack at service
  1779. // provider. The assumption here is that if they implement it
  1780. // they have the decency to forward QS's to their container.
  1781. hr = pUnk->QueryInterface( IID_IServiceProvider,
  1782. (void**)&pServiceProvider );
  1783. if( FAILED(hr) )
  1784. {
  1785. // Ok, now try the 'slow way' : maybe the object is an 'OLE' object
  1786. // that knows about it's client site:
  1787. hr = pUnk->QueryInterface( IID_IOleObject, (void**)&pOleObject );
  1788. if( SUCCEEDED(hr) )
  1789. {
  1790. IOleClientSite * pClientSite = 0;
  1791. hr = pOleObject->GetClientSite(&pClientSite);
  1792. if( SUCCEEDED(hr) )
  1793. {
  1794. // Now see if we have a service provider at that site
  1795. hr = pClientSite->QueryInterface
  1796. ( IID_IServiceProvider,
  1797. (void**)&pServiceProvider );
  1798. }
  1799. if( pClientSite )
  1800. pClientSite->Release();
  1801. }
  1802. else
  1803. {
  1804. // Ok, it's not an OLE object, maybe it's one of these
  1805. // new fangled 'ObjectWithSites':
  1806. IObjectWithSite * pObjWithSite = 0;
  1807. hr = pUnk->QueryInterface( IID_IObjectWithSite,
  1808. (void**)&pObjWithSite );
  1809. if( SUCCEEDED(hr) )
  1810. {
  1811. // Now see if we have a service provider at that site
  1812. hr = pObjWithSite->GetSite(IID_IServiceProvider,
  1813. (void**)&pServiceProvider);
  1814. }
  1815. if( pObjWithSite )
  1816. pObjWithSite->Release();
  1817. }
  1818. if( pOleObject )
  1819. pOleObject->Release();
  1820. }
  1821. // BUGBUG: In the code above we stop looking at one level up --
  1822. // this may be too harsh and we should loop on client sites
  1823. // until we get to the top...
  1824. if( !pServiceProvider )
  1825. hr = E_UNEXPECTED;
  1826. // Ok, we have a service provider, let's see if BindHost is
  1827. // available. (Here there is some upward delegation going on
  1828. // via service provider).
  1829. if( SUCCEEDED(hr) )
  1830. hr = pServiceProvider->QueryService( SID_SBindHost, IID_IBindHost,
  1831. (void**)&pBindHost );
  1832. if( pServiceProvider )
  1833. pServiceProvider->Release();
  1834. pmkr = 0;
  1835. }
  1836. if (pBindHost)
  1837. {
  1838. // This allows the container to actually drive the download
  1839. // by creating it's own moniker.
  1840. hr = pBindHost->CreateMoniker( LPOLESTR(pwzURL),NULL, &pmkr,0 );
  1841. if( SUCCEEDED(hr) )
  1842. {
  1843. // This allows containers to hook the download for
  1844. // doing progress and aborting
  1845. hr = pBindHost->MonikerBindToStorage(pmkr, NULL, pBSCB, IID_IStream,(void**)&pstrm);
  1846. }
  1847. pBindHost->Release();
  1848. }
  1849. else
  1850. {
  1851. // If you are here, then either the caller didn't pass
  1852. // a 'caller' pointer or the caller is not in a BindHost
  1853. // friendly environment.
  1854. hr = CreateURLMoniker( 0, pwzURL, &pmkr );
  1855. if( SUCCEEDED(hr) )
  1856. {
  1857. hr = CreateAsyncBindCtx( 0,pBSCB,0, &pBndCtx );
  1858. }
  1859. if (SUCCEEDED(hr))
  1860. {
  1861. hr = pmkr->BindToStorage( pBndCtx, NULL, IID_IStream, (void**)&pstrm );
  1862. }
  1863. }
  1864. if( pstrm )
  1865. pstrm->Release();
  1866. if( pmkr )
  1867. pmkr->Release();
  1868. if( pBndCtx )
  1869. pBndCtx->Release();
  1870. PerfDbgLog1(tagTransApi, NULL, "-URLDownloadW (hr:%lx)", hr);
  1871. DEBUG_LEAVE_API(hr);
  1872. return hr;
  1873. }
  1874. //+---------------------------------------------------------------------------
  1875. //
  1876. // Function: FindMimeFromData
  1877. //
  1878. // Synopsis:
  1879. //
  1880. // Arguments: [pBC] --
  1881. // [pwzURL] --
  1882. // [pBuffer] --
  1883. // [cbSize] --
  1884. // [dwReserved] --
  1885. //
  1886. // Returns:
  1887. //
  1888. // History: 3-28-97 JohannP (Johann Posch) Created
  1889. //
  1890. // Notes:
  1891. //
  1892. //----------------------------------------------------------------------------
  1893. STDAPI FindMimeFromData(
  1894. LPBC pBC, // bind context - can be NULL
  1895. LPCWSTR pwzUrl, // url - can be null
  1896. LPVOID pBuffer, // buffer with data to sniff - can be null (pwzUrl must be valid)
  1897. DWORD cbSize, // size of buffer
  1898. LPCWSTR pwzMimeProposed, // proposed mime if - can be null
  1899. DWORD dwMimeFlags, // will be determined
  1900. LPWSTR *ppwzMimeOut, // the suggested mime
  1901. DWORD dwReserved) // must be 0
  1902. {
  1903. DEBUG_ENTER_API((DBG_API,
  1904. Hresult,
  1905. "FindMimeFromData",
  1906. "%#x, %.80wq, %#x, %#x, %.80wq, %#x, %.80wq, %#x",
  1907. pBC, pwzUrl, pBuffer, cbSize, pwzMimeProposed, dwMimeFlags, ppwzMimeOut, dwReserved
  1908. ));
  1909. LPCWSTR wzMimeFromData = 0;
  1910. HRESULT hr = E_FAIL;
  1911. PerfDbgLog1(tagTransApi, NULL, "+FindMimeFromData (sugg: %ws)", pwzMimeProposed ? pwzMimeProposed : L"NULL");
  1912. if ( !ppwzMimeOut
  1913. || (!pwzUrl && !pBuffer))
  1914. {
  1915. hr = E_INVALIDARG;
  1916. }
  1917. else if( pBuffer || pwzMimeProposed )
  1918. {
  1919. CContentAnalyzer ca;
  1920. wzMimeFromData = ca.FindMimeFromData(pwzUrl,(char*) pBuffer, cbSize, pwzMimeProposed, dwMimeFlags);
  1921. if (wzMimeFromData)
  1922. {
  1923. *ppwzMimeOut = OLESTRDuplicate(wzMimeFromData);
  1924. if (*ppwzMimeOut)
  1925. {
  1926. hr = NOERROR;
  1927. }
  1928. else
  1929. {
  1930. hr = E_OUTOFMEMORY;
  1931. }
  1932. }
  1933. }
  1934. else
  1935. {
  1936. // file extension is the only solution
  1937. LPSTR pszExt = NULL;
  1938. CHAR szUrl[MAX_PATH];
  1939. CHAR szMime[MAX_PATH];
  1940. DWORD cbMime = MAX_PATH;
  1941. W2A(pwzUrl, szUrl, MAX_PATH);
  1942. pszExt = FindFileExtension(szUrl);
  1943. if( pszExt )
  1944. {
  1945. hr = GetMimeFromExt(pszExt, szMime, &cbMime);
  1946. }
  1947. else
  1948. {
  1949. hr = E_FAIL;
  1950. }
  1951. if( SUCCEEDED(hr) )
  1952. {
  1953. *ppwzMimeOut = DupA2W(szMime);
  1954. if (*ppwzMimeOut)
  1955. {
  1956. hr = NOERROR;
  1957. }
  1958. else
  1959. {
  1960. hr = E_OUTOFMEMORY;
  1961. }
  1962. }
  1963. }
  1964. PerfDbgLog1(tagTransApi, NULL, "-FindMimeFromData (actual: %ws)", wzMimeFromData ? wzMimeFromData : L"NULL" );
  1965. DEBUG_LEAVE_API(hr);
  1966. return hr;
  1967. }
  1968. //+---------------------------------------------------------------------------
  1969. //
  1970. // Function: CoInternetParseUrl
  1971. //
  1972. // Synopsis:
  1973. //
  1974. // Arguments: [pwzUrl] --
  1975. // [ParseAction] --
  1976. // [dwFlags] --
  1977. // [pszResult] --
  1978. // [cchResult] --
  1979. // [dwReserved] --
  1980. //
  1981. // Returns:
  1982. //
  1983. // History: 4-13-1997 JohannP (Johann Posch) Created
  1984. //
  1985. // Notes:
  1986. //
  1987. //----------------------------------------------------------------------------
  1988. STDAPI CoInternetParseUrl(
  1989. LPCWSTR pwzUrl,
  1990. PARSEACTION ParseAction,
  1991. DWORD dwFlags,
  1992. LPWSTR pszResult,
  1993. DWORD cchResult,
  1994. DWORD *pcchResult,
  1995. DWORD dwReserved
  1996. )
  1997. {
  1998. DEBUG_ENTER_API((DBG_API,
  1999. Hresult,
  2000. "CoInternetParseUrl",
  2001. "%.80wq, %#x, %#x, %#x, %#x, %#x, %#x",
  2002. pwzUrl, ParseAction, dwFlags, pszResult, cchResult, pcchResult, dwReserved
  2003. ));
  2004. PerfDbgLog(tagTransApi, NULL, "+CoInternetParseUrl");
  2005. COInetSession *pOInetSession = 0;
  2006. HRESULT hr = INET_E_DEFAULT_ACTION;
  2007. if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwzUrl))
  2008. {
  2009. hr = GetCOInetSession(0, &pOInetSession,0);
  2010. if (hr == NOERROR)
  2011. {
  2012. hr = pOInetSession->ParseUrl(pwzUrl, ParseAction, dwFlags, pszResult, cchResult, pcchResult, dwReserved);
  2013. pOInetSession->Release();
  2014. }
  2015. }
  2016. if (hr == INET_E_DEFAULT_ACTION)
  2017. {
  2018. hr = E_FAIL;
  2019. switch (ParseAction)
  2020. {
  2021. case PARSE_CANONICALIZE :
  2022. *pcchResult = cchResult;
  2023. hr = UrlCanonicalizeW(pwzUrl, pszResult, pcchResult, dwFlags);
  2024. break;
  2025. case PARSE_SCHEMA :
  2026. *pcchResult = cchResult;
  2027. hr = UrlGetPartW(pwzUrl, pszResult, pcchResult, URL_PART_SCHEME, 0);
  2028. break;
  2029. break;
  2030. case PARSE_SITE :
  2031. break;
  2032. case PARSE_DOMAIN :
  2033. *pcchResult = cchResult;
  2034. hr = UrlGetPartW(pwzUrl, pszResult, pcchResult, URL_PART_HOSTNAME, 0);
  2035. TransAssert(hr != E_POINTER);
  2036. break;
  2037. break;
  2038. case PARSE_FRIENDLY :
  2039. break;
  2040. case PARSE_SECURITY_URL :
  2041. // should return "schema:host" for all protocols
  2042. break;
  2043. case PARSE_ROOTDOCUMENT :
  2044. {
  2045. PARSEDURLW puW;
  2046. puW.cbSize = sizeof(PARSEDURLW);
  2047. if (SUCCEEDED(ParseURLW(pwzUrl, &puW)) && IsHierarchicalScheme(puW.nScheme))
  2048. {
  2049. DWORD cchRequired = 1;
  2050. // The first URLGetPartW call is just to get the number of chars required for the hostname.
  2051. // This is not as efficient but keeps the code simpler.
  2052. if ((UrlGetPartW(pwzUrl, pszResult, &cchRequired, URL_PART_HOSTNAME, 0)) == E_POINTER)
  2053. {
  2054. cchRequired += (puW.cchProtocol + 3);
  2055. if (cchResult >= cchRequired)
  2056. {
  2057. LPWSTR pszCopyTo = pszResult;
  2058. *pcchResult = cchRequired - 1; // don't include terminating NULL char.
  2059. memcpy(pszCopyTo, puW.pszProtocol, puW.cchProtocol * sizeof(WCHAR));
  2060. pszCopyTo += puW.cchProtocol;
  2061. memcpy(pszCopyTo, L"://", 3 * sizeof(WCHAR));
  2062. pszCopyTo += 3;
  2063. DWORD cchHost = (DWORD) (cchResult - (pszCopyTo - pszResult));
  2064. hr = UrlGetPartW(pwzUrl, pszCopyTo, &cchHost, URL_PART_HOSTNAME, 0);
  2065. }
  2066. else
  2067. {
  2068. *pcchResult = cchRequired;
  2069. hr = E_OUTOFMEMORY;
  2070. }
  2071. }
  2072. }
  2073. }
  2074. break;
  2075. case PARSE_DOCUMENT :
  2076. break;
  2077. case PARSE_ANCHOR :
  2078. break;
  2079. case PARSE_ENCODE :
  2080. case PARSE_UNESCAPE :
  2081. *pcchResult = cchResult;
  2082. hr = UrlUnescapeW((LPWSTR)pwzUrl, pszResult, pcchResult, dwFlags);
  2083. break;
  2084. case PARSE_ESCAPE :
  2085. case PARSE_DECODE :
  2086. *pcchResult = cchResult;
  2087. hr = UrlEscapeW(pwzUrl, pszResult, pcchResult, dwFlags);
  2088. break;
  2089. case PARSE_PATH_FROM_URL :
  2090. *pcchResult = cchResult;
  2091. hr = PathCreateFromUrlW(pwzUrl, pszResult, pcchResult, dwFlags);
  2092. break;
  2093. case PARSE_URL_FROM_PATH :
  2094. *pcchResult = cchResult;
  2095. hr = UrlCreateFromPathW(pwzUrl, pszResult, pcchResult, dwFlags);
  2096. break;
  2097. case PARSE_LOCATION :
  2098. {
  2099. hr = E_FAIL;
  2100. *pcchResult = 0;
  2101. LPCWSTR pwzStr = UrlGetLocationW(pwzUrl); //, pszResult, pcchResult, dwFlags);
  2102. if (pwzStr)
  2103. {
  2104. DWORD dwlen = wcslen(pwzStr);
  2105. if (dwlen < cchResult)
  2106. {
  2107. wcscpy(pszResult, pwzStr);
  2108. *pcchResult = dwlen;
  2109. hr = NOERROR;
  2110. }
  2111. else
  2112. {
  2113. // buffer too small
  2114. }
  2115. }
  2116. }
  2117. break;
  2118. case PARSE_MIME :
  2119. default:
  2120. hr = E_FAIL;
  2121. }
  2122. }
  2123. PerfDbgLog1(tagTransApi, NULL, "-CoInternetParseUrl (hr:%lx)", hr);
  2124. DEBUG_LEAVE_API(hr);
  2125. return hr;
  2126. }
  2127. //+---------------------------------------------------------------------------
  2128. //
  2129. // Method: IsHierarchicalScheme
  2130. //
  2131. // Synopsis:
  2132. //
  2133. // Arguments: [dwScheme] --
  2134. //
  2135. // Returns:
  2136. //
  2137. // History: 6-16-1997 Sanjays (Sanjay Shenoy) Created
  2138. //
  2139. // Notes:
  2140. //
  2141. //----------------------------------------------------------------------------
  2142. BOOL IsHierarchicalScheme(DWORD dwScheme)
  2143. {
  2144. DEBUG_ENTER((DBG_TRANSDAT,
  2145. Bool,
  2146. "IsHierarchicalScheme",
  2147. "%#x",
  2148. dwScheme
  2149. ));
  2150. BOOL bReturn;
  2151. switch ( dwScheme )
  2152. {
  2153. case URL_SCHEME_HTTP:
  2154. case URL_SCHEME_FTP:
  2155. case URL_SCHEME_HTTPS:
  2156. case URL_SCHEME_NEWS:
  2157. case URL_SCHEME_GOPHER:
  2158. case URL_SCHEME_NNTP:
  2159. case URL_SCHEME_TELNET:
  2160. case URL_SCHEME_SNEWS:
  2161. bReturn = TRUE;
  2162. break;
  2163. default:
  2164. bReturn = FALSE;
  2165. break;
  2166. }
  2167. DEBUG_LEAVE(bReturn);
  2168. return bReturn;
  2169. }
  2170. //+---------------------------------------------------------------------------
  2171. //
  2172. // Method: IsHierarchicalUrl
  2173. //
  2174. // Synopsis:
  2175. //
  2176. // Arguments: [pwszUrl] --
  2177. //
  2178. // Returns:
  2179. //
  2180. // History: 6-16-1997 Sanjays (Sanjay Shenoy) Created
  2181. //
  2182. // Notes:
  2183. //
  2184. //----------------------------------------------------------------------------
  2185. BOOL IsHierarchicalUrl(LPCWSTR pwszUrl)
  2186. {
  2187. DEBUG_ENTER((DBG_TRANSDAT,
  2188. Bool,
  2189. "IsHierarchicalUrl",
  2190. "%.80wq",
  2191. pwszUrl
  2192. ));
  2193. DWORD dwScheme = URL_SCHEME_INVALID;
  2194. if(pwszUrl)
  2195. {
  2196. PARSEDURLW pu;
  2197. pu.cbSize = sizeof(pu);
  2198. if(SUCCEEDED(ParseURLW(pwszUrl, &pu)))
  2199. dwScheme = pu.nScheme;
  2200. }
  2201. BOOL fRet = IsHierarchicalScheme(dwScheme);
  2202. DEBUG_LEAVE(fRet);
  2203. return fRet;
  2204. }
  2205. //+---------------------------------------------------------------------------
  2206. //
  2207. // Method: CoInternetGetSecurityUrl
  2208. //
  2209. // Synopsis:
  2210. //
  2211. // Arguments: [pwszUrl] --
  2212. // [ppszSecUrl] --
  2213. // [psuAction]
  2214. // [dwReserved]
  2215. // Returns:
  2216. //
  2217. // History: 4-28-1997 Sanjays (Sanjay Shenoy) Created
  2218. //
  2219. // Notes:
  2220. //
  2221. //----------------------------------------------------------------------------
  2222. STDAPI CoInternetGetSecurityUrl(
  2223. LPCWSTR pwszUrl,
  2224. LPWSTR *ppwszSecUrl, // out argument.
  2225. PSUACTION psuAction,
  2226. DWORD dwReserved
  2227. )
  2228. {
  2229. DEBUG_ENTER_API((DBG_API,
  2230. Hresult,
  2231. "CoInternetGetSecurityUrl",
  2232. "%.80wq, %#x, %#x, %#x",
  2233. pwszUrl, ppwszSecUrl, psuAction, dwReserved
  2234. ));
  2235. PerfDbgLog(tagTransApi, NULL, "+CoInternetGetSecurityUrl");
  2236. COInetSession *pOInetSession = NULL;
  2237. if (pwszUrl == NULL || ppwszSecUrl == NULL)
  2238. {
  2239. DEBUG_LEAVE_API(E_INVALIDARG);
  2240. return E_INVALIDARG;
  2241. }
  2242. if (psuAction != PSU_DEFAULT && psuAction != PSU_SECURITY_URL_ONLY)
  2243. {
  2244. DEBUG_LEAVE_API(E_NOTIMPL);
  2245. return E_NOTIMPL;
  2246. }
  2247. LPWSTR pwszSecUrl = (LPWSTR) pwszUrl;
  2248. *ppwszSecUrl = NULL;
  2249. BOOL bAllocSecUrl = FALSE; // Should we free pwszSecUrl?
  2250. HRESULT hr = S_OK;
  2251. // Step 1
  2252. // If this is a custom protocol, give it a chance to return back the
  2253. // security URL first.
  2254. hr = GetCOInetSession(0, &pOInetSession, 0);
  2255. if (hr == NOERROR)
  2256. {
  2257. DWORD dwId;
  2258. // It is important to loop here. The URL returned by a pluggable protocol by calling
  2259. // PARSE_SECURITY_URL might be another pluggable protocol.
  2260. while ( !g_bShortcircuitKnownProtocols || ((dwId = IsKnownProtocol(pwszSecUrl)) == DLD_PROTOCOL_NONE)
  2261. || (dwId == DLD_PROTOCOL_STREAM)) // Special case mk: hack since there could be a
  2262. // namespace handler defined for it.
  2263. {
  2264. // Allocate as much memory as the url. This should be a good upper limit in most all cases.
  2265. DWORD cchIn = lstrlenW(pwszSecUrl) + 1;
  2266. DWORD cchOut = 0;
  2267. LPWSTR pwszTmp = new WCHAR[cchIn];
  2268. if (pwszTmp != NULL)
  2269. hr = pOInetSession->ParseUrl(pwszSecUrl, PARSE_SECURITY_URL, 0, pwszTmp, cchIn, &cchOut, 0);
  2270. else
  2271. hr = E_OUTOFMEMORY;
  2272. // Not enough memory.
  2273. if (hr == S_FALSE)
  2274. {
  2275. // Plug prot claims it needs more memory but asks us for a buffer of a
  2276. // smaller size.
  2277. TransAssert(cchIn < cchOut);
  2278. if (cchIn >= cchOut)
  2279. {
  2280. hr = E_UNEXPECTED;
  2281. }
  2282. else
  2283. {
  2284. cchIn = cchOut;
  2285. delete [] pwszTmp;
  2286. pwszTmp = new WCHAR[cchIn];
  2287. if ( pwszTmp != NULL )
  2288. {
  2289. hr = pOInetSession->ParseUrl(pwszSecUrl, PARSE_SECURITY_URL, 0, pwszTmp, cchIn, &cchOut, 0);
  2290. TransAssert(hr != S_FALSE);
  2291. }
  2292. else
  2293. {
  2294. hr = E_OUTOFMEMORY;
  2295. }
  2296. }
  2297. }
  2298. if (SUCCEEDED(hr))
  2299. {
  2300. // If for some reason the pluggable protocol just returned back
  2301. // the original string, don't go into an infinite loop.
  2302. if (0 == StrCmpW(pwszSecUrl, pwszTmp))
  2303. {
  2304. delete [] pwszTmp;
  2305. break;
  2306. }
  2307. if (bAllocSecUrl)
  2308. delete [] pwszSecUrl;
  2309. pwszSecUrl = pwszTmp;
  2310. bAllocSecUrl = TRUE;
  2311. }
  2312. else
  2313. {
  2314. if (hr == INET_E_DEFAULT_ACTION || hr == E_NOTIMPL)
  2315. {
  2316. // This implies the pluggable protocol just wants us to use the
  2317. // base url as the security url.
  2318. hr = S_OK;
  2319. }
  2320. delete [] pwszTmp;
  2321. break;
  2322. }
  2323. }
  2324. }
  2325. else
  2326. {
  2327. // Some protocols don't support the IInternetProtocolInfo interface.
  2328. // We will do the best we can.
  2329. hr = S_OK;
  2330. }
  2331. // End of Step 1.
  2332. // At this point we have the security URL. We are done if the PSUACTION
  2333. // indicated we should only be getting the security URL.
  2334. if (psuAction == PSU_SECURITY_URL_ONLY)
  2335. {
  2336. if (SUCCEEDED(hr))
  2337. {
  2338. // If we didn't allocate memory for pwszSecUrl i.e. it is the same as the
  2339. // input string, we have to do that before returning it back.
  2340. if (!bAllocSecUrl)
  2341. {
  2342. *ppwszSecUrl = new WCHAR [(lstrlenW(pwszSecUrl) + 1)];
  2343. if (*ppwszSecUrl != NULL)
  2344. StrCpyW(*ppwszSecUrl, pwszSecUrl);
  2345. else
  2346. hr = E_OUTOFMEMORY;
  2347. }
  2348. else
  2349. {
  2350. *ppwszSecUrl = pwszSecUrl;
  2351. }
  2352. }
  2353. }
  2354. else
  2355. {
  2356. TransAssert(psuAction == PSU_DEFAULT);
  2357. // Step 2.
  2358. // If URL after Step 1 is still not well known ask the protocol handler to simplify
  2359. // it it is well known call UrlGetPart in shlwapi.
  2360. LPWSTR pwszRet = NULL;
  2361. if (SUCCEEDED(hr))
  2362. {
  2363. if (pwszSecUrl == NULL)
  2364. {
  2365. TransAssert(FALSE); // This has to be due to a bug in Step 1.
  2366. pwszSecUrl = (LPWSTR) pwszUrl; // recover as best as we can.
  2367. }
  2368. // Since Step 2 is just supposed to strip off parts we can safely assume that
  2369. // the out string will be smaller than the input string.
  2370. DWORD cchIn = lstrlenW(pwszSecUrl) + 1;
  2371. DWORD cchOut = 0;
  2372. pwszRet = new WCHAR[cchIn];
  2373. if (pwszRet == NULL)
  2374. {
  2375. hr = E_OUTOFMEMORY;
  2376. }
  2377. else if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwszSecUrl))
  2378. {
  2379. TransAssert(pOInetSession);
  2380. if (pOInetSession)
  2381. hr = pOInetSession->ParseUrl(pwszSecUrl, PARSE_SECURITY_DOMAIN, 0, pwszRet, cchIn, &cchOut, 0);
  2382. else
  2383. hr = INET_E_DEFAULT_ACTION ; // no protocol info ==> use default
  2384. TransAssert(hr != S_FALSE); // Should never require more memory
  2385. if (hr == INET_E_DEFAULT_ACTION || hr == E_NOTIMPL)
  2386. {
  2387. StrCpyW(pwszRet, pwszSecUrl);
  2388. hr = S_OK;
  2389. }
  2390. }
  2391. else // Known protocol call shlwapi.
  2392. {
  2393. if (IsHierarchicalUrl(pwszSecUrl))
  2394. {
  2395. hr = UrlGetPartW(pwszSecUrl, pwszRet, &cchIn, URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME);
  2396. TransAssert(hr != E_POINTER);
  2397. }
  2398. else
  2399. {
  2400. // Just copy the string from step 1, we can't do any meaningful processing.
  2401. hr = INET_E_DEFAULT_ACTION;
  2402. }
  2403. // If UrlGetPart didn't process it, just pass the original string back.
  2404. if (!SUCCEEDED(hr))
  2405. {
  2406. hr = S_OK;
  2407. StrCpyW(pwszRet, pwszSecUrl);
  2408. }
  2409. }
  2410. }
  2411. // End of Step 2.
  2412. if (bAllocSecUrl)
  2413. delete [] pwszSecUrl;
  2414. if (SUCCEEDED(hr))
  2415. {
  2416. TransAssert(pwszRet != NULL);
  2417. *ppwszSecUrl = pwszRet;
  2418. }
  2419. }
  2420. PerfDbgLog1(tagTransApi, NULL, "-CoInternetGetSecurityUrl (hr:%lx)", hr);
  2421. DEBUG_LEAVE_API(hr);
  2422. return hr;
  2423. }
  2424. //+---------------------------------------------------------------------------
  2425. //
  2426. // Function: CoInternetCombineUrl
  2427. //
  2428. // Synopsis:
  2429. //
  2430. // Arguments: [pwzBaseUrl] --
  2431. // [pwzRelativeUrl] --
  2432. // [dwFlags] --
  2433. // [pszResult] --
  2434. // [cchResult] --
  2435. // [dwReserved] --
  2436. //
  2437. // Returns:
  2438. //
  2439. // History: 4-13-1997 JohannP (Johann Posch) Created
  2440. //
  2441. // Notes:
  2442. //
  2443. //----------------------------------------------------------------------------
  2444. STDAPI CoInternetCombineUrl(
  2445. LPCWSTR pwzBaseUrl,
  2446. LPCWSTR pwzRelativeUrl,
  2447. DWORD dwFlags,
  2448. LPWSTR pszResult,
  2449. DWORD cchResult,
  2450. DWORD *pcchResult,
  2451. DWORD dwReserved
  2452. )
  2453. {
  2454. DEBUG_ENTER_API((DBG_API,
  2455. Hresult,
  2456. "CoInternetCombineUrl",
  2457. "%.80wq, %.80wq, %#x, %#x, %#x, %#x, %#x",
  2458. pwzBaseUrl, pwzRelativeUrl, dwFlags, pszResult, cchResult, pcchResult, dwReserved
  2459. ));
  2460. PerfDbgLog(tagTransApi, NULL, "+CoInternetCombineUrl");
  2461. COInetSession *pOInetSession = 0;
  2462. HRESULT hr = INET_E_DEFAULT_ACTION;
  2463. if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwzBaseUrl))
  2464. {
  2465. hr = GetCOInetSession(0, &pOInetSession,0);
  2466. if (hr == NOERROR)
  2467. {
  2468. hr = pOInetSession->CombineUrl(pwzBaseUrl, pwzRelativeUrl, dwFlags, pszResult, cchResult, pcchResult, dwReserved);
  2469. pOInetSession->Release();
  2470. }
  2471. }
  2472. if (hr == INET_E_DEFAULT_ACTION)
  2473. {
  2474. DWORD dwRes = cchResult;
  2475. hr = UrlCombineW(pwzBaseUrl, pwzRelativeUrl, pszResult, &dwRes, dwFlags);
  2476. *pcchResult = dwRes;
  2477. }
  2478. PerfDbgLog1(tagTransApi, NULL, "-CoInternetCombineUrl (hr:%lx)", hr);
  2479. DEBUG_LEAVE_API(hr);
  2480. return hr;
  2481. }
  2482. //+---------------------------------------------------------------------------
  2483. //
  2484. // Function: CoInternetCompareUrl
  2485. //
  2486. // Synopsis:
  2487. //
  2488. // Arguments: [pwzUrl1] --
  2489. // [pwzUrl2] --
  2490. // [dwFlags] --
  2491. //
  2492. // Returns:
  2493. //
  2494. // History: 4-13-1997 JohannP (Johann Posch) Created
  2495. //
  2496. // Notes:
  2497. //
  2498. //----------------------------------------------------------------------------
  2499. STDAPI CoInternetCompareUrl(
  2500. LPCWSTR pwzUrl1,
  2501. LPCWSTR pwzUrl2,
  2502. DWORD dwFlags
  2503. )
  2504. {
  2505. DEBUG_ENTER_API((DBG_API,
  2506. Hresult,
  2507. "CoInternetCompareUrl",
  2508. "%.80wq, %.80wq, %#x",
  2509. pwzUrl1, pwzUrl2, dwFlags
  2510. ));
  2511. PerfDbgLog(tagTransApi, NULL, "+CoInternetCompareUrl");
  2512. COInetSession *pOInetSession = 0;
  2513. HRESULT hr = INET_E_DEFAULT_ACTION;
  2514. if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwzUrl1))
  2515. {
  2516. hr = GetCOInetSession(0, &pOInetSession,0);
  2517. if (hr == NOERROR)
  2518. {
  2519. hr = pOInetSession->CompareUrl(pwzUrl1, pwzUrl2, dwFlags);
  2520. pOInetSession->Release();
  2521. }
  2522. }
  2523. if (hr == INET_E_DEFAULT_ACTION)
  2524. {
  2525. int iRes = UrlCompareW(pwzUrl1, pwzUrl2, dwFlags & CF_INGNORE_SLASH);
  2526. if (iRes == 0)
  2527. {
  2528. hr = S_OK;
  2529. }
  2530. else
  2531. {
  2532. hr = S_FALSE;
  2533. }
  2534. }
  2535. PerfDbgLog1(tagTransApi, NULL, "-CoInternetCompareUrl (hr:%lx)", hr);
  2536. DEBUG_LEAVE_API(hr);
  2537. return hr;
  2538. }
  2539. //+---------------------------------------------------------------------------
  2540. //
  2541. // Function: CoInternetQueryInfo
  2542. //
  2543. // Synopsis:
  2544. //
  2545. // Arguments: [pwzUrl] --
  2546. // [dwOptions] --
  2547. // [pvBuffer] --
  2548. // [cbBuffer] --
  2549. // [pcbBuffer] --
  2550. // [dwReserved] --
  2551. //
  2552. // Returns:
  2553. //
  2554. // History: 4-14-1997 JohannP (Johann Posch) Created
  2555. //
  2556. // Notes:
  2557. //
  2558. //----------------------------------------------------------------------------
  2559. STDAPI CoInternetQueryInfo(
  2560. LPCWSTR pwzUrl,
  2561. QUERYOPTION QueryOption,
  2562. DWORD dwQueryFlags,
  2563. LPVOID pvBuffer,
  2564. DWORD cbBuffer,
  2565. DWORD *pcbBuffer,
  2566. DWORD dwReserved
  2567. )
  2568. {
  2569. DEBUG_ENTER_API((DBG_API,
  2570. Hresult,
  2571. "CoInternetQueryInfo",
  2572. "%.80wq, %#x, %#x, %#x, %#x, %#x, %#x",
  2573. pwzUrl, QueryOption, dwQueryFlags, pvBuffer, cbBuffer, pcbBuffer, dwReserved
  2574. ));
  2575. PerfDbgLog(tagTransApi, NULL, "+CoInternetQueryInfo");
  2576. COInetSession *pOInetSession = 0;
  2577. HRESULT hr = INET_E_DEFAULT_ACTION;
  2578. if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwzUrl))
  2579. {
  2580. hr = GetCOInetSession(0, &pOInetSession,0);
  2581. if (hr == NOERROR)
  2582. {
  2583. hr = pOInetSession->QueryInfo(pwzUrl, QueryOption, dwQueryFlags, pvBuffer, cbBuffer, pcbBuffer, dwReserved);
  2584. pOInetSession->Release();
  2585. }
  2586. }
  2587. if (hr == INET_E_DEFAULT_ACTION)
  2588. {
  2589. switch (QueryOption)
  2590. {
  2591. case QUERY_USES_NETWORK:
  2592. case QUERY_USES_CACHE:
  2593. {
  2594. if (!pvBuffer || cbBuffer < sizeof(DWORD))
  2595. {
  2596. DEBUG_LEAVE_API(E_FAIL);
  2597. return E_FAIL;
  2598. }
  2599. if (pcbBuffer)
  2600. {
  2601. *pcbBuffer = sizeof(DWORD);
  2602. }
  2603. switch (GetUrlScheme(pwzUrl))
  2604. {
  2605. case URL_SCHEME_FILE:
  2606. case URL_SCHEME_NEWS:
  2607. case URL_SCHEME_NNTP:
  2608. case URL_SCHEME_MK:
  2609. case URL_SCHEME_SHELL:
  2610. case URL_SCHEME_SNEWS:
  2611. case URL_SCHEME_LOCAL:
  2612. *((DWORD *)pvBuffer) = FALSE;
  2613. DEBUG_LEAVE_API(S_OK);
  2614. return S_OK;
  2615. case URL_SCHEME_FTP:
  2616. case URL_SCHEME_HTTP:
  2617. case URL_SCHEME_GOPHER:
  2618. case URL_SCHEME_TELNET:
  2619. case URL_SCHEME_WAIS:
  2620. case URL_SCHEME_HTTPS:
  2621. *((DWORD *)pvBuffer) = TRUE;
  2622. DEBUG_LEAVE_API(S_OK);
  2623. return S_OK;
  2624. default:
  2625. DEBUG_LEAVE_API(E_FAIL);
  2626. return E_FAIL;
  2627. }
  2628. }
  2629. break;
  2630. case QUERY_IS_CACHED:
  2631. case QUERY_IS_INSTALLEDENTRY:
  2632. case QUERY_IS_CACHED_OR_MAPPED:
  2633. {
  2634. char szUrl[MAX_URL_SIZE];
  2635. DWORD dwFlags = 0;
  2636. if(QueryOption == QUERY_IS_INSTALLEDENTRY)
  2637. {
  2638. dwFlags = INTERNET_CACHE_FLAG_INSTALLED_ENTRY;
  2639. }
  2640. else if(QueryOption == QUERY_IS_CACHED_OR_MAPPED)
  2641. {
  2642. dwFlags = INTERNET_CACHE_FLAG_ENTRY_OR_MAPPING;
  2643. }
  2644. // Otherwise let the flags remain as 0
  2645. if (!pvBuffer || cbBuffer < sizeof(DWORD))
  2646. {
  2647. DEBUG_LEAVE_API(E_FAIL);
  2648. return E_FAIL;
  2649. }
  2650. if (pcbBuffer)
  2651. {
  2652. *pcbBuffer = sizeof(DWORD);
  2653. }
  2654. W2A(pwzUrl, szUrl, MAX_URL_SIZE);
  2655. char *pchLoc = StrChr(szUrl, TEXT('#'));
  2656. if (pchLoc)
  2657. *pchLoc = TEXT('\0');
  2658. *((DWORD *)pvBuffer) = GetUrlCacheEntryInfoEx(szUrl, NULL, NULL, NULL, NULL, NULL, dwFlags);
  2659. DEBUG_LEAVE_API(S_OK);
  2660. return S_OK;
  2661. }
  2662. break;
  2663. case QUERY_CAN_NAVIGATE:
  2664. {
  2665. //Bug#107130 - If we couldn't find the NEWS protocol, or it refused to answer this query,
  2666. // trident assumes that it CAN navigate, and leads to above bug.
  2667. // If we couldn't load this protocol, or it delegated to us, we now give Trident what they want.
  2668. if (URL_SCHEME_NEWS == GetUrlScheme(pwzUrl))
  2669. {
  2670. if (!pvBuffer || cbBuffer < sizeof(DWORD))
  2671. {
  2672. DEBUG_LEAVE_API(E_FAIL);
  2673. return E_FAIL;
  2674. }
  2675. if (pcbBuffer)
  2676. {
  2677. *pcbBuffer = sizeof(DWORD);
  2678. }
  2679. *((DWORD *)pvBuffer) = FALSE;
  2680. DEBUG_LEAVE_API(S_OK);
  2681. return S_OK;
  2682. }
  2683. }
  2684. break;
  2685. default:
  2686. // do not know what do to
  2687. hr = E_FAIL;
  2688. }
  2689. }
  2690. PerfDbgLog1(tagTransApi, NULL, "-CoInternetQueryInfo (hr:%lx)", hr);
  2691. DEBUG_LEAVE_API(hr);
  2692. return hr;
  2693. }
  2694. //+---------------------------------------------------------------------------
  2695. //
  2696. // Function: CoInternetGetProtocolFlags
  2697. //
  2698. // Synopsis:
  2699. //
  2700. // Arguments: [pwzUrl] --
  2701. // [pdwFlags] --
  2702. // [dwReserved] --
  2703. //
  2704. // Returns:
  2705. //
  2706. // History: 4-14-1997 JohannP (Johann Posch) Created
  2707. //
  2708. // Notes:
  2709. //
  2710. //----------------------------------------------------------------------------
  2711. STDAPI CoInternetGetProtocolFlags(
  2712. LPCWSTR pwzUrl,
  2713. DWORD *pdwFlags,
  2714. DWORD dwReserved
  2715. )
  2716. {
  2717. DEBUG_ENTER_API((DBG_API,
  2718. Hresult,
  2719. "CoInternetGetProtocolFlags",
  2720. "%.80wq, %#x, %#x",
  2721. pwzUrl, pdwFlags, dwReserved
  2722. ));
  2723. PerfDbgLog(tagTransApi, NULL, "+CoInternetGetProtocolFlags");
  2724. COInetSession *pOInetSession = 0;
  2725. HRESULT hr = E_NOTIMPL;
  2726. PerfDbgLog1(tagTransApi, NULL, "-CoInternetGetProtocolFlags (hr:%lx)", hr);
  2727. DEBUG_LEAVE_API(hr);
  2728. return hr;
  2729. }
  2730. //+---------------------------------------------------------------------------
  2731. //
  2732. // Function: CoInternetCreateSecurityManager
  2733. //
  2734. // Synopsis:
  2735. //
  2736. // Arguments: [pSP] --
  2737. // [pSM] --
  2738. // [dwReserved] --
  2739. //
  2740. // Returns:
  2741. //
  2742. // History: 4-28-1997 JohannP (Johann Posch) Created
  2743. //
  2744. // Notes:
  2745. //
  2746. //----------------------------------------------------------------------------
  2747. STDAPI CoInternetCreateSecurityManager(IServiceProvider *pSP, IInternetSecurityManager **ppSM, DWORD dwReserved)
  2748. {
  2749. DEBUG_ENTER_API((DBG_API,
  2750. Hresult,
  2751. "CoInternetCreateSecurityManager",
  2752. "%#x, %#x, %#x",
  2753. pSP, ppSM, dwReserved
  2754. ));
  2755. PerfDbgLog(tagTransApi, NULL, "+CoInternetCreateUrlSecurityManager");
  2756. HRESULT hr = NOERROR;
  2757. hr = InternetCreateSecurityManager(0, IID_IInternetSecurityManager, (void **)ppSM, dwReserved);
  2758. PerfDbgLog1(tagTransApi, NULL, "-CoInternetCreateUrlSecurityManager (hr:%lx)", hr);
  2759. DEBUG_LEAVE_API(hr);
  2760. return hr;
  2761. }
  2762. //+---------------------------------------------------------------------------
  2763. //
  2764. // Function: CoInternetCreateZoneManager
  2765. //
  2766. // Synopsis:
  2767. //
  2768. // Arguments: [pSP] --
  2769. // [ppZM] --
  2770. // [dwReserved] --
  2771. //
  2772. // Returns:
  2773. //
  2774. // History: 4-28-1997 JohannP (Johann Posch) Created
  2775. //
  2776. // Notes:
  2777. //
  2778. //----------------------------------------------------------------------------
  2779. STDAPI CoInternetCreateZoneManager(IServiceProvider *pSP, IInternetZoneManager **ppZM, DWORD dwReserved)
  2780. {
  2781. DEBUG_ENTER_API((DBG_API,
  2782. Hresult,
  2783. "CoInternetCreateZoneManager",
  2784. "%#x, %#x, %#x",
  2785. pSP, ppZM, dwReserved
  2786. ));
  2787. PerfDbgLog(tagTransApi, NULL, "+CoInternetCreateUrlZoneManager");
  2788. HRESULT hr;
  2789. hr = InternetCreateZoneManager(0, IID_IInternetZoneManager, (void **) ppZM, dwReserved);
  2790. PerfDbgLog1(tagTransApi, NULL, "-CoInternetCreateUrlZoneManager (hr:%lx)", hr);
  2791. DEBUG_LEAVE_API(hr);
  2792. return hr;
  2793. }
  2794. BOOL PDFNeedProgressiveDownload()
  2795. {
  2796. DEBUG_ENTER((DBG_TRANSDAT,
  2797. Bool,
  2798. "PDFNeedProgressiveDownload",
  2799. NULL
  2800. ));
  2801. HKEY hClsRegEntry;
  2802. CHAR szInProc[CLSIDSTR_MAX + 64];
  2803. CHAR szPath[MAX_PATH];
  2804. long lSize;
  2805. BOOL fRet = TRUE;
  2806. BYTE* pVerBuffer = NULL;
  2807. DWORD cbFileVersionBufSize;
  2808. DWORD dwTemp;
  2809. unsigned uiLength = 0;
  2810. VS_FIXEDFILEINFO *lpVSFixedFileInfo;
  2811. strcpy(szInProc,
  2812. "CLSID\\{CA8A9780-280D-11CF-A24D-444553540000}\\InProcServer32");
  2813. if( ERROR_SUCCESS != RegOpenKey(
  2814. HKEY_CLASSES_ROOT, szInProc, &hClsRegEntry) )
  2815. {
  2816. goto Exit;
  2817. }
  2818. // now we are at HKCR\CLSID\xxx-yyyy\InProcServer32
  2819. // we need to get the path to the ocx
  2820. lSize = MAX_PATH;
  2821. if( ERROR_SUCCESS != RegQueryValue(
  2822. hClsRegEntry, NULL, szPath, &lSize) )
  2823. {
  2824. RegCloseKey(hClsRegEntry);
  2825. goto Exit;
  2826. }
  2827. // done with key
  2828. RegCloseKey(hClsRegEntry);
  2829. // we have the path now
  2830. if((cbFileVersionBufSize = GetFileVersionInfoSize( szPath, &dwTemp)) == 0 )
  2831. {
  2832. goto Exit;
  2833. }
  2834. pVerBuffer = new BYTE[cbFileVersionBufSize];
  2835. if( !pVerBuffer )
  2836. {
  2837. goto Exit;
  2838. }
  2839. if( !GetFileVersionInfo(szPath, 0, cbFileVersionBufSize, pVerBuffer) )
  2840. {
  2841. goto Exit;
  2842. }
  2843. if( !VerQueryValue(
  2844. pVerBuffer, TEXT("\\"),(LPVOID*)&lpVSFixedFileInfo, &uiLength) )
  2845. {
  2846. goto Exit;
  2847. }
  2848. if( lpVSFixedFileInfo->dwFileVersionMS == 0x00010003 &&
  2849. lpVSFixedFileInfo->dwFileVersionLS < 170 )
  2850. {
  2851. // this is 3.0 or 3.01, we should disable progressive download
  2852. fRet = FALSE;
  2853. }
  2854. Exit:
  2855. if( pVerBuffer != NULL)
  2856. delete [] pVerBuffer;
  2857. DEBUG_LEAVE(fRet);
  2858. return fRet;
  2859. }