Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

677 lines
16 KiB

  1. //--------------------------------------------------------------------------
  2. //
  3. // Module Name: LaunStub.Cpp
  4. //
  5. // Brief Description:
  6. // This module contains the code that parses HTTP-based
  7. // response from the ULS server.
  8. //
  9. // Author: Chu, Lon-Chan (lonchanc)
  10. //
  11. // Copyright (c) 1996 Microsoft Corporation
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "precomp.h"
  15. #include "launstub.h"
  16. PTSTR LocalStrDup ( PTSTR pszToDup )
  17. {
  18. UINT uLen;
  19. PTSTR psz = NULL;
  20. if (pszToDup)
  21. {
  22. uLen = lstrlen (pszToDup);
  23. psz = (PTSTR) new TCHAR[uLen + 1];
  24. if (psz)
  25. {
  26. lstrcpy (psz, pszToDup);
  27. }
  28. }
  29. return psz;
  30. }
  31. ULONG DecStrToInt ( PTSTR psz )
  32. {
  33. ULONG ul = 0;
  34. WORD w;
  35. if (psz)
  36. {
  37. while ((w = (WORD) *psz++) != NULL)
  38. {
  39. if (TEXT ('0') <= w && w <= TEXT ('9'))
  40. {
  41. w -= TEXT ('0');
  42. ul = ul * 10 + w;
  43. }
  44. else
  45. {
  46. break;
  47. }
  48. }
  49. }
  50. return ul;
  51. }
  52. ULONG HexStrToInt ( PTSTR psz )
  53. {
  54. ULONG ul = 0;
  55. WORD w;
  56. if (psz)
  57. {
  58. while ((w = (WORD) *psz++) != NULL)
  59. {
  60. if (TEXT ('0') <= w && w <= TEXT ('9'))
  61. {
  62. w -= TEXT ('0');
  63. }
  64. else
  65. if (TEXT ('a') <= w && w <= TEXT ('f'))
  66. {
  67. w -= (TEXT ('a') - 10);
  68. }
  69. else
  70. if (TEXT ('A') <= w && w <= TEXT ('F'))
  71. {
  72. w -= (TEXT ('A') - 10);
  73. }
  74. else
  75. {
  76. break;
  77. }
  78. ul = (ul << 4) + w;
  79. }
  80. }
  81. return ul;
  82. }
  83. BOOL IsWhiteSpace ( TCHAR c )
  84. {
  85. return (c == TEXT (' ') || c == TEXT ('\t') || c == TEXT ('\r') || c == TEXT ('\n'));
  86. }
  87. enum
  88. {
  89. // beta 3 strings
  90. ATTR_HR,
  91. ATTR_PORT,
  92. ATTR_HA,
  93. ATTR_HC,
  94. ATTR_CID,
  95. ATTR_UID,
  96. ATTR_URL,
  97. ATTR_IP,
  98. ATTR_MT,
  99. B3ATTR_COUNT
  100. };
  101. static PTSTR g_B3Attr[B3ATTR_COUNT] =
  102. {
  103. // beta 3 strings
  104. TEXT ("HR"),
  105. TEXT ("PORT"),
  106. TEXT ("HA"),
  107. TEXT ("HC"),
  108. TEXT ("CID"),
  109. TEXT ("UID"),
  110. TEXT ("URL"),
  111. TEXT ("IP"),
  112. TEXT ("MT"),
  113. };
  114. enum
  115. {
  116. // beta 4 strings
  117. ATTR_HRESULT,
  118. ATTR_HCLIENT,
  119. ATTR_HAPPLICATION,
  120. ATTR_NAPPS,
  121. ATTR_IPADDRESS,
  122. ATTR_PORTNUM,
  123. ATTR_APPID,
  124. ATTR_PROTID,
  125. ATTR_USERID,
  126. ATTR_MIMETYPE,
  127. ATTR_APPMIME,
  128. ATTR_PROTMIME,
  129. ATTR_QUERYURL,
  130. B4ATTR_COUNT
  131. };
  132. static PTSTR g_B4Attr[B4ATTR_COUNT] =
  133. {
  134. // beta 4 strings
  135. TEXT ("hresult"),
  136. TEXT ("hclient"),
  137. TEXT ("happlication"),
  138. TEXT ("napps"),
  139. TEXT ("ipaddress"),
  140. TEXT ("portnum"),
  141. TEXT ("appid"),
  142. TEXT ("protid"),
  143. TEXT ("userid"),
  144. TEXT ("mimetype"),
  145. TEXT ("appmime"),
  146. TEXT ("protmime"),
  147. TEXT ("queryurl"),
  148. };
  149. typedef struct tagULPCMD
  150. {
  151. PTSTR pszCmd;
  152. ULONG nCmdId;
  153. }
  154. ULPCMD;
  155. static ULPCMD g_B3Cmd[] =
  156. {
  157. { TEXT ("ON"), CLIENT_MESSAGE_ID_LOGON },
  158. { TEXT ("OFF"), CLIENT_MESSAGE_ID_LOGOFF },
  159. { TEXT ("KA"), CLIENT_MESSAGE_ID_KEEPALIVE },
  160. { TEXT ("RES"), CLIENT_MESSAGE_ID_RESOLVE },
  161. };
  162. static ULPCMD g_B4Cmd[] =
  163. {
  164. { TEXT ("on"), CLIENT_MESSAGE_ID_LOGON },
  165. { TEXT ("off"), CLIENT_MESSAGE_ID_LOGOFF },
  166. { TEXT ("ka"), CLIENT_MESSAGE_ID_KEEPALIVE },
  167. { TEXT ("res"), CLIENT_MESSAGE_ID_RESOLVE },
  168. };
  169. /*
  170. @doc EXTERNAL ULCLIENT
  171. @api HRESULT | CULSLaunch_Stub::ParseUlsHttpRespFile |
  172. Parses a HTTP-based response from the ULS server.
  173. @parm PTSTR | pszUlsFile | A pointer to the HTTP-based response
  174. file name string.
  175. @parm ULS_HTTP_RESP * | pResp | A pointer to the generic
  176. HTTP response structure.
  177. @rdesc Returns ULS_SUCCESS if this operation succeeds.
  178. @comm This method parses the responses from the commands
  179. defined in the g_B3Cmd array. The attributes this method
  180. understands are listed in the g_B3Attr array.
  181. */
  182. STDMETHODIMP CULSLaunch_Stub::ParseUlsHttpRespFile
  183. ( PTSTR pszUlsFile, ULS_HTTP_RESP *pResp )
  184. {
  185. HANDLE hf = INVALID_HANDLE_VALUE;
  186. HRESULT hr;
  187. PTSTR pszBuf = NULL;
  188. ULONG cbFileSize;
  189. // clean up the structure first
  190. ZeroMemory (pResp, sizeof (ULS_HTTP_RESP));
  191. pResp->cbSize = sizeof (ULS_HTTP_RESP);
  192. // open the uls file
  193. hf = CreateFile (pszUlsFile, GENERIC_READ, FILE_SHARE_READ, NULL,
  194. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
  195. FILE_FLAG_SEQUENTIAL_SCAN |
  196. // FILE_FLAG_DELETE_ON_CLOSE, NULL);
  197. 0, NULL);
  198. if (hf == INVALID_HANDLE_VALUE)
  199. {
  200. return ULS_E_INVALID_HANDLE;
  201. }
  202. // get the size of the uls file
  203. cbFileSize = GetFileSize (hf, NULL);
  204. if (! cbFileSize)
  205. {
  206. return ULS_E_INVALID_HANDLE;
  207. }
  208. // round up to align with the paragraph boundary
  209. cbFileSize = ((cbFileSize + 4) & (~ 0x0F)) + 0x10;
  210. // allocate a buffer to hold the entire uls file
  211. pszBuf = (PTSTR) new TCHAR[cbFileSize];
  212. if (! pszBuf)
  213. {
  214. hr = ULS_E_OUTOFMEMORY;
  215. goto MyExit;
  216. }
  217. // read the file in
  218. if (! ReadFile (hf, pszBuf, cbFileSize, &cbFileSize, NULL))
  219. {
  220. hr = ULS_E_IO_ERROR;
  221. goto MyExit;
  222. }
  223. // parse the uls buffer
  224. hr = ParseUlsHttpRespBuffer (pszBuf, cbFileSize, pResp);
  225. if (hr != ULS_SUCCESS)
  226. {
  227. goto MyExit;
  228. }
  229. MyExit:
  230. if (hf != INVALID_HANDLE_VALUE) CloseHandle (hf);
  231. delete [] pszBuf;
  232. if (hr != ULS_SUCCESS && pResp)
  233. {
  234. FreeUlsHttpResp (pResp);
  235. }
  236. return hr;
  237. }
  238. /*
  239. @doc EXTERNAL ULCLIENT
  240. @api HRESULT | CULSLaunch_Stub::ParseUlsHttpRespBuffer |
  241. Parses a HTTP-based response from the ULS server.
  242. @parm PTSTR | pszBuf | A pointer to the buffer holding
  243. the entire HTTP-based response data.
  244. @parm ULONG | cbBufSize | The size in byte of the buffer.
  245. @parm ULS_HTTP_RESP * | pResp | A pointer to the generic
  246. HTTP response structure.
  247. @rdesc Returns ULS_SUCCESS if this operation succeeds.
  248. @comm This method parses the responses from the commands
  249. defined in the g_B3Cmd array. The attributes this method
  250. understands are listed in the g_B3Attr array.
  251. */
  252. STDMETHODIMP CULSLaunch_Stub::ParseUlsHttpRespBuffer
  253. ( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp )
  254. {
  255. HRESULT hr;
  256. #ifdef SANITY_CHECK
  257. // sanity check
  258. if (MyIsBadReadPtr (pszBuf, cbBufSize) ||
  259. MyIsBadWritePtr (pResp, sizeof (ULS_HTTP_RESP)))
  260. {
  261. return ULS_E_INVALID_POINTER;
  262. }
  263. #endif
  264. hr = ParseB3HttpRespBuffer (pszBuf, cbBufSize, pResp);
  265. if (hr == ULS_E_INVALID_FORMAT)
  266. {
  267. ZeroMemory (pResp, sizeof (ULS_HTTP_RESP));
  268. pResp->cbSize = sizeof (ULS_HTTP_RESP);
  269. hr = ParseB4HttpRespBuffer (pszBuf, cbBufSize, pResp);
  270. }
  271. return hr;
  272. }
  273. HRESULT CULSLaunch_Stub::ParseB3HttpRespBuffer // beta 3 implementation
  274. ( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp )
  275. {
  276. PTSTR psz;
  277. int i;
  278. // get mime type
  279. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('<'));
  280. if (! psz) return ULS_E_INVALID_FORMAT;
  281. pszBuf = psz + 1;
  282. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('>'));
  283. if (! psz) return ULS_E_INVALID_FORMAT;
  284. *psz = TEXT ('\0');
  285. lstrcpyn (pResp->szMimeType, pszBuf, MAX_MIME_TYPE_LENGTH);
  286. // get to the type of response
  287. pszBuf = psz + 1;
  288. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('<'));
  289. if (! psz) return ULS_E_INVALID_FORMAT;
  290. pszBuf = psz + 1;
  291. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('['));
  292. if (! psz) return ULS_E_INVALID_FORMAT;
  293. pszBuf = psz + 1;
  294. psz = (LPTSTR)_StrChr (pszBuf, TEXT (']'));
  295. if (! psz) return ULS_E_INVALID_FORMAT;
  296. *psz = TEXT ('\0');
  297. pResp->nCmdId = (ULONG) -1;
  298. for (i = 0; i < sizeof (g_B3Cmd) / sizeof (g_B3Cmd[0]); i++)
  299. {
  300. if (! lstrcmpi (pszBuf, g_B3Cmd[i].pszCmd))
  301. {
  302. pResp->nCmdId = g_B3Cmd[i].nCmdId;
  303. break;
  304. }
  305. }
  306. if (pResp->nCmdId == (ULONG) -1) return ULS_E_INVALID_FORMAT;
  307. // skip any white space
  308. for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; }
  309. // main loop
  310. while (*pszBuf && *pszBuf != TEXT ('>'))
  311. {
  312. // locate the equal sign
  313. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('='));
  314. if (! psz) return ULS_E_INVALID_FORMAT;
  315. *psz = TEXT ('\0');
  316. // search for attribute
  317. for (i = 0; i < sizeof (g_B3Attr) / sizeof (g_B3Attr[0]); i++)
  318. {
  319. if (! lstrcmpi (pszBuf, g_B3Attr[i]))
  320. {
  321. break;
  322. }
  323. }
  324. if (i >= sizeof (g_B3Attr) / sizeof (g_B3Attr[0])) return ULS_E_INVALID_FORMAT;
  325. // locate the attribute value
  326. for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; }
  327. for (psz = pszBuf + 1; *psz; psz++) { if (IsWhiteSpace (*psz)) break; }
  328. *psz = TEXT ('\0');
  329. // now the attribute value is a null-terminated string pointed by pszBuf
  330. // parse the attribute value
  331. switch (i)
  332. {
  333. case ATTR_HR:
  334. pResp->hr = HexStrToInt (pszBuf);
  335. break;
  336. case ATTR_PORT:
  337. pResp->nPort = DecStrToInt (pszBuf);
  338. break;
  339. case ATTR_HA:
  340. pResp->dwAppSession = HexStrToInt (pszBuf);
  341. break;
  342. case ATTR_HC:
  343. pResp->dwClientSession = HexStrToInt (pszBuf);
  344. break;
  345. case ATTR_CID:
  346. pResp->dwClientId = HexStrToInt (pszBuf);
  347. break;
  348. case ATTR_UID:
  349. ASSERT(!pResp->pszUID);
  350. pResp->pszUID = LocalStrDup (pszBuf);
  351. break;
  352. case ATTR_URL:
  353. ASSERT(!pResp->pszURL);
  354. pResp->pszURL = LocalStrDup (pszBuf);
  355. break;
  356. case ATTR_IP:
  357. lstrcpyn (pResp->szIPAddress, pszBuf, MAX_IP_ADDRESS_STRING_LENGTH);
  358. break;
  359. case ATTR_MT:
  360. // already got it
  361. break;
  362. }
  363. // skip any white space
  364. for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; }
  365. }
  366. return ULS_SUCCESS;
  367. }
  368. HRESULT CULSLaunch_Stub::ParseB4HttpRespBuffer // beta 4 implementation
  369. ( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp )
  370. {
  371. PTSTR psz, pszSave;
  372. int i;
  373. // get mime type
  374. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('['));
  375. if (! psz)
  376. {
  377. return ULS_E_INVALID_FORMAT;
  378. }
  379. pszBuf = psz + 1;
  380. psz = (LPTSTR)_StrChr (pszBuf, TEXT (']'));
  381. if (! psz)
  382. {
  383. return ULS_E_INVALID_FORMAT;
  384. }
  385. *psz = TEXT ('\0');
  386. // now pszBuf is ptr to the string inside [], such on, off, ka, res.
  387. pResp->nCmdId = (ULONG) -1;
  388. for (i = 0; i < sizeof (g_B4Cmd) / sizeof (g_B4Cmd[0]); i++)
  389. {
  390. if (! lstrcmpi (pszBuf, g_B4Cmd[i].pszCmd))
  391. {
  392. pResp->nCmdId = g_B4Cmd[i].nCmdId;
  393. break;
  394. }
  395. }
  396. // to see if this cmd is something I don't know
  397. if (pResp->nCmdId == (ULONG) -1)
  398. {
  399. return ULS_E_INVALID_FORMAT;
  400. }
  401. // update the buf ptr
  402. pszBuf = psz + 1;
  403. // main loop
  404. while (*pszBuf)
  405. {
  406. // locate a \r \n
  407. while (*pszBuf != TEXT ('\r') && *pszBuf != TEXT ('\n'))
  408. {
  409. pszBuf++;
  410. }
  411. // skip any white space including \r \n
  412. while (*pszBuf)
  413. {
  414. if (! IsWhiteSpace (*pszBuf))
  415. {
  416. break;
  417. }
  418. pszBuf++;
  419. }
  420. // end of file
  421. if (! *pszBuf)
  422. {
  423. return ULS_SUCCESS;
  424. }
  425. // locate the equal sign
  426. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('='));
  427. if (! psz)
  428. {
  429. continue; // cannot goto NextLine because psz==NULL
  430. }
  431. // to make pszBuf ptr to the attr name
  432. *psz = TEXT ('\0');
  433. // search for attribute
  434. for (i = 0; i < sizeof (g_B4Attr) / sizeof (g_B4Attr[0]); i++)
  435. {
  436. if (! lstrcmpi (pszBuf, g_B4Attr[i]))
  437. {
  438. break;
  439. }
  440. }
  441. // is this attribute valid? if not, ignore it!
  442. if (i >= sizeof (g_B4Attr) / sizeof (g_B4Attr[0]))
  443. {
  444. goto NextLine;
  445. }
  446. // locate pszBuf now ptr to attr value
  447. pszBuf = psz + 1;
  448. // get to the end of line
  449. for (psz = pszBuf; *psz; psz++)
  450. {
  451. if (*psz == TEXT ('\r') || *psz == TEXT ('\n'))
  452. {
  453. break;
  454. }
  455. }
  456. // deal with attrname=\r\nEOF
  457. if (! *psz)
  458. {
  459. return ULS_SUCCESS;
  460. }
  461. // make the attr value is a null-terminated string pointed by pszBuf
  462. *psz = TEXT ('\0');
  463. // parse the attribute value
  464. switch (i)
  465. {
  466. case ATTR_HRESULT:
  467. pResp->hr = HexStrToInt (pszBuf);
  468. break;
  469. case ATTR_PORTNUM:
  470. pResp->nPort = DecStrToInt (pszBuf);
  471. break;
  472. case ATTR_HAPPLICATION:
  473. pResp->dwAppSession = HexStrToInt (pszBuf);
  474. break;
  475. case ATTR_HCLIENT:
  476. pResp->dwClientSession = HexStrToInt (pszBuf);
  477. break;
  478. case ATTR_USERID:
  479. pszSave = pResp->pszUID;
  480. pResp->pszUID = LocalStrDup (pszBuf);
  481. if (pResp->pszUID)
  482. {
  483. delete [] pszSave;
  484. }
  485. else
  486. {
  487. pResp->pszUID = pszSave; // restore
  488. }
  489. break;
  490. case ATTR_QUERYURL:
  491. pszSave = pResp->pszURL;
  492. pResp->pszURL = LocalStrDup (pszBuf);
  493. if (pResp->pszURL)
  494. {
  495. delete [] pszSave;
  496. }
  497. else
  498. {
  499. pResp->pszURL = pszSave; // restore
  500. }
  501. break;
  502. case ATTR_IPADDRESS:
  503. lstrcpyn (pResp->szIPAddress, pszBuf,
  504. sizeof (pResp->szIPAddress) / sizeof (pResp->szIPAddress[0]));
  505. break;
  506. case ATTR_MIMETYPE:
  507. lstrcpyn (pResp->szMimeType, pszBuf,
  508. sizeof (pResp->szMimeType) / sizeof (pResp->szMimeType[0]));
  509. break;
  510. case ATTR_APPMIME:
  511. lstrcpyn (pResp->szAppMime, pszBuf,
  512. sizeof (pResp->szAppMime) / sizeof (pResp->szAppMime[0]));
  513. break;
  514. case ATTR_PROTMIME:
  515. lstrcpyn (pResp->szProtMime, pszBuf,
  516. sizeof (pResp->szProtMime) / sizeof (pResp->szProtMime[0]));
  517. break;
  518. case ATTR_APPID:
  519. lstrcpyn (pResp->szAppId, pszBuf,
  520. sizeof (pResp->szAppId) / sizeof (pResp->szAppId[0]));
  521. break;
  522. case ATTR_PROTID:
  523. lstrcpyn (pResp->szProtId, pszBuf,
  524. sizeof (pResp->szProtId) / sizeof (pResp->szProtId[0]));
  525. break;
  526. case ATTR_NAPPS:
  527. pResp->nApps = DecStrToInt (pszBuf);
  528. break;
  529. default:
  530. break;
  531. }
  532. NextLine:
  533. // make sure we are at \r \n
  534. *psz = TEXT ('\r');
  535. pszBuf = psz;
  536. }
  537. return ULS_SUCCESS;
  538. }
  539. /*
  540. @doc EXTERNAL ULCLIENT
  541. @api HRESULT | CULSLaunch_Stub::FreeUlsHttpResp |
  542. Frees internal resources in a generic HTTP-based
  543. response structure.
  544. @parm ULS_HTTP_RESP * | pResp | A pointer to the generic
  545. HTTP response structure.
  546. @rdesc Returns ULS_SUCCESS if this operation succeeds.
  547. @comm The internal resources must be created by
  548. the ParseUlsHttpRespFile method or
  549. the ParseUlsHttpRespBuffer method.
  550. */
  551. STDMETHODIMP CULSLaunch_Stub::FreeUlsHttpResp ( ULS_HTTP_RESP *pResp )
  552. {
  553. if (pResp->pszUID)
  554. {
  555. delete [] pResp->pszUID;
  556. pResp->pszUID = NULL;
  557. }
  558. if (pResp->pszURL)
  559. {
  560. delete [] pResp->pszURL;
  561. pResp->pszURL = NULL;
  562. }
  563. return ULS_SUCCESS;
  564. }