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.

545 lines
15 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: resprot.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 11-07-1996 JohannP (Johann Posch) Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <urlint.h>
  18. #include <stdio.h>
  19. #include <sem.hxx>
  20. #include <wininet.h>
  21. #include "urlcf.hxx"
  22. #include "protbase.hxx"
  23. #include "resprot.hxx"
  24. #include <tchar.h>
  25. #define MAX_ID 10000
  26. HRESULT LookupProtocolClsIDFromReg(LPCTSTR pszUrl, CLSID *pclsid);
  27. #define SZPROTOCOLROOT "PROTOCOLS\\Handler\\"
  28. #define SZCLASS "CLSID"
  29. #define SZMYPROTOCOL "search"
  30. //+---------------------------------------------------------------------------
  31. //
  32. // Method: CResProtocol::Start
  33. //
  34. // Synopsis:
  35. //
  36. // Arguments: [pwzUrl] --
  37. // [pTrans] --
  38. // [pOIBindInfo] --
  39. // [grfSTI] --
  40. // [dwReserved] --
  41. //
  42. // Returns:
  43. //
  44. // History: 10-29-1996 JohannP (Johann Posch) Created
  45. //
  46. // Notes:
  47. //
  48. //----------------------------------------------------------------------------
  49. STDMETHODIMP CResProtocol::Start(LPCWSTR pwzUrl, IOInetProtocolSink *pTrans, IOInetBindInfo *pOIBindInfo,
  50. DWORD grfSTI, DWORD dwReserved)
  51. {
  52. TransDebugOut((DEB_PROT, "%p _IN CResProtocol::Start\n", this));
  53. HRESULT hr = NOERROR;
  54. CLSID clsid;
  55. TransAssert((!_pProtSink && pOIBindInfo && pTrans));
  56. TransAssert((_pszUrl == NULL));
  57. // have to start the base class to get the bindinfo and the full URL.
  58. hr = CBaseProtocol::Start(pwzUrl,pTrans, pOIBindInfo, grfSTI, dwReserved);
  59. if (hr == NOERROR)
  60. {
  61. // first, check if this is hookable URL.
  62. // return E_USEDEFAULTPROTOCAL if not.
  63. if ((hr = Bind()) == NOERROR)
  64. {
  65. // We need to use the new (cooked) URL if Bind() succeeded.
  66. if ((hr = LookupProtocolClsIDFromReg(_szNewUrl, &clsid)) == NOERROR)
  67. {
  68. IClassFactory *pCF = 0;
  69. hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,IID_IClassFactory, (void**)&pCF);
  70. if (hr == NOERROR)
  71. {
  72. // Perf:
  73. // we might want to move Create/Release of the HTTP protocl handler out of
  74. // Start/Terminate to Create/Release.
  75. hr = pCF->CreateInstance(NULL, IID_IOInetProtocol, (void **)&_pProt);
  76. if (hr == NOERROR)
  77. {
  78. // ???
  79. // We also may need to implement our own IOInetBindInfo so that we
  80. // can give it the new (cooked) BindInfo.
  81. // We need to pass down the new (cooked) URL if Bind() succeeded.
  82. LPWSTR pwzNewUrl = DupA2W(_szNewUrl);
  83. if (pwzNewUrl)
  84. {
  85. hr = _pProt->Start(pwzNewUrl, pTrans, pOIBindInfo, grfSTI, dwReserved);
  86. delete pwzNewUrl;
  87. }
  88. }
  89. pCF->Release();
  90. }
  91. }
  92. }
  93. }
  94. TransDebugOut((DEB_PROT, "%p OUT CResProtocol::Start (hr:%lx)\n",this, hr));
  95. return hr;
  96. }
  97. //+---------------------------------------------------------------------------
  98. //
  99. // Method: CResProtocol::Continue
  100. //
  101. // Synopsis:
  102. //
  103. // Arguments: [pStateInfoIn] --
  104. //
  105. // Returns:
  106. //
  107. // History: 10-29-1996 JohannP (Johann Posch) Created
  108. //
  109. // Notes:
  110. //
  111. //----------------------------------------------------------------------------
  112. STDMETHODIMP CResProtocol::Continue(PROTOCOLDATA *pStateInfoIn)
  113. {
  114. TransDebugOut((DEB_PROT, "%p _IN CResProtocol::Continue\n", this));
  115. HRESULT hr = E_FAIL;
  116. if (_pProt)
  117. hr = _pProt->Continue(pStateInfoIn);
  118. TransDebugOut((DEB_PROT, "%p OUT CResProtocol::Continue (hr:%lx)\n",this, hr));
  119. return hr;
  120. }
  121. //+---------------------------------------------------------------------------
  122. //
  123. // Method: CResProtocol::Read
  124. //
  125. // Synopsis:
  126. //
  127. // Arguments: [ULONG] --
  128. // [ULONG] --
  129. // [pcbRead] --
  130. //
  131. // Returns:
  132. //
  133. // History: 10-29-1996 JohannP (Johann Posch) Created
  134. //
  135. // Notes:
  136. //
  137. //----------------------------------------------------------------------------
  138. STDMETHODIMP CResProtocol::Read(void *pv,ULONG cb,ULONG *pcbRead)
  139. {
  140. TransDebugOut((DEB_PROT, "%p _IN CResProtocol::Read (cb:%ld)\n", this,cb));
  141. HRESULT hr = NOERROR;
  142. if (_pProt)
  143. hr = _pProt->Read(pv, cb, pcbRead);
  144. TransDebugOut((DEB_PROT, "%p OUT CResProtocol::Read (pcbRead:%ld, hr:%lx)\n",this,*pcbRead, hr));
  145. return hr;
  146. }
  147. //+---------------------------------------------------------------------------
  148. //
  149. // Method: CResProtocol::Seek
  150. //
  151. // Synopsis:
  152. //
  153. // Arguments: [DWORD] --
  154. // [ULARGE_INTEGER] --
  155. // [plibNewPosition] --
  156. //
  157. // Returns:
  158. //
  159. // History: 10-29-1996 JohannP (Johann Posch) Created
  160. //
  161. // Notes: WORK: not done
  162. //
  163. //----------------------------------------------------------------------------
  164. STDMETHODIMP CResProtocol::Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition)
  165. {
  166. TransDebugOut((DEB_PROT, "%p _IN CResProtocol::Seek\n", this));
  167. HRESULT hr = NOERROR;
  168. if (_pProt)
  169. hr = _pProt->Seek(dlibMove, dwOrigin, plibNewPosition);
  170. TransDebugOut((DEB_PROT, "%p OUT CResProtocol::Seek (hr:%lx)\n",this, hr));
  171. return hr;
  172. }
  173. //+---------------------------------------------------------------------------
  174. //
  175. // Method: CResProtocol::CResProtocol
  176. //
  177. // Synopsis:
  178. //
  179. // Arguments: (none)
  180. //
  181. // Returns:
  182. //
  183. // History: 1-27-96 JohannP (Johann Posch) Created
  184. //
  185. // Notes:
  186. //
  187. //----------------------------------------------------------------------------
  188. CResProtocol::CResProtocol(REFCLSID rclsid, IUnknown *pUnkOuter, IUnknown **ppUnkInner) : CBaseProtocol(rclsid, pUnkOuter, ppUnkInner)
  189. {
  190. TransDebugOut((DEB_PROT, "%p _IN/OUT CResProtocol::CResProtocol \n", this));
  191. }
  192. //+---------------------------------------------------------------------------
  193. //
  194. // Method: CResProtocol::~CResProtocol
  195. //
  196. // Synopsis:
  197. //
  198. // Arguments: (none)
  199. //
  200. // Returns:
  201. //
  202. // History: 11-09-1996 JohannP (Johann Posch) Created
  203. //
  204. // Notes:
  205. //
  206. //----------------------------------------------------------------------------
  207. CResProtocol::~CResProtocol()
  208. {
  209. TransDebugOut((DEB_PROT, "%p _IN/OUT CResProtocol::~CResProtocol \n", this));
  210. }
  211. // SUPER HACK FUNCTION because InternetCrackUrl is not very good.
  212. // THIS FUNCTION DOES NOT CHECK THE INPUT BUFFER SIZE.
  213. // AND CALLER MUST PROVIDE lpszUrlPath buffer for us to parse.
  214. BOOL
  215. MyCrackUrl(
  216. LPCSTR lpszUrl,
  217. DWORD dwUrlLength,
  218. DWORD dwFlags,
  219. LPURL_COMPONENTSA lpUC
  220. )
  221. {
  222. LPSTR pszBuf = lpUC->lpszUrlPath;
  223. DWORD dwSize = lpUC->dwUrlPathLength;
  224. BOOL ret = FALSE;
  225. if (pszBuf)
  226. {
  227. if (InternetCanonicalizeUrl(lpszUrl, pszBuf, &dwSize, ICU_DECODE | ICU_NO_ENCODE))
  228. {
  229. // find protocol
  230. LPSTR pTmp = StrChr(pszBuf, ':');
  231. if (pTmp)
  232. {
  233. *pTmp = '\0';
  234. if (lpUC->lpszScheme)
  235. {
  236. lstrcpy(lpUC->lpszScheme, pszBuf);
  237. lpUC->dwSchemeLength = pTmp - pszBuf;
  238. }
  239. pszBuf = ++pTmp;
  240. // skip '/'s
  241. while (*pszBuf && (*pszBuf == '/'))
  242. pszBuf++;
  243. // find host name
  244. pTmp = StrChr(pszBuf, '/');
  245. if (lpUC->lpszHostName)
  246. {
  247. if (pTmp)
  248. lpUC->dwHostNameLength = pTmp - pszBuf;
  249. else
  250. lpUC->dwHostNameLength = lstrlen(pszBuf);
  251. // + 1 for the NULL terminator
  252. lstrcpyn(lpUC->lpszHostName, pszBuf, lpUC->dwHostNameLength + 1);
  253. }
  254. // if a '/' was found, the rest is URL path
  255. if (pTmp)
  256. lpUC->dwUrlPathLength = lstrlen(pTmp);
  257. else
  258. lpUC->dwUrlPathLength = 0;
  259. lpUC->lpszUrlPath = pTmp;
  260. ret = TRUE;
  261. }
  262. }
  263. }
  264. return ret;
  265. }
  266. //+---------------------------------------------------------------------------
  267. //
  268. // Method: CResProtocol::Bind
  269. //
  270. // Synopsis:
  271. //
  272. // Arguments: (none)
  273. //
  274. // Returns:
  275. //
  276. // History: 11-09-1996 JohannP (Johann Posch) Created
  277. //
  278. // Notes:
  279. //
  280. //----------------------------------------------------------------------------
  281. STDMETHODIMP CResProtocol::Bind()
  282. {
  283. TransDebugOut((DEB_PROT, "%p _IN CResProtocol::Bind (szUrl >%s< )\n", this, _pszUrl));
  284. // HRESULT hr = MK_E_SYNTAX;
  285. // HRESULT hr = INET_E_USE_DEFAULT_PROTOCOLHANDLER;
  286. HRESULT hr = MK_E_NOPREFIX;
  287. // HRESULT hr = INET_E_UNKNOWN_PROTOCOL;
  288. URL_COMPONENTS uc;
  289. TCHAR szScheme[INTERNET_MAX_SCHEME_LENGTH];
  290. TCHAR szHost[INTERNET_MAX_HOST_NAME_LENGTH];
  291. TCHAR szURL[MAX_URL_SIZE];
  292. DWORD dwNeeded;
  293. LPSTR lpSearchName;
  294. LPSTR lpNewName = NULL;
  295. ZeroMemory(&uc, sizeof(uc));
  296. uc.dwStructSize = sizeof(uc);
  297. uc.lpszScheme = szScheme;
  298. uc.dwSchemeLength = ARRAYSIZE(szScheme);
  299. uc.lpszHostName = szHost;
  300. uc.dwHostNameLength = ARRAYSIZE(szHost);
  301. uc.lpszUrlPath = szURL;
  302. uc.dwUrlPathLength = ARRAYSIZE(szURL);
  303. // uc.dwExtraInfoLength ???
  304. // BUGBUG ???
  305. // InternetCrackUrl doesn't work with "search:\\..."
  306. if (MyCrackUrl(_pszUrl, 0, ICU_DECODE, &uc))
  307. {
  308. // TODO:
  309. // process the URL string
  310. if (!lstrcmpi(szScheme, SZMYPROTOCOL))
  311. {
  312. // if this is our "search:" protocol
  313. // BUGBUG
  314. // we need to look up the registry for the default protocol to use.
  315. uc.lpszScheme = NULL;
  316. uc.nScheme = INTERNET_SCHEME_HTTP;
  317. uc.nPort = INTERNET_DEFAULT_HTTP_PORT;
  318. if (uc.dwHostNameLength)
  319. {
  320. lpSearchName = uc.lpszHostName;
  321. uc.dwHostNameLength = 0;
  322. // ???
  323. // should we clear the UrlPath and ExtraInfo
  324. }
  325. else if (uc.dwUrlPathLength)
  326. {
  327. lpSearchName = uc.lpszUrlPath;
  328. uc.lpszUrlPath = NULL;
  329. }
  330. else
  331. lpSearchName = NULL;
  332. if (lpSearchName)
  333. {
  334. // apply the search.
  335. // ==========================================================
  336. if (!lstrcmpi(lpSearchName, "united airline"))
  337. lpNewName = "www.ual.com";
  338. else if (!lstrcmpi(lpSearchName, "foo bar"))
  339. lpNewName = "msw";
  340. // ==========================================================
  341. if (lpNewName)
  342. {
  343. // this is a searchable string
  344. uc.lpszHostName = lpNewName;
  345. dwNeeded = ARRAYSIZE(_szNewUrl);
  346. if (InternetCreateUrl(&uc, 0, _szNewUrl, &dwNeeded))
  347. hr = NOERROR;
  348. }
  349. }
  350. }
  351. else if (uc.nScheme == INTERNET_SCHEME_HTTP)
  352. {
  353. lpSearchName = uc.lpszHostName;
  354. // apply search
  355. // ==========================================================
  356. if (!lstrcmpi(lpSearchName, "united airline"))
  357. lpNewName = "www.ual.com";
  358. else if (!lstrcmpi(lpSearchName, "foo bar"))
  359. lpNewName = "msw";
  360. // ==========================================================
  361. if (lpNewName)
  362. {
  363. // if search succeeded
  364. uc.lpszHostName = lpNewName;
  365. uc.dwHostNameLength = 0;
  366. dwNeeded = ARRAYSIZE(_szNewUrl);
  367. if (InternetCreateUrl(&uc, 0, _szNewUrl, &dwNeeded))
  368. hr = NOERROR;
  369. }
  370. }
  371. }
  372. else
  373. {
  374. DebugBreak();
  375. DWORD dwError = GetLastError();
  376. }
  377. if (hr != NOERROR)
  378. {
  379. _pProtSink->ReportResult(hr, 0, 0);
  380. }
  381. TransDebugOut((DEB_PROT, "%p OUT CResProtocol::Bind (hr:%lx)\n", this,hr));
  382. return hr;
  383. }
  384. //+---------------------------------------------------------------------------
  385. //
  386. // Function: LookupProtocolClsIDFromReg
  387. //
  388. // Synopsis: finds a protocol handler class for a given URL
  389. //
  390. // Arguments: [pwzUrl] --
  391. // [pclsid] --
  392. //
  393. // Returns:
  394. //
  395. // History: 11-01-1996 JohannP (Johann Posch) Created
  396. //
  397. // Notes:
  398. //
  399. //----------------------------------------------------------------------------
  400. HRESULT LookupProtocolClsIDFromReg(LPCTSTR pszUrl, CLSID *pclsid)
  401. {
  402. TransDebugOut((DEB_PROT, "API _IN LookupProtocolClsIDFromReg (szUrl >%s< )\n", pszUrl));
  403. HRESULT hr = INET_E_UNKNOWN_PROTOCOL;
  404. DWORD dwType;
  405. TCHAR pszProt[MAX_URL_SIZE + 1];
  406. TransAssert((pszUrl && pclsid));
  407. if (pszUrl)
  408. {
  409. char szDelimiter = ':';
  410. lstrcpy(pszProt, pszUrl);
  411. LPSTR pszDel = StrChr(pszProt, szDelimiter);
  412. if (pszDel)
  413. {
  414. *pszDel = '\0';
  415. // fail if the protocol is "search" so we don't get call recursively.
  416. if (lstrcmpi(pszProt, SZMYPROTOCOL))
  417. {
  418. HKEY hProtocolKey = NULL;
  419. DWORD dwLen = 256;
  420. char szProtocolKey[256];
  421. lstrcpy(szProtocolKey, SZPROTOCOLROOT);
  422. lstrcat(szProtocolKey, pszProt);
  423. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szProtocolKey, 0, KEY_QUERY_VALUE, &hProtocolKey) == ERROR_SUCCESS)
  424. {
  425. if (RegQueryValueEx(hProtocolKey, SZCLASS, NULL, &dwType, (LPBYTE)szProtocolKey, &dwLen) == ERROR_SUCCESS)
  426. {
  427. LPWSTR pwzClsId = DupA2W(szProtocolKey);
  428. if (pwzClsId)
  429. {
  430. hr = CLSIDFromString(pwzClsId, pclsid);
  431. TransDebugOut((DEB_PROT, "API FOUND LookupProtocolClsIDFromReg(hr:%lx, ClsId:%ws)\n", hr,pwzClsId));
  432. delete pwzClsId;
  433. }
  434. else
  435. {
  436. hr = E_OUTOFMEMORY;
  437. }
  438. }
  439. RegCloseKey(hProtocolKey);
  440. }
  441. }
  442. }
  443. else
  444. {
  445. // look up the registry
  446. hr = MK_E_SYNTAX;
  447. }
  448. }
  449. TransDebugOut((DEB_PROT, "API OUT LookupProtocolClsIDFromReg(hr:%lx)\n", hr));
  450. return hr;
  451. }