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.

441 lines
13 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name :
  4. logging.cxx
  5. Abstract:
  6. Handle Logging
  7. Author:
  8. Anil Ruia (AnilR) 1-Jul-2000
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. w3core.dll
  13. --*/
  14. #include "precomp.hxx"
  15. CONTEXT_STATUS W3_STATE_LOG::DoWork(
  16. W3_MAIN_CONTEXT *pMainContext,
  17. DWORD,
  18. DWORD)
  19. /*++
  20. Routine Description:
  21. Log the request (and call the END_OF_REQUEST notification)
  22. Arguments:
  23. pMainContext - W3_MAIN_CONTEXT representing an execution of the
  24. state machine
  25. Return Value:
  26. CONTEXT_STATUS_CONTINUE - if we should continue in state machine
  27. else stop executing the machine and free up the current thread
  28. --*/
  29. {
  30. BOOL fUnused = FALSE;
  31. if (pMainContext->QueryNeedFinalDone())
  32. {
  33. //
  34. // Clear remaining chunks from handle/response state
  35. //
  36. pMainContext->QueryResponse()->Clear();
  37. //
  38. // End of request notifications happen BEFORE logging.
  39. //
  40. if ( pMainContext->IsNotificationNeeded( SF_NOTIFY_END_OF_REQUEST ) )
  41. {
  42. pMainContext->NotifyFilters( SF_NOTIFY_END_OF_REQUEST,
  43. NULL,
  44. &fUnused );
  45. }
  46. //
  47. // Clear any crud from the last write from END_OF_REQUEST filter
  48. //
  49. pMainContext->QueryResponse()->Clear();
  50. //
  51. // Do the final send
  52. //
  53. pMainContext->SendEntity(W3_FLAG_PAST_END_OF_REQ);
  54. }
  55. if (pMainContext->QueryDoCustomLogging())
  56. {
  57. if (FAILED(pMainContext->CollectLoggingData(FALSE)))
  58. {
  59. goto Exit;
  60. }
  61. pMainContext->QuerySite()->LogInformation(pMainContext->QueryLogContext());
  62. }
  63. Exit:
  64. return CONTEXT_STATUS_CONTINUE;
  65. }
  66. CONTEXT_STATUS W3_STATE_LOG::OnCompletion(
  67. W3_MAIN_CONTEXT *pMainContext,
  68. DWORD,
  69. DWORD)
  70. /*++
  71. Routine Description:
  72. Completion for the W3_STATE_LOG state
  73. Arguments:
  74. pMainContext - W3_MAIN_CONTEXT representing an execution of the
  75. state machine
  76. Return Value:
  77. CONTEXT_STATUS_CONTINUE - if we should continue in state machine
  78. else stop executing the machine and free up the current thread
  79. --*/
  80. {
  81. //
  82. // This code should never get hit
  83. //
  84. DBG_ASSERT(FALSE);
  85. return CONTEXT_STATUS_CONTINUE;
  86. }
  87. HRESULT W3_MAIN_CONTEXT::CollectLoggingData(BOOL fCollectForULLogging)
  88. /*++
  89. Routine Description:
  90. Routine which collects all the logging data
  91. Arguments:
  92. None
  93. Return Value:
  94. HRESULT
  95. --*/
  96. {
  97. STACK_STRA(strVal, 64);
  98. STACK_STRU(strValW, 64);
  99. HRESULT hr = S_OK;
  100. DWORD dwLength;
  101. HTTP_LOG_FIELDS_DATA *pUlLogData = QueryUlLogData();
  102. W3_REQUEST *pRequest = QueryRequest();
  103. if (IsNotificationNeeded(SF_NOTIFY_LOG))
  104. {
  105. //
  106. // There is a SF_NOTIFY_LOG filter, collect the data for the
  107. // notification
  108. //
  109. HTTP_FILTER_LOG filtLog;
  110. ZeroMemory(&filtLog, sizeof filtLog);
  111. if (SUCCEEDED(GetServerVariableRemoteHost(this, &strVal)))
  112. {
  113. dwLength = strVal.QueryCCH() + 1;
  114. if (FAILED(hr = _HeaderBuffer.AllocateSpace(
  115. dwLength,
  116. (PCHAR *)&filtLog.pszClientHostName)))
  117. {
  118. goto Exit;
  119. }
  120. strVal.CopyToBuffer((LPSTR)filtLog.pszClientHostName,
  121. &dwLength);
  122. }
  123. if (SUCCEEDED(GetServerVariableLogonUser(this, &strVal)))
  124. {
  125. dwLength = strVal.QueryCCH() + 1;
  126. if (FAILED(hr = _HeaderBuffer.AllocateSpace(
  127. dwLength,
  128. (PCHAR *)&filtLog.pszClientUserName)))
  129. {
  130. goto Exit;
  131. }
  132. strVal.CopyToBuffer((LPSTR)filtLog.pszClientUserName,
  133. &dwLength);
  134. }
  135. else
  136. {
  137. filtLog.pszClientUserName = "";
  138. }
  139. if (SUCCEEDED(GetServerVariableLocalAddr(this, &strVal)))
  140. {
  141. dwLength = strVal.QueryCCH() + 1;
  142. if (FAILED(hr = _HeaderBuffer.AllocateSpace(
  143. dwLength,
  144. (PCHAR *)&filtLog.pszServerName)))
  145. {
  146. goto Exit;
  147. }
  148. strVal.CopyToBuffer((LPSTR)filtLog.pszServerName,
  149. &dwLength);
  150. }
  151. pRequest->QueryVerb((CHAR **)&filtLog.pszOperation, (USHORT *)&dwLength);
  152. if (FAILED(hr = pRequest->GetUrl(&strValW)) ||
  153. FAILED(hr = strVal.CopyWToUTF8(strValW)) ||
  154. FAILED(hr = _HeaderBuffer.AllocateSpace(
  155. strVal.QueryStr(),
  156. strVal.QueryCCH(),
  157. (CHAR **)&filtLog.pszTarget)))
  158. {
  159. goto Exit;
  160. }
  161. //
  162. // If an ISAPI used HSE_APPEND_LOG_PARAMETER use it
  163. //
  164. if (_LogContext.m_strLogParam.IsEmpty())
  165. {
  166. pRequest->GetQueryStringA(&_LogContext.m_strLogParam);
  167. }
  168. filtLog.pszParameters = _LogContext.m_strLogParam.QueryStr();
  169. filtLog.dwHttpStatus = QueryResponse()->QueryStatusCode();
  170. if ( HRESULT_FACILITY( QueryErrorStatus() ) == FACILITY_WIN32 )
  171. {
  172. filtLog.dwWin32Status = WIN32_FROM_HRESULT( QueryErrorStatus() );
  173. }
  174. else
  175. {
  176. filtLog.dwWin32Status = QueryErrorStatus();
  177. }
  178. filtLog.dwBytesSent = _LogContext.m_dwBytesSent;
  179. filtLog.dwBytesRecvd = _LogContext.m_dwBytesRecvd;
  180. filtLog.msTimeForProcessing = GetTickCount() - _LogContext.m_msStartTickCount;
  181. NotifyFilters(SF_NOTIFY_LOG, &filtLog, NULL);
  182. //
  183. // The filter may have changed some the data, copy it back to our
  184. // logging structure
  185. //
  186. pUlLogData->ClientIp = (CHAR *)filtLog.pszClientHostName;
  187. pUlLogData->ClientIpLength = (USHORT) strlen(filtLog.pszClientHostName);
  188. if (FAILED(hr = strValW.CopyA(filtLog.pszClientUserName)) ||
  189. FAILED(hr = _HeaderBuffer.AllocateSpace(
  190. strValW.QueryStr(),
  191. strValW.QueryCCH(),
  192. &pUlLogData->UserName)))
  193. {
  194. goto Exit;
  195. }
  196. pUlLogData->UserNameLength =
  197. (USHORT)(strValW.QueryCCH() * sizeof(WCHAR));
  198. pUlLogData->ServerIp = (CHAR *)filtLog.pszServerName;
  199. pUlLogData->ServerIpLength = (USHORT) strlen(filtLog.pszServerName);
  200. pUlLogData->Method = (CHAR *)filtLog.pszOperation;
  201. pUlLogData->MethodLength = (USHORT) strlen(filtLog.pszOperation);
  202. if (FAILED(hr = strValW.CopyA(filtLog.pszTarget)) ||
  203. FAILED(hr = _HeaderBuffer.AllocateSpace(
  204. strValW.QueryStr(),
  205. strValW.QueryCCH(),
  206. &pUlLogData->UriStem)))
  207. {
  208. goto Exit;
  209. }
  210. pUlLogData->UriStemLength =
  211. (USHORT)(strValW.QueryCCH() * sizeof(WCHAR));
  212. pUlLogData->UriQuery = (CHAR *)filtLog.pszParameters;
  213. pUlLogData->UriQueryLength = (USHORT) strlen(filtLog.pszParameters);
  214. pUlLogData->ProtocolStatus = filtLog.dwHttpStatus;
  215. pUlLogData->Win32Status = filtLog.dwWin32Status;
  216. _LogContext.m_dwBytesSent = filtLog.dwBytesSent;
  217. _LogContext.m_dwBytesRecvd = filtLog.dwBytesRecvd;
  218. _LogContext.m_msProcessingTime = filtLog.msTimeForProcessing;
  219. }
  220. else
  221. {
  222. //
  223. // No filter, just get the logging data
  224. //
  225. if (SUCCEEDED(GetServerVariableRemoteHost(this, &strVal)))
  226. {
  227. if (FAILED(hr = _HeaderBuffer.AllocateSpace(
  228. strVal.QueryStr(),
  229. strVal.QueryCCH(),
  230. &pUlLogData->ClientIp)))
  231. {
  232. goto Exit;
  233. }
  234. pUlLogData->ClientIpLength = (USHORT)strVal.QueryCCH();
  235. }
  236. if ( QueryUserContext() == NULL )
  237. {
  238. if (FAILED(hr = pRequest->GetRequestUserName(&strVal)))
  239. {
  240. goto Exit;
  241. }
  242. if (strVal.IsEmpty())
  243. {
  244. pUlLogData->UserName = L"";
  245. pUlLogData->UserNameLength = 0;
  246. }
  247. else
  248. {
  249. if (FAILED(hr = strValW.CopyA(strVal.QueryStr())) ||
  250. FAILED(hr = _HeaderBuffer.AllocateSpace(
  251. strValW.QueryStr(),
  252. strValW.QueryCCH(),
  253. &pUlLogData->UserName)))
  254. {
  255. goto Exit;
  256. }
  257. pUlLogData->UserNameLength = (USHORT)strValW.QueryCB();
  258. }
  259. }
  260. else
  261. {
  262. pUlLogData->UserName = QueryUserContext()->QueryUserName();
  263. if (pUlLogData->UserName)
  264. {
  265. pUlLogData->UserNameLength = wcslen(pUlLogData->UserName) * sizeof(WCHAR);
  266. }
  267. }
  268. if (SUCCEEDED(GetServerVariableLocalAddr(this, &strVal)))
  269. {
  270. if (FAILED(hr = _HeaderBuffer.AllocateSpace(
  271. strVal.QueryStr(),
  272. strVal.QueryCCH(),
  273. &pUlLogData->ServerIp)))
  274. {
  275. goto Exit;
  276. }
  277. pUlLogData->ServerIpLength =
  278. (USHORT)strVal.QueryCCH();
  279. }
  280. pRequest->QueryVerb(&pUlLogData->Method,
  281. &pUlLogData->MethodLength);
  282. pRequest->QueryUrl(&pUlLogData->UriStem,
  283. &pUlLogData->UriStemLength);
  284. //
  285. // If an ISAPI used HSE_APPEND_LOG_PARAMETER use it
  286. //
  287. if (_LogContext.m_strLogParam.IsEmpty())
  288. {
  289. pRequest->GetQueryStringA(&_LogContext.m_strLogParam);
  290. }
  291. pUlLogData->UriQuery = _LogContext.m_strLogParam.QueryStr();
  292. pUlLogData->UriQueryLength = (USHORT)_LogContext.m_strLogParam.QueryCCH();
  293. pUlLogData->ProtocolStatus = QueryResponse()->QueryStatusCode();
  294. if ( HRESULT_FACILITY( QueryErrorStatus() ) == FACILITY_WIN32 )
  295. {
  296. pUlLogData->Win32Status = WIN32_FROM_HRESULT( QueryErrorStatus() );
  297. }
  298. else
  299. {
  300. pUlLogData->Win32Status = QueryErrorStatus();
  301. }
  302. }
  303. //
  304. // Now get data unaffected by any SF_NOTIFY_LOG filter
  305. //
  306. pUlLogData->ServerPort = pRequest->QueryLocalPort();
  307. pUlLogData->ServiceName = QuerySite()->QueryName()->QueryStr();
  308. pUlLogData->ServiceNameLength = (USHORT)QuerySite()->QueryName()->QueryCCH();
  309. pUlLogData->ServerName = g_pW3Server->QueryComputerName();
  310. pUlLogData->ServerNameLength = g_pW3Server->QueryComputerNameLength();
  311. if (fCollectForULLogging)
  312. {
  313. pUlLogData->Host = pRequest->GetHeader(HttpHeaderHost,
  314. &pUlLogData->HostLength);
  315. pUlLogData->UserAgent = pRequest->GetHeader(HttpHeaderUserAgent,
  316. &pUlLogData->UserAgentLength);
  317. pUlLogData->Cookie = pRequest->GetHeader(HttpHeaderCookie,
  318. &pUlLogData->CookieLength);
  319. pUlLogData->Referrer = pRequest->GetHeader(HttpHeaderReferer,
  320. &pUlLogData->ReferrerLength);
  321. }
  322. else
  323. {
  324. _LogContext.m_msProcessingTime =
  325. GetTickCount() - _LogContext.m_msStartTickCount;
  326. GetServerVariableHttpVersion(this,
  327. &_LogContext.m_strVersion);
  328. if (QuerySite()->IsRequiredExtraLoggingFields())
  329. {
  330. //
  331. // If the custom logging module needs extra logging fields, get them
  332. //
  333. const MULTISZA *pmszExtraLoggingFields =
  334. QuerySite()->QueryExtraLoggingFields();
  335. LPSTR pszHeaderName = (LPSTR)pmszExtraLoggingFields->First();
  336. while (pszHeaderName != NULL)
  337. {
  338. hr = SERVER_VARIABLE_HASH::GetServerVariable(
  339. this,
  340. pszHeaderName,
  341. &strVal);
  342. if (FAILED(hr))
  343. {
  344. goto Exit;
  345. }
  346. if (!_LogContext.m_mszHTTPHeaders.Append(strVal.QueryStr()))
  347. {
  348. hr = E_OUTOFMEMORY;
  349. goto Exit;
  350. }
  351. pszHeaderName = (LPSTR)pmszExtraLoggingFields->Next(pszHeaderName);
  352. }
  353. }
  354. }
  355. Exit:
  356. return hr;
  357. }