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.

495 lines
15 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 *,
  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. fCollectForULLogging - whether the data is being collected for http.sys/custom logging
  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. CHUNK_BUFFER * pHeaderBuffer;
  102. HTTP_LOG_FIELDS_DATA *pUlLogData = QueryUlLogData();
  103. W3_REQUEST *pRequest = QueryRequest();
  104. W3_RESPONSE *pResponse = QueryResponse();
  105. pHeaderBuffer = QueryHeaderBuffer();
  106. DBG_ASSERT( pHeaderBuffer != NULL );
  107. if (IsNotificationNeeded(SF_NOTIFY_LOG))
  108. {
  109. //
  110. // There is a SF_NOTIFY_LOG filter, collect the data for the
  111. // notification
  112. //
  113. HTTP_FILTER_LOG filtLog;
  114. ZeroMemory(&filtLog, sizeof filtLog);
  115. if (SUCCEEDED(hr = GetServerVariableRemoteHost(this, &strVal)))
  116. {
  117. dwLength = strVal.QueryCCH() + 1;
  118. if (FAILED(hr = pHeaderBuffer->AllocateSpace(
  119. dwLength,
  120. (PCHAR *)&filtLog.pszClientHostName)))
  121. {
  122. goto Exit;
  123. }
  124. strVal.CopyToBuffer((LPSTR)filtLog.pszClientHostName,
  125. &dwLength);
  126. }
  127. else
  128. {
  129. goto Exit;
  130. }
  131. if (SUCCEEDED(hr = GetServerVariableLogonUser(this, &strVal)))
  132. {
  133. dwLength = strVal.QueryCCH() + 1;
  134. if (FAILED(hr = pHeaderBuffer->AllocateSpace(
  135. dwLength,
  136. (PCHAR *)&filtLog.pszClientUserName)))
  137. {
  138. goto Exit;
  139. }
  140. strVal.CopyToBuffer((LPSTR)filtLog.pszClientUserName,
  141. &dwLength);
  142. }
  143. else
  144. {
  145. goto Exit;
  146. }
  147. if (SUCCEEDED(hr = GetServerVariableLocalAddr(this, &strVal)))
  148. {
  149. dwLength = strVal.QueryCCH() + 1;
  150. if (FAILED(hr = pHeaderBuffer->AllocateSpace(
  151. dwLength,
  152. (PCHAR *)&filtLog.pszServerName)))
  153. {
  154. goto Exit;
  155. }
  156. strVal.CopyToBuffer((LPSTR)filtLog.pszServerName,
  157. &dwLength);
  158. }
  159. else
  160. {
  161. goto Exit;
  162. }
  163. pRequest->QueryVerb((CHAR **)&filtLog.pszOperation, (USHORT *)&dwLength);
  164. if (FAILED(hr = pRequest->GetUrl(&strValW)) ||
  165. FAILED(hr = strVal.CopyWToUTF8(strValW)) ||
  166. FAILED(hr = pHeaderBuffer->AllocateSpace(
  167. strVal.QueryStr(),
  168. strVal.QueryCCH(),
  169. (CHAR **)&filtLog.pszTarget)))
  170. {
  171. goto Exit;
  172. }
  173. //
  174. // If an ISAPI used HSE_APPEND_LOG_PARAMETER use it
  175. //
  176. if (_LogContext.m_strLogParam.IsEmpty())
  177. {
  178. if (FAILED(hr = pRequest->GetQueryStringA(&_LogContext.m_strLogParam)))
  179. {
  180. goto Exit;
  181. }
  182. }
  183. filtLog.pszParameters = _LogContext.m_strLogParam.QueryStr();
  184. filtLog.dwHttpStatus = pResponse->QueryStatusCode();
  185. if ( HRESULT_FACILITY( QueryErrorStatus() ) == FACILITY_WIN32 )
  186. {
  187. filtLog.dwWin32Status = WIN32_FROM_HRESULT( QueryErrorStatus() );
  188. }
  189. else
  190. {
  191. filtLog.dwWin32Status = QueryErrorStatus();
  192. }
  193. filtLog.dwBytesSent = _LogContext.m_dwBytesSent;
  194. filtLog.dwBytesRecvd = _LogContext.m_dwBytesRecvd;
  195. filtLog.msTimeForProcessing = GetTickCount() - _LogContext.m_msStartTickCount;
  196. NotifyFilters(SF_NOTIFY_LOG, &filtLog, NULL);
  197. //
  198. // The filter may have changed some the data, copy it back to our
  199. // logging structure
  200. //
  201. pUlLogData->ClientIp = (CHAR *)filtLog.pszClientHostName;
  202. pUlLogData->ClientIpLength = (USHORT) strlen(filtLog.pszClientHostName);
  203. if (FAILED(hr = strValW.CopyA(filtLog.pszClientUserName)) ||
  204. FAILED(hr = pHeaderBuffer->AllocateSpace(
  205. strValW.QueryStr(),
  206. strValW.QueryCCH(),
  207. (PWSTR*) &pUlLogData->UserName)))
  208. {
  209. goto Exit;
  210. }
  211. pUlLogData->UserNameLength =
  212. (USHORT)(strValW.QueryCCH() * sizeof(WCHAR));
  213. pUlLogData->ServerIp = (CHAR *)filtLog.pszServerName;
  214. pUlLogData->ServerIpLength = (USHORT) strlen(filtLog.pszServerName);
  215. pUlLogData->Method = (CHAR *)filtLog.pszOperation;
  216. pUlLogData->MethodLength = (USHORT) strlen(filtLog.pszOperation);
  217. pUlLogData->MethodNum = (HTTP_VERB)METHOD_HASH::GetIndex((CHAR *)filtLog.pszOperation);
  218. if (FAILED(hr = strValW.CopyA(filtLog.pszTarget)) ||
  219. FAILED(hr = pHeaderBuffer->AllocateSpace(
  220. strValW.QueryStr(),
  221. strValW.QueryCCH(),
  222. (PWSTR*) &pUlLogData->UriStem)))
  223. {
  224. goto Exit;
  225. }
  226. pUlLogData->UriStemLength =
  227. (USHORT)(strValW.QueryCCH() * sizeof(WCHAR));
  228. pUlLogData->UriQuery = (CHAR *)filtLog.pszParameters;
  229. pUlLogData->UriQueryLength = (USHORT) strlen(filtLog.pszParameters);
  230. pUlLogData->ProtocolStatus = (USHORT) filtLog.dwHttpStatus;
  231. pUlLogData->Win32Status = filtLog.dwWin32Status;
  232. _LogContext.m_dwBytesSent = filtLog.dwBytesSent;
  233. _LogContext.m_dwBytesRecvd = filtLog.dwBytesRecvd;
  234. _LogContext.m_msProcessingTime = filtLog.msTimeForProcessing;
  235. }
  236. else
  237. {
  238. //
  239. // No filter, just get the logging data
  240. //
  241. if (SUCCEEDED(hr = GetServerVariableRemoteHost(this, &strVal)))
  242. {
  243. if (FAILED(hr = pHeaderBuffer->AllocateSpace(
  244. strVal.QueryStr(),
  245. strVal.QueryCCH(),
  246. (PSTR*) &pUlLogData->ClientIp)))
  247. {
  248. goto Exit;
  249. }
  250. pUlLogData->ClientIpLength = (USHORT)strVal.QueryCCH();
  251. }
  252. else
  253. {
  254. goto Exit;
  255. }
  256. if ( QueryUserContext() == NULL )
  257. {
  258. if (FAILED(hr = pRequest->GetRequestUserName(&strVal)))
  259. {
  260. goto Exit;
  261. }
  262. if (strVal.IsEmpty())
  263. {
  264. pUlLogData->UserName = L"";
  265. pUlLogData->UserNameLength = 0;
  266. }
  267. else
  268. {
  269. if (FAILED(hr = strValW.CopyA(strVal.QueryStr())) ||
  270. FAILED(hr = pHeaderBuffer->AllocateSpace(
  271. strValW.QueryStr(),
  272. strValW.QueryCCH(),
  273. (PWSTR*) &pUlLogData->UserName)))
  274. {
  275. goto Exit;
  276. }
  277. pUlLogData->UserNameLength = (USHORT)strValW.QueryCB();
  278. }
  279. }
  280. else
  281. {
  282. pUlLogData->UserName = QueryUserContext()->QueryUserName();
  283. if (pUlLogData->UserName)
  284. {
  285. pUlLogData->UserNameLength = (USHORT)wcslen(pUlLogData->UserName) * sizeof(WCHAR);
  286. }
  287. }
  288. if (SUCCEEDED(hr = GetServerVariableLocalAddr(this, &strVal)))
  289. {
  290. if (FAILED(hr = pHeaderBuffer->AllocateSpace(
  291. strVal.QueryStr(),
  292. strVal.QueryCCH(),
  293. (PSTR*) &pUlLogData->ServerIp)))
  294. {
  295. goto Exit;
  296. }
  297. pUlLogData->ServerIpLength =
  298. (USHORT)strVal.QueryCCH();
  299. }
  300. else
  301. {
  302. goto Exit;
  303. }
  304. pRequest->QueryVerb((CHAR**) &pUlLogData->Method,
  305. &pUlLogData->MethodLength);
  306. pUlLogData->MethodNum = pRequest->QueryVerbType();
  307. pRequest->QueryUrl((WCHAR**) &pUlLogData->UriStem,
  308. &pUlLogData->UriStemLength);
  309. //
  310. // If an ISAPI used HSE_APPEND_LOG_PARAMETER use it
  311. //
  312. if (_LogContext.m_strLogParam.IsEmpty())
  313. {
  314. if (FAILED(hr = pRequest->GetQueryStringA(&_LogContext.m_strLogParam)))
  315. {
  316. goto Exit;
  317. }
  318. }
  319. pUlLogData->UriQuery = _LogContext.m_strLogParam.QueryStr();
  320. pUlLogData->UriQueryLength = (USHORT)_LogContext.m_strLogParam.QueryCCH();
  321. pUlLogData->ProtocolStatus = pResponse->QueryStatusCode();
  322. if ( HRESULT_FACILITY( QueryErrorStatus() ) == FACILITY_WIN32 )
  323. {
  324. pUlLogData->Win32Status = WIN32_FROM_HRESULT( QueryErrorStatus() );
  325. }
  326. else
  327. {
  328. pUlLogData->Win32Status = QueryErrorStatus();
  329. }
  330. if (!fCollectForULLogging)
  331. {
  332. _LogContext.m_msProcessingTime =
  333. GetTickCount() - _LogContext.m_msStartTickCount;
  334. }
  335. }
  336. //
  337. // Now get data unaffected by any SF_NOTIFY_LOG filter
  338. //
  339. HTTP_SUB_ERROR subError;
  340. pResponse->QuerySubError(&subError);
  341. pUlLogData->SubStatus = subError.mdSubError;
  342. pUlLogData->ServerPort = ntohs( pRequest->QueryLocalPort() );
  343. pUlLogData->ServiceName = QuerySite()->QueryName()->QueryStr();
  344. pUlLogData->ServiceNameLength = (USHORT)QuerySite()->QueryName()->QueryCCH();
  345. pUlLogData->ServerName = g_pW3Server->QueryComputerName();
  346. pUlLogData->ServerNameLength = g_pW3Server->QueryComputerNameLength();
  347. if (fCollectForULLogging)
  348. {
  349. pUlLogData->Host = pRequest->GetHeader(HttpHeaderHost,
  350. &pUlLogData->HostLength);
  351. pUlLogData->UserAgent = pRequest->GetHeader(HttpHeaderUserAgent,
  352. &pUlLogData->UserAgentLength);
  353. pUlLogData->Cookie = pRequest->GetHeader(HttpHeaderCookie,
  354. &pUlLogData->CookieLength);
  355. pUlLogData->Referrer = pRequest->GetHeader(HttpHeaderReferer,
  356. &pUlLogData->ReferrerLength);
  357. }
  358. else
  359. {
  360. if (FAILED(hr = GetServerVariableHttpVersion(this,
  361. &_LogContext.m_strVersion)))
  362. {
  363. goto Exit;
  364. }
  365. if (QuerySite()->IsRequiredExtraLoggingFields())
  366. {
  367. //
  368. // If the custom logging module needs extra logging fields, get them
  369. //
  370. const MULTISZA *pmszExtraLoggingFields =
  371. QuerySite()->QueryExtraLoggingFields();
  372. LPSTR pszHeaderName = (LPSTR)pmszExtraLoggingFields->First();
  373. STACK_STRA( strHeaderName, 128);
  374. while (pszHeaderName != NULL)
  375. {
  376. hr = strHeaderName.Copy( pszHeaderName,
  377. (DWORD)strlen(pszHeaderName) - 1 );
  378. if (FAILED(hr))
  379. {
  380. goto Exit;
  381. }
  382. hr = pRequest->GetHeader( strHeaderName,
  383. &strVal );
  384. if (FAILED(hr))
  385. {
  386. if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_INDEX))
  387. {
  388. strVal.Reset();
  389. hr = S_OK;
  390. }
  391. else
  392. {
  393. goto Exit;
  394. }
  395. }
  396. if (!_LogContext.m_mszHTTPHeaders.Append(strVal.QueryStr()))
  397. {
  398. hr = HRESULT_FROM_WIN32(GetLastError());
  399. goto Exit;
  400. }
  401. pszHeaderName = (LPSTR)pmszExtraLoggingFields->Next(pszHeaderName);
  402. }
  403. }
  404. }
  405. Exit:
  406. return hr;
  407. }