|
|
//--------------------------------------------------------------------------
//
// Module Name: LaunStub.Cpp
//
// Brief Description:
// This module contains the code that parses HTTP-based
// response from the ULS server.
//
// Author: Chu, Lon-Chan (lonchanc)
//
// Copyright (c) 1996 Microsoft Corporation
//
//--------------------------------------------------------------------------
#include "precomp.h"
#include "launstub.h"
PTSTR LocalStrDup ( PTSTR pszToDup ) { UINT uLen; PTSTR psz = NULL;
if (pszToDup) { uLen = lstrlen (pszToDup); psz = (PTSTR) new TCHAR[uLen + 1]; if (psz) { lstrcpy (psz, pszToDup); } }
return psz; }
ULONG DecStrToInt ( PTSTR psz ) { ULONG ul = 0; WORD w;
if (psz) { while ((w = (WORD) *psz++) != NULL) { if (TEXT ('0') <= w && w <= TEXT ('9')) { w -= TEXT ('0'); ul = ul * 10 + w; } else { break; } } }
return ul; }
ULONG HexStrToInt ( PTSTR psz ) { ULONG ul = 0; WORD w;
if (psz) { while ((w = (WORD) *psz++) != NULL) { if (TEXT ('0') <= w && w <= TEXT ('9')) { w -= TEXT ('0'); } else if (TEXT ('a') <= w && w <= TEXT ('f')) { w -= (TEXT ('a') - 10); } else if (TEXT ('A') <= w && w <= TEXT ('F')) { w -= (TEXT ('A') - 10); } else { break; }
ul = (ul << 4) + w; } }
return ul; }
BOOL IsWhiteSpace ( TCHAR c ) { return (c == TEXT (' ') || c == TEXT ('\t') || c == TEXT ('\r') || c == TEXT ('\n')); }
enum { // beta 3 strings
ATTR_HR, ATTR_PORT, ATTR_HA, ATTR_HC, ATTR_CID, ATTR_UID, ATTR_URL, ATTR_IP, ATTR_MT,
B3ATTR_COUNT };
static PTSTR g_B3Attr[B3ATTR_COUNT] = { // beta 3 strings
TEXT ("HR"), TEXT ("PORT"), TEXT ("HA"), TEXT ("HC"), TEXT ("CID"), TEXT ("UID"), TEXT ("URL"), TEXT ("IP"), TEXT ("MT"), };
enum { // beta 4 strings
ATTR_HRESULT, ATTR_HCLIENT, ATTR_HAPPLICATION, ATTR_NAPPS, ATTR_IPADDRESS, ATTR_PORTNUM, ATTR_APPID, ATTR_PROTID, ATTR_USERID, ATTR_MIMETYPE, ATTR_APPMIME, ATTR_PROTMIME, ATTR_QUERYURL,
B4ATTR_COUNT };
static PTSTR g_B4Attr[B4ATTR_COUNT] = { // beta 4 strings
TEXT ("hresult"), TEXT ("hclient"), TEXT ("happlication"), TEXT ("napps"), TEXT ("ipaddress"), TEXT ("portnum"), TEXT ("appid"), TEXT ("protid"), TEXT ("userid"), TEXT ("mimetype"), TEXT ("appmime"), TEXT ("protmime"), TEXT ("queryurl"), };
typedef struct tagULPCMD { PTSTR pszCmd; ULONG nCmdId; } ULPCMD;
static ULPCMD g_B3Cmd[] = { { TEXT ("ON"), CLIENT_MESSAGE_ID_LOGON }, { TEXT ("OFF"), CLIENT_MESSAGE_ID_LOGOFF }, { TEXT ("KA"), CLIENT_MESSAGE_ID_KEEPALIVE }, { TEXT ("RES"), CLIENT_MESSAGE_ID_RESOLVE }, };
static ULPCMD g_B4Cmd[] = { { TEXT ("on"), CLIENT_MESSAGE_ID_LOGON }, { TEXT ("off"), CLIENT_MESSAGE_ID_LOGOFF }, { TEXT ("ka"), CLIENT_MESSAGE_ID_KEEPALIVE }, { TEXT ("res"), CLIENT_MESSAGE_ID_RESOLVE }, };
/*
@doc EXTERNAL ULCLIENT @api HRESULT | CULSLaunch_Stub::ParseUlsHttpRespFile | Parses a HTTP-based response from the ULS server. @parm PTSTR | pszUlsFile | A pointer to the HTTP-based response file name string. @parm ULS_HTTP_RESP * | pResp | A pointer to the generic HTTP response structure. @rdesc Returns ULS_SUCCESS if this operation succeeds. @comm This method parses the responses from the commands defined in the g_B3Cmd array. The attributes this method understands are listed in the g_B3Attr array. */
STDMETHODIMP CULSLaunch_Stub::ParseUlsHttpRespFile ( PTSTR pszUlsFile, ULS_HTTP_RESP *pResp ) { HANDLE hf = INVALID_HANDLE_VALUE; HRESULT hr; PTSTR pszBuf = NULL; ULONG cbFileSize;
// clean up the structure first
ZeroMemory (pResp, sizeof (ULS_HTTP_RESP)); pResp->cbSize = sizeof (ULS_HTTP_RESP);
// open the uls file
hf = CreateFile (pszUlsFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | // FILE_FLAG_DELETE_ON_CLOSE, NULL);
0, NULL); if (hf == INVALID_HANDLE_VALUE) { return ULS_E_INVALID_HANDLE; }
// get the size of the uls file
cbFileSize = GetFileSize (hf, NULL); if (! cbFileSize) { return ULS_E_INVALID_HANDLE; }
// round up to align with the paragraph boundary
cbFileSize = ((cbFileSize + 4) & (~ 0x0F)) + 0x10;
// allocate a buffer to hold the entire uls file
pszBuf = (PTSTR) new TCHAR[cbFileSize]; if (! pszBuf) { hr = ULS_E_OUTOFMEMORY; goto MyExit; }
// read the file in
if (! ReadFile (hf, pszBuf, cbFileSize, &cbFileSize, NULL)) { hr = ULS_E_IO_ERROR; goto MyExit; }
// parse the uls buffer
hr = ParseUlsHttpRespBuffer (pszBuf, cbFileSize, pResp); if (hr != ULS_SUCCESS) { goto MyExit; }
MyExit:
if (hf != INVALID_HANDLE_VALUE) CloseHandle (hf);
delete [] pszBuf;
if (hr != ULS_SUCCESS && pResp) { FreeUlsHttpResp (pResp); }
return hr; }
/*
@doc EXTERNAL ULCLIENT @api HRESULT | CULSLaunch_Stub::ParseUlsHttpRespBuffer | Parses a HTTP-based response from the ULS server. @parm PTSTR | pszBuf | A pointer to the buffer holding the entire HTTP-based response data. @parm ULONG | cbBufSize | The size in byte of the buffer. @parm ULS_HTTP_RESP * | pResp | A pointer to the generic HTTP response structure. @rdesc Returns ULS_SUCCESS if this operation succeeds. @comm This method parses the responses from the commands defined in the g_B3Cmd array. The attributes this method understands are listed in the g_B3Attr array. */
STDMETHODIMP CULSLaunch_Stub::ParseUlsHttpRespBuffer ( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp ) { HRESULT hr;
#ifdef SANITY_CHECK
// sanity check
if (MyIsBadReadPtr (pszBuf, cbBufSize) || MyIsBadWritePtr (pResp, sizeof (ULS_HTTP_RESP))) { return ULS_E_INVALID_POINTER; } #endif
hr = ParseB3HttpRespBuffer (pszBuf, cbBufSize, pResp);
if (hr == ULS_E_INVALID_FORMAT) { ZeroMemory (pResp, sizeof (ULS_HTTP_RESP)); pResp->cbSize = sizeof (ULS_HTTP_RESP); hr = ParseB4HttpRespBuffer (pszBuf, cbBufSize, pResp); }
return hr; }
HRESULT CULSLaunch_Stub::ParseB3HttpRespBuffer // beta 3 implementation
( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp ) { PTSTR psz; int i;
// get mime type
psz = (LPTSTR)_StrChr (pszBuf, TEXT ('<')); if (! psz) return ULS_E_INVALID_FORMAT; pszBuf = psz + 1; psz = (LPTSTR)_StrChr (pszBuf, TEXT ('>')); if (! psz) return ULS_E_INVALID_FORMAT; *psz = TEXT ('\0'); lstrcpyn (pResp->szMimeType, pszBuf, MAX_MIME_TYPE_LENGTH);
// get to the type of response
pszBuf = psz + 1; psz = (LPTSTR)_StrChr (pszBuf, TEXT ('<')); if (! psz) return ULS_E_INVALID_FORMAT; pszBuf = psz + 1; psz = (LPTSTR)_StrChr (pszBuf, TEXT ('[')); if (! psz) return ULS_E_INVALID_FORMAT; pszBuf = psz + 1; psz = (LPTSTR)_StrChr (pszBuf, TEXT (']')); if (! psz) return ULS_E_INVALID_FORMAT; *psz = TEXT ('\0'); pResp->nCmdId = (ULONG) -1; for (i = 0; i < sizeof (g_B3Cmd) / sizeof (g_B3Cmd[0]); i++) { if (! lstrcmpi (pszBuf, g_B3Cmd[i].pszCmd)) { pResp->nCmdId = g_B3Cmd[i].nCmdId; break; } } if (pResp->nCmdId == (ULONG) -1) return ULS_E_INVALID_FORMAT;
// skip any white space
for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; }
// main loop
while (*pszBuf && *pszBuf != TEXT ('>')) { // locate the equal sign
psz = (LPTSTR)_StrChr (pszBuf, TEXT ('=')); if (! psz) return ULS_E_INVALID_FORMAT; *psz = TEXT ('\0');
// search for attribute
for (i = 0; i < sizeof (g_B3Attr) / sizeof (g_B3Attr[0]); i++) { if (! lstrcmpi (pszBuf, g_B3Attr[i])) { break; } } if (i >= sizeof (g_B3Attr) / sizeof (g_B3Attr[0])) return ULS_E_INVALID_FORMAT;
// locate the attribute value
for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; } for (psz = pszBuf + 1; *psz; psz++) { if (IsWhiteSpace (*psz)) break; } *psz = TEXT ('\0'); // now the attribute value is a null-terminated string pointed by pszBuf
// parse the attribute value
switch (i) { case ATTR_HR: pResp->hr = HexStrToInt (pszBuf); break;
case ATTR_PORT: pResp->nPort = DecStrToInt (pszBuf); break;
case ATTR_HA: pResp->dwAppSession = HexStrToInt (pszBuf); break;
case ATTR_HC: pResp->dwClientSession = HexStrToInt (pszBuf); break;
case ATTR_CID: pResp->dwClientId = HexStrToInt (pszBuf); break;
case ATTR_UID: ASSERT(!pResp->pszUID); pResp->pszUID = LocalStrDup (pszBuf); break;
case ATTR_URL: ASSERT(!pResp->pszURL); pResp->pszURL = LocalStrDup (pszBuf); break;
case ATTR_IP: lstrcpyn (pResp->szIPAddress, pszBuf, MAX_IP_ADDRESS_STRING_LENGTH); break;
case ATTR_MT: // already got it
break; }
// skip any white space
for (pszBuf = psz + 1; *pszBuf; pszBuf++) { if (! IsWhiteSpace (*pszBuf)) break; } }
return ULS_SUCCESS; }
HRESULT CULSLaunch_Stub::ParseB4HttpRespBuffer // beta 4 implementation
( PTSTR pszBuf, ULONG cbBufSize, ULS_HTTP_RESP *pResp ) { PTSTR psz, pszSave; int i;
// get mime type
psz = (LPTSTR)_StrChr (pszBuf, TEXT ('[')); if (! psz) { return ULS_E_INVALID_FORMAT; } pszBuf = psz + 1; psz = (LPTSTR)_StrChr (pszBuf, TEXT (']')); if (! psz) { return ULS_E_INVALID_FORMAT; } *psz = TEXT ('\0');
// now pszBuf is ptr to the string inside [], such on, off, ka, res.
pResp->nCmdId = (ULONG) -1; for (i = 0; i < sizeof (g_B4Cmd) / sizeof (g_B4Cmd[0]); i++) { if (! lstrcmpi (pszBuf, g_B4Cmd[i].pszCmd)) { pResp->nCmdId = g_B4Cmd[i].nCmdId; break; } }
// to see if this cmd is something I don't know
if (pResp->nCmdId == (ULONG) -1) { return ULS_E_INVALID_FORMAT; }
// update the buf ptr
pszBuf = psz + 1;
// main loop
while (*pszBuf) { // locate a \r \n
while (*pszBuf != TEXT ('\r') && *pszBuf != TEXT ('\n')) { pszBuf++; }
// skip any white space including \r \n
while (*pszBuf) { if (! IsWhiteSpace (*pszBuf)) { break; } pszBuf++; }
// end of file
if (! *pszBuf) { return ULS_SUCCESS; } // locate the equal sign
psz = (LPTSTR)_StrChr (pszBuf, TEXT ('=')); if (! psz) { continue; // cannot goto NextLine because psz==NULL
}
// to make pszBuf ptr to the attr name
*psz = TEXT ('\0');
// search for attribute
for (i = 0; i < sizeof (g_B4Attr) / sizeof (g_B4Attr[0]); i++) { if (! lstrcmpi (pszBuf, g_B4Attr[i])) { break; } }
// is this attribute valid? if not, ignore it!
if (i >= sizeof (g_B4Attr) / sizeof (g_B4Attr[0])) { goto NextLine; }
// locate pszBuf now ptr to attr value
pszBuf = psz + 1;
// get to the end of line
for (psz = pszBuf; *psz; psz++) { if (*psz == TEXT ('\r') || *psz == TEXT ('\n')) { break; } }
// deal with attrname=\r\nEOF
if (! *psz) { return ULS_SUCCESS; }
// make the attr value is a null-terminated string pointed by pszBuf
*psz = TEXT ('\0');
// parse the attribute value
switch (i) { case ATTR_HRESULT: pResp->hr = HexStrToInt (pszBuf); break;
case ATTR_PORTNUM: pResp->nPort = DecStrToInt (pszBuf); break;
case ATTR_HAPPLICATION: pResp->dwAppSession = HexStrToInt (pszBuf); break;
case ATTR_HCLIENT: pResp->dwClientSession = HexStrToInt (pszBuf); break;
case ATTR_USERID: pszSave = pResp->pszUID; pResp->pszUID = LocalStrDup (pszBuf); if (pResp->pszUID) { delete [] pszSave; } else { pResp->pszUID = pszSave; // restore
} break;
case ATTR_QUERYURL: pszSave = pResp->pszURL; pResp->pszURL = LocalStrDup (pszBuf); if (pResp->pszURL) { delete [] pszSave; } else { pResp->pszURL = pszSave; // restore
} break;
case ATTR_IPADDRESS: lstrcpyn (pResp->szIPAddress, pszBuf, sizeof (pResp->szIPAddress) / sizeof (pResp->szIPAddress[0])); break;
case ATTR_MIMETYPE: lstrcpyn (pResp->szMimeType, pszBuf, sizeof (pResp->szMimeType) / sizeof (pResp->szMimeType[0])); break;
case ATTR_APPMIME: lstrcpyn (pResp->szAppMime, pszBuf, sizeof (pResp->szAppMime) / sizeof (pResp->szAppMime[0])); break;
case ATTR_PROTMIME: lstrcpyn (pResp->szProtMime, pszBuf, sizeof (pResp->szProtMime) / sizeof (pResp->szProtMime[0])); break;
case ATTR_APPID: lstrcpyn (pResp->szAppId, pszBuf, sizeof (pResp->szAppId) / sizeof (pResp->szAppId[0])); break;
case ATTR_PROTID: lstrcpyn (pResp->szProtId, pszBuf, sizeof (pResp->szProtId) / sizeof (pResp->szProtId[0])); break;
case ATTR_NAPPS: pResp->nApps = DecStrToInt (pszBuf); break;
default: break; }
NextLine:
// make sure we are at \r \n
*psz = TEXT ('\r'); pszBuf = psz; }
return ULS_SUCCESS; }
/*
@doc EXTERNAL ULCLIENT @api HRESULT | CULSLaunch_Stub::FreeUlsHttpResp | Frees internal resources in a generic HTTP-based response structure. @parm ULS_HTTP_RESP * | pResp | A pointer to the generic HTTP response structure. @rdesc Returns ULS_SUCCESS if this operation succeeds. @comm The internal resources must be created by the ParseUlsHttpRespFile method or the ParseUlsHttpRespBuffer method. */
STDMETHODIMP CULSLaunch_Stub::FreeUlsHttpResp ( ULS_HTTP_RESP *pResp ) { if (pResp->pszUID) { delete [] pResp->pszUID; pResp->pszUID = NULL; }
if (pResp->pszURL) { delete [] pResp->pszURL; pResp->pszURL = NULL; }
return ULS_SUCCESS; }
|