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.

678 lines
17 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. hr = ULS_E_INVALID_HANDLE;
  207. goto MyExit;
  208. }
  209. // round up to align with the paragraph boundary
  210. cbFileSize = ((cbFileSize + 4) & (~ 0x0F)) + 0x10;
  211. // allocate a buffer to hold the entire uls file
  212. pszBuf = (PTSTR) new TCHAR[cbFileSize];
  213. if (! pszBuf)
  214. {
  215. hr = ULS_E_OUTOFMEMORY;
  216. goto MyExit;
  217. }
  218. // read the file in
  219. if (! ReadFile (hf, pszBuf, cbFileSize, &cbFileSize, NULL))
  220. {
  221. hr = ULS_E_IO_ERROR;
  222. goto MyExit;
  223. }
  224. // parse the uls buffer
  225. hr = ParseUlsHttpRespBuffer (pszBuf, cbFileSize, pResp);
  226. if (hr != ULS_SUCCESS)
  227. {
  228. goto MyExit;
  229. }
  230. MyExit:
  231. if (hf != INVALID_HANDLE_VALUE) CloseHandle (hf);
  232. delete [] pszBuf;
  233. if (hr != ULS_SUCCESS && pResp)
  234. {
  235. FreeUlsHttpResp (pResp);
  236. }
  237. return hr;
  238. }
  239. /*
  240. @doc EXTERNAL ULCLIENT
  241. @api HRESULT | CULSLaunch_Stub::ParseUlsHttpRespBuffer |
  242. Parses a HTTP-based response from the ULS server.
  243. @parm PTSTR | pszBuf | A pointer to the buffer holding
  244. the entire HTTP-based response data.
  245. @parm ULONG | cbBufSize | The size in byte of the buffer.
  246. @parm ULS_HTTP_RESP * | pResp | A pointer to the generic
  247. HTTP response structure.
  248. @rdesc Returns ULS_SUCCESS if this operation succeeds.
  249. @comm This method parses the responses from the commands
  250. defined in the g_B3Cmd array. The attributes this method
  251. understands are listed in the g_B3Attr array.
  252. */
  253. STDMETHODIMP CULSLaunch_Stub::ParseUlsHttpRespBuffer
  254. ( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp )
  255. {
  256. HRESULT hr;
  257. #ifdef SANITY_CHECK
  258. // sanity check
  259. if (MyIsBadReadPtr (pszBuf, cbBufSize) ||
  260. MyIsBadWritePtr (pResp, sizeof (ULS_HTTP_RESP)))
  261. {
  262. return ULS_E_INVALID_POINTER;
  263. }
  264. #endif
  265. hr = ParseB3HttpRespBuffer (pszBuf, cbBufSize, pResp);
  266. if (hr == ULS_E_INVALID_FORMAT)
  267. {
  268. ZeroMemory (pResp, sizeof (ULS_HTTP_RESP));
  269. pResp->cbSize = sizeof (ULS_HTTP_RESP);
  270. hr = ParseB4HttpRespBuffer (pszBuf, cbBufSize, pResp);
  271. }
  272. return hr;
  273. }
  274. HRESULT CULSLaunch_Stub::ParseB3HttpRespBuffer // beta 3 implementation
  275. ( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp )
  276. {
  277. PTSTR psz;
  278. int i;
  279. // get mime type
  280. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('<'));
  281. if (! psz) return ULS_E_INVALID_FORMAT;
  282. pszBuf = psz + 1;
  283. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('>'));
  284. if (! psz) return ULS_E_INVALID_FORMAT;
  285. *psz = TEXT ('\0');
  286. lstrcpyn (pResp->szMimeType, pszBuf, MAX_MIME_TYPE_LENGTH);
  287. // get to the type of response
  288. pszBuf = psz + 1;
  289. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('<'));
  290. if (! psz) return ULS_E_INVALID_FORMAT;
  291. pszBuf = psz + 1;
  292. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('['));
  293. if (! psz) return ULS_E_INVALID_FORMAT;
  294. pszBuf = psz + 1;
  295. psz = (LPTSTR)_StrChr (pszBuf, TEXT (']'));
  296. if (! psz) return ULS_E_INVALID_FORMAT;
  297. *psz = TEXT ('\0');
  298. pResp->nCmdId = (ULONG) -1;
  299. for (i = 0; i < sizeof (g_B3Cmd) / sizeof (g_B3Cmd[0]); i++)
  300. {
  301. if (! lstrcmpi (pszBuf, g_B3Cmd[i].pszCmd))
  302. {
  303. pResp->nCmdId = g_B3Cmd[i].nCmdId;
  304. break;
  305. }
  306. }
  307. if (pResp->nCmdId == (ULONG) -1) return ULS_E_INVALID_FORMAT;
  308. // skip any white space
  309. for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; }
  310. // main loop
  311. while (*pszBuf && *pszBuf != TEXT ('>'))
  312. {
  313. // locate the equal sign
  314. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('='));
  315. if (! psz) return ULS_E_INVALID_FORMAT;
  316. *psz = TEXT ('\0');
  317. // search for attribute
  318. for (i = 0; i < sizeof (g_B3Attr) / sizeof (g_B3Attr[0]); i++)
  319. {
  320. if (! lstrcmpi (pszBuf, g_B3Attr[i]))
  321. {
  322. break;
  323. }
  324. }
  325. if (i >= sizeof (g_B3Attr) / sizeof (g_B3Attr[0])) return ULS_E_INVALID_FORMAT;
  326. // locate the attribute value
  327. for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; }
  328. for (psz = pszBuf + 1; *psz; psz++) { if (IsWhiteSpace (*psz)) break; }
  329. *psz = TEXT ('\0');
  330. // now the attribute value is a null-terminated string pointed by pszBuf
  331. // parse the attribute value
  332. switch (i)
  333. {
  334. case ATTR_HR:
  335. pResp->hr = HexStrToInt (pszBuf);
  336. break;
  337. case ATTR_PORT:
  338. pResp->nPort = DecStrToInt (pszBuf);
  339. break;
  340. case ATTR_HA:
  341. pResp->dwAppSession = HexStrToInt (pszBuf);
  342. break;
  343. case ATTR_HC:
  344. pResp->dwClientSession = HexStrToInt (pszBuf);
  345. break;
  346. case ATTR_CID:
  347. pResp->dwClientId = HexStrToInt (pszBuf);
  348. break;
  349. case ATTR_UID:
  350. ASSERT(!pResp->pszUID);
  351. pResp->pszUID = LocalStrDup (pszBuf);
  352. break;
  353. case ATTR_URL:
  354. ASSERT(!pResp->pszURL);
  355. pResp->pszURL = LocalStrDup (pszBuf);
  356. break;
  357. case ATTR_IP:
  358. lstrcpyn (pResp->szIPAddress, pszBuf, MAX_IP_ADDRESS_STRING_LENGTH);
  359. break;
  360. case ATTR_MT:
  361. // already got it
  362. break;
  363. }
  364. // skip any white space
  365. for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; }
  366. }
  367. return ULS_SUCCESS;
  368. }
  369. HRESULT CULSLaunch_Stub::ParseB4HttpRespBuffer // beta 4 implementation
  370. ( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp )
  371. {
  372. PTSTR psz, pszSave;
  373. int i;
  374. // get mime type
  375. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('['));
  376. if (! psz)
  377. {
  378. return ULS_E_INVALID_FORMAT;
  379. }
  380. pszBuf = psz + 1;
  381. psz = (LPTSTR)_StrChr (pszBuf, TEXT (']'));
  382. if (! psz)
  383. {
  384. return ULS_E_INVALID_FORMAT;
  385. }
  386. *psz = TEXT ('\0');
  387. // now pszBuf is ptr to the string inside [], such on, off, ka, res.
  388. pResp->nCmdId = (ULONG) -1;
  389. for (i = 0; i < sizeof (g_B4Cmd) / sizeof (g_B4Cmd[0]); i++)
  390. {
  391. if (! lstrcmpi (pszBuf, g_B4Cmd[i].pszCmd))
  392. {
  393. pResp->nCmdId = g_B4Cmd[i].nCmdId;
  394. break;
  395. }
  396. }
  397. // to see if this cmd is something I don't know
  398. if (pResp->nCmdId == (ULONG) -1)
  399. {
  400. return ULS_E_INVALID_FORMAT;
  401. }
  402. // update the buf ptr
  403. pszBuf = psz + 1;
  404. // main loop
  405. while (*pszBuf)
  406. {
  407. // locate a \r \n
  408. while (*pszBuf != TEXT ('\r') && *pszBuf != TEXT ('\n'))
  409. {
  410. pszBuf++;
  411. }
  412. // skip any white space including \r \n
  413. while (*pszBuf)
  414. {
  415. if (! IsWhiteSpace (*pszBuf))
  416. {
  417. break;
  418. }
  419. pszBuf++;
  420. }
  421. // end of file
  422. if (! *pszBuf)
  423. {
  424. return ULS_SUCCESS;
  425. }
  426. // locate the equal sign
  427. psz = (LPTSTR)_StrChr (pszBuf, TEXT ('='));
  428. if (! psz)
  429. {
  430. continue; // cannot goto NextLine because psz==NULL
  431. }
  432. // to make pszBuf ptr to the attr name
  433. *psz = TEXT ('\0');
  434. // search for attribute
  435. for (i = 0; i < sizeof (g_B4Attr) / sizeof (g_B4Attr[0]); i++)
  436. {
  437. if (! lstrcmpi (pszBuf, g_B4Attr[i]))
  438. {
  439. break;
  440. }
  441. }
  442. // is this attribute valid? if not, ignore it!
  443. if (i >= sizeof (g_B4Attr) / sizeof (g_B4Attr[0]))
  444. {
  445. goto NextLine;
  446. }
  447. // locate pszBuf now ptr to attr value
  448. pszBuf = psz + 1;
  449. // get to the end of line
  450. for (psz = pszBuf; *psz; psz++)
  451. {
  452. if (*psz == TEXT ('\r') || *psz == TEXT ('\n'))
  453. {
  454. break;
  455. }
  456. }
  457. // deal with attrname=\r\nEOF
  458. if (! *psz)
  459. {
  460. return ULS_SUCCESS;
  461. }
  462. // make the attr value is a null-terminated string pointed by pszBuf
  463. *psz = TEXT ('\0');
  464. // parse the attribute value
  465. switch (i)
  466. {
  467. case ATTR_HRESULT:
  468. pResp->hr = HexStrToInt (pszBuf);
  469. break;
  470. case ATTR_PORTNUM:
  471. pResp->nPort = DecStrToInt (pszBuf);
  472. break;
  473. case ATTR_HAPPLICATION:
  474. pResp->dwAppSession = HexStrToInt (pszBuf);
  475. break;
  476. case ATTR_HCLIENT:
  477. pResp->dwClientSession = HexStrToInt (pszBuf);
  478. break;
  479. case ATTR_USERID:
  480. pszSave = pResp->pszUID;
  481. pResp->pszUID = LocalStrDup (pszBuf);
  482. if (pResp->pszUID)
  483. {
  484. delete [] pszSave;
  485. }
  486. else
  487. {
  488. pResp->pszUID = pszSave; // restore
  489. }
  490. break;
  491. case ATTR_QUERYURL:
  492. pszSave = pResp->pszURL;
  493. pResp->pszURL = LocalStrDup (pszBuf);
  494. if (pResp->pszURL)
  495. {
  496. delete [] pszSave;
  497. }
  498. else
  499. {
  500. pResp->pszURL = pszSave; // restore
  501. }
  502. break;
  503. case ATTR_IPADDRESS:
  504. lstrcpyn (pResp->szIPAddress, pszBuf,
  505. sizeof (pResp->szIPAddress) / sizeof (pResp->szIPAddress[0]));
  506. break;
  507. case ATTR_MIMETYPE:
  508. lstrcpyn (pResp->szMimeType, pszBuf,
  509. sizeof (pResp->szMimeType) / sizeof (pResp->szMimeType[0]));
  510. break;
  511. case ATTR_APPMIME:
  512. lstrcpyn (pResp->szAppMime, pszBuf,
  513. sizeof (pResp->szAppMime) / sizeof (pResp->szAppMime[0]));
  514. break;
  515. case ATTR_PROTMIME:
  516. lstrcpyn (pResp->szProtMime, pszBuf,
  517. sizeof (pResp->szProtMime) / sizeof (pResp->szProtMime[0]));
  518. break;
  519. case ATTR_APPID:
  520. lstrcpyn (pResp->szAppId, pszBuf,
  521. sizeof (pResp->szAppId) / sizeof (pResp->szAppId[0]));
  522. break;
  523. case ATTR_PROTID:
  524. lstrcpyn (pResp->szProtId, pszBuf,
  525. sizeof (pResp->szProtId) / sizeof (pResp->szProtId[0]));
  526. break;
  527. case ATTR_NAPPS:
  528. pResp->nApps = DecStrToInt (pszBuf);
  529. break;
  530. default:
  531. break;
  532. }
  533. NextLine:
  534. // make sure we are at \r \n
  535. *psz = TEXT ('\r');
  536. pszBuf = psz;
  537. }
  538. return ULS_SUCCESS;
  539. }
  540. /*
  541. @doc EXTERNAL ULCLIENT
  542. @api HRESULT | CULSLaunch_Stub::FreeUlsHttpResp |
  543. Frees internal resources in a generic HTTP-based
  544. response structure.
  545. @parm ULS_HTTP_RESP * | pResp | A pointer to the generic
  546. HTTP response structure.
  547. @rdesc Returns ULS_SUCCESS if this operation succeeds.
  548. @comm The internal resources must be created by
  549. the ParseUlsHttpRespFile method or
  550. the ParseUlsHttpRespBuffer method.
  551. */
  552. STDMETHODIMP CULSLaunch_Stub::FreeUlsHttpResp ( ULS_HTTP_RESP *pResp )
  553. {
  554. if (pResp->pszUID)
  555. {
  556. delete [] pResp->pszUID;
  557. pResp->pszUID = NULL;
  558. }
  559. if (pResp->pszURL)
  560. {
  561. delete [] pResp->pszURL;
  562. pResp->pszURL = NULL;
  563. }
  564. return ULS_SUCCESS;
  565. }