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.

769 lines
23 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. ullog.c (UL IIS+ HIT Logging)
  5. Abstract:
  6. This module implements the logging facilities
  7. for IIS+ including the NCSA, IIS and W3CE types
  8. of logging.
  9. Author:
  10. Ali E. Turkoglu (aliTu) 10-May-2000
  11. Revision History:
  12. --*/
  13. #ifndef _ULLOGP_H_
  14. #define _ULLOGP_H_
  15. #ifdef __cplusplus
  16. extern "C" {
  17. #endif
  18. //
  19. // Private definitions for the Ul Logging Module
  20. //
  21. #define UTF8_LOGGING_ENABLED() (g_UTF8Logging)
  22. #define _UL_GET_LOG_FILE_NAME_PREFIX(x) \
  23. ( (x) == HttpLoggingTypeW3C ? L"\\extend" : \
  24. (x) == HttpLoggingTypeIIS ? L"\\inetsv" : \
  25. (x) == HttpLoggingTypeNCSA ? L"\\ncsa" : L"\\unknwn" \
  26. )
  27. #define _UL_GET_LOG_FILE_NAME_PREFIX_UTF8(x) \
  28. ( (x) == HttpLoggingTypeW3C ? L"\\u_extend" : \
  29. (x) == HttpLoggingTypeIIS ? L"\\u_inetsv" : \
  30. (x) == HttpLoggingTypeNCSA ? L"\\u_ncsa" : L"\\u_unknwn" \
  31. )
  32. #define UL_GET_LOG_FILE_NAME_PREFIX(x) \
  33. (UTF8_LOGGING_ENABLED() ? _UL_GET_LOG_FILE_NAME_PREFIX_UTF8(x) :\
  34. _UL_GET_LOG_FILE_NAME_PREFIX(x))
  35. #define SPACE_TO_PLUS_CONVERSION_REQUIRED(x) \
  36. ( (x) == UlLogFieldCookie || \
  37. (x) == UlLogFieldReferrer || \
  38. (x) == UlLogFieldUserAgent || \
  39. (x) == UlLogFieldHost )
  40. //
  41. // Obsolete - Only used by Old Hit
  42. // Replace this with a switch statement inside a inline function
  43. // which is more efficient, if u start using it again
  44. //
  45. #define UL_GET_NAME_FOR_HTTP_VERB(v) \
  46. ( (v) == HttpVerbUnparsed ? L"UNPARSED" : \
  47. (v) == HttpVerbUnknown ? L"UNKNOWN" : \
  48. (v) == HttpVerbInvalid ? L"INVALID" : \
  49. (v) == HttpVerbOPTIONS ? L"OPTIONS" : \
  50. (v) == HttpVerbGET ? L"GET" : \
  51. (v) == HttpVerbHEAD ? L"HEAD" : \
  52. (v) == HttpVerbPOST ? L"POST" : \
  53. (v) == HttpVerbPUT ? L"PUT" : \
  54. (v) == HttpVerbDELETE ? L"DELETE" : \
  55. (v) == HttpVerbTRACE ? L"TRACE" : \
  56. (v) == HttpVerbCONNECT ? L"CONNECT" : \
  57. (v) == HttpVerbTRACK ? L"TRACK" : \
  58. (v) == HttpVerbMOVE ? L"MOVE" : \
  59. (v) == HttpVerbCOPY ? L"COPY" : \
  60. (v) == HttpVerbPROPFIND ? L"PROPFIND" : \
  61. (v) == HttpVerbPROPPATCH ? L"PROPPATCH" : \
  62. (v) == HttpVerbMKCOL ? L"MKCOL" : \
  63. (v) == HttpVerbLOCK ? L"LOCK" : \
  64. (v) == HttpVerbUNLOCK ? L"UNLOCK" : \
  65. (v) == HttpVerbSEARCH ? L"SEARCH" : \
  66. L"???" \
  67. )
  68. #define UL_SET_BITMASKS_FOR_LOG_FIELDS(table) \
  69. do { \
  70. \
  71. table[UlLogFieldDate].FieldMask = MD_EXTLOG_DATE; \
  72. table[UlLogFieldTime].FieldMask = MD_EXTLOG_TIME; \
  73. table[UlLogFieldClientIp].FieldMask = MD_EXTLOG_CLIENT_IP; \
  74. table[UlLogFieldUserName].FieldMask = MD_EXTLOG_USERNAME; \
  75. table[UlLogFieldSiteName].FieldMask = MD_EXTLOG_SITE_NAME; \
  76. table[UlLogFieldServerName].FieldMask = MD_EXTLOG_COMPUTER_NAME; \
  77. table[UlLogFieldServerIp].FieldMask = MD_EXTLOG_SERVER_IP; \
  78. table[UlLogFieldMethod].FieldMask = MD_EXTLOG_METHOD; \
  79. table[UlLogFieldUriStem].FieldMask = MD_EXTLOG_URI_STEM; \
  80. table[UlLogFieldUriQuery].FieldMask = MD_EXTLOG_URI_QUERY; \
  81. table[UlLogFieldProtocolStatus].FieldMask = MD_EXTLOG_HTTP_STATUS; \
  82. table[UlLogFieldWin32Status].FieldMask = MD_EXTLOG_WIN32_STATUS; \
  83. table[UlLogFieldBytesSent].FieldMask = MD_EXTLOG_BYTES_SENT; \
  84. table[UlLogFieldBytesReceived].FieldMask = MD_EXTLOG_BYTES_RECV; \
  85. table[UlLogFieldTimeTaken].FieldMask = MD_EXTLOG_TIME_TAKEN; \
  86. table[UlLogFieldServerPort].FieldMask = MD_EXTLOG_SERVER_PORT; \
  87. table[UlLogFieldUserAgent].FieldMask = MD_EXTLOG_USER_AGENT; \
  88. table[UlLogFieldCookie].FieldMask = MD_EXTLOG_COOKIE; \
  89. table[UlLogFieldReferrer].FieldMask = MD_EXTLOG_REFERER; \
  90. table[UlLogFieldProtocolVersion].FieldMask= MD_EXTLOG_PROTOCOL_VERSION; \
  91. table[UlLogFieldHost].FieldMask = MD_EXTLOG_HOST; \
  92. \
  93. } while(FALSE)
  94. #define UL_DEFAULT_NCSA_FIELDS (MD_EXTLOG_CLIENT_IP | \
  95. MD_EXTLOG_USERNAME | \
  96. MD_EXTLOG_DATE | \
  97. MD_EXTLOG_TIME | \
  98. MD_EXTLOG_METHOD | \
  99. MD_EXTLOG_URI_STEM | \
  100. MD_EXTLOG_URI_QUERY | \
  101. MD_EXTLOG_PROTOCOL_VERSION | \
  102. MD_EXTLOG_HTTP_STATUS | \
  103. MD_EXTLOG_BYTES_SENT)
  104. #define UL_DEFAULT_IIS_FIELDS (MD_EXTLOG_CLIENT_IP | \
  105. MD_EXTLOG_USERNAME | \
  106. MD_EXTLOG_DATE | \
  107. MD_EXTLOG_TIME | \
  108. MD_EXTLOG_SITE_NAME | \
  109. MD_EXTLOG_COMPUTER_NAME | \
  110. MD_EXTLOG_SERVER_IP | \
  111. MD_EXTLOG_TIME_TAKEN | \
  112. MD_EXTLOG_BYTES_RECV | \
  113. MD_EXTLOG_BYTES_SENT | \
  114. MD_EXTLOG_HTTP_STATUS | \
  115. MD_EXTLOG_WIN32_STATUS | \
  116. MD_EXTLOG_METHOD | \
  117. MD_EXTLOG_URI_STEM)
  118. #define UL_GET_LOG_TYPE_MASK(x,y) \
  119. ( (x) == HttpLoggingTypeW3C ? (y) : \
  120. (x) == HttpLoggingTypeIIS ? UL_DEFAULT_IIS_FIELDS : \
  121. (x) == HttpLoggingTypeNCSA ? UL_DEFAULT_NCSA_FIELDS : 0 \
  122. )
  123. //
  124. // The order of the following should match with
  125. // UL_LOG_FIELD_TYPE type definition.
  126. //
  127. PWSTR UlFieldTitleLookupTable[] =
  128. {
  129. L" date",
  130. L" time",
  131. L" s-sitename",
  132. L" s-computername",
  133. L" s-ip",
  134. L" cs-method",
  135. L" cs-uri-stem",
  136. L" cs-uri-query",
  137. L" sc-status",
  138. L" sc-win32-status",
  139. L" s-port",
  140. L" cs-username",
  141. L" c-ip",
  142. L" cs-version",
  143. L" cs(User-Agent)",
  144. L" cs(Cookie)",
  145. L" cs(Referer)",
  146. L" cs-host",
  147. L" sc-bytes",
  148. L" cs-bytes",
  149. L" time-taken"
  150. };
  151. #define UL_GET_LOG_FIELD_TITLE(x) \
  152. ((x)>=UlLogFieldMaximum ? L"Unknown" : UlFieldTitleLookupTable[(x)])
  153. #define UL_GET_LOG_TITLE_IF_PICKED(x,y,z) \
  154. ((y)&(z) ? UL_GET_LOG_FIELD_TITLE((x)) : L"")
  155. //
  156. // Maximum possible log file name length
  157. //
  158. // \u_extend12345678901234567890.log => 33 chars -> 66 bytes
  159. //
  160. // Generic Full Path File Name Length. Same as MAX_PATH
  161. // should be greater than above number.
  162. #define UL_MAX_FILE_NAME_SUFFIX_LENGTH (260)
  163. #define DEFAULT_LOG_FILE_EXTENSION L"log"
  164. #define DEFAULT_LOG_FILE_EXTENSION_PLUS_DOT L".log"
  165. #define SIZE_OF_GMT_OFFSET (6)
  166. #define UL_GET_NAME_FOR_HTTP_VERSION(v) \
  167. ( HTTP_EQUAL_VERSION((v), 0, 9) ? "HTTP/0.9" : \
  168. HTTP_EQUAL_VERSION((v), 1, 0) ? "HTTP/1.0" : \
  169. HTTP_EQUAL_VERSION((v), 1, 1) ? "HTTP/1.1" : \
  170. "HTTP/?.?" \
  171. )
  172. #define UL_HTTP_VERSION_LENGTH (8)
  173. #define IS_LOGGING_DISABLED(g) \
  174. ((g) == NULL || \
  175. (g)->LoggingConfig.Flags.Present == 0 || \
  176. (g)->LoggingConfig.LoggingEnabled == FALSE)
  177. //
  178. // Little utility to make life happier
  179. //
  180. const PSTR _Months[] =
  181. {
  182. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  183. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  184. };
  185. #define UL_GET_MONTH_AS_STR(m) \
  186. ( ((m)>=1) && ((m)<=12) ? _Months[(m)-1] : "Unk" )
  187. //
  188. // Following is used when storing logging data to UL Cache.
  189. //
  190. typedef struct _UL_CACHE_LOG_FIELD
  191. {
  192. UL_LOG_FIELD_TYPE Type; // Field Type
  193. ULONG Length; // Field length in Bytes
  194. PWSTR FieldValue; // The Log Field Itself
  195. } UL_CACHE_LOG_FIELD, *PUL_CACHE_LOG_FIELD;
  196. #define DEFAULT_MAX_LOG_BUFFER_SIZE (0x00010000)
  197. //
  198. // Cached Date header string.
  199. //
  200. #define ONE_SECOND (10000000)
  201. #define DATE_LOG_FIELD_LENGTH (15)
  202. #define TIME_LOG_FIELD_LENGTH (8)
  203. typedef struct _UL_LOG_DATE_AND_TIME_CACHE
  204. {
  205. CHAR Date[DATE_LOG_FIELD_LENGTH+1];
  206. ULONG DateLength;
  207. CHAR Time[TIME_LOG_FIELD_LENGTH+1];
  208. ULONG TimeLength;
  209. LARGE_INTEGER LastSystemTime;
  210. } UL_LOG_DATE_AND_TIME_CACHE, *PUL_LOG_DATE_AND_TIME_CACHE;
  211. //
  212. // Buffer flush out period in minutes.
  213. //
  214. #define DEFAULT_BUFFER_TIMER_PERIOD (1)
  215. //
  216. // The amount of buffer allocated for directory search query during
  217. // initialization. Pick this big enough to avoid too many querries
  218. // 4K provides enough size for 40 something filenames. Increase it
  219. // for faster startups with too many sites and/or too many log files
  220. //
  221. #define UL_DIRECTORY_SEARCH_BUFFER_SIZE (4*1024)
  222. //
  223. // UlpWriteW3CLogRecord attempts to use a buffer size upto this
  224. //
  225. #define UL_DEFAULT_WRITE_BUFFER_LEN (512)
  226. // For W3C log format, max overhead for the fix length fields
  227. // which will be generated per hit (non-cache) is as follows;
  228. // Date & Time : 20
  229. // PStatus : MAX_ULONG_STR + 1 (11)
  230. // Win32Status : MAX_ULONG_STR + 1
  231. // ServerPort : MAX_ULONG_STR + 1
  232. // PVersion : UL_HTTP_VERSION_LENGTH + 1
  233. // BSent : MAX_ULONGLONG_STR + 1 (21)
  234. // TTaken : MAX_ULONGLONG_STR + 1
  235. // BReceived : MAX_ULONGLONG_STR + 1
  236. // \r\n\0 : 3
  237. // TOTAL : 128
  238. #define MAX_W3C_FIX_FIELD_OVERHEAD (128)
  239. // For NCSA log format, max overhead for the fix length fields
  240. // which will be generated per cache hit is as follows;
  241. // Date & Time : NCSA_FIX_DATE_AND_TIME_FIELD_SIZE
  242. // Fixed dash : 2
  243. // ClientIp : MAX_IPV4_STRING_LENGTH + 1 (16)
  244. // UserName : 2
  245. // PStatus : MAX_ULONG_STR + 1 (11)
  246. // PVersion : UL_HTTP_VERSION_LENGTH + 1 + 1
  247. // BSent : MAX_ULONGLONG_STR + 1 (21)
  248. // \n\0 : 2
  249. // TOTAL : 93
  250. #define MAX_NCSA_CACHE_FIELD_OVERHEAD (96)
  251. // For IIS log format, max overhead for the fix length fields
  252. // which will be generated per cache hit is as follows;
  253. // Date & Time : 22
  254. // ClientIp : MAX_IPV4_STRING_LENGTH + 2 (17)
  255. // UserName : 3
  256. // PStatus : MAX_ULONG_STR + 2 (12)
  257. // PVersion : UL_HTTP_VERSION_LENGTH + 2
  258. // BSent : MAX_ULONGLONG_STR + 2 (22)
  259. // TTaken : MAX_ULONGLONG_STR + 2
  260. // BReceived : MAX_ULONGLONG_STR + 2
  261. // TOTAL : 124
  262. #define MAX_IIS_CACHE_FIELD_OVERHEAD (128)
  263. // For W3C log format see the inline function
  264. // UlpRecalcLogLineLengthW3C.
  265. //
  266. // Private function calls
  267. //
  268. NTSTATUS
  269. UlpConstructLogFileEntry(
  270. IN PHTTP_CONFIG_GROUP_LOGGING pConfig,
  271. OUT PUL_LOG_FILE_ENTRY * ppEntry,
  272. OUT PUNICODE_STRING pDirectoryName,
  273. IN PTIME_FIELDS pCurrentTimeFields
  274. );
  275. VOID
  276. UlpInsertLogFileEntry(
  277. PUL_LOG_FILE_ENTRY pEntry,
  278. PTIME_FIELDS pFields
  279. );
  280. ULONG
  281. UlpGetLogFileLength(
  282. IN HANDLE hFile
  283. );
  284. NTSTATUS
  285. UlpAppendW3CLogTitle(
  286. IN PUL_LOG_FILE_ENTRY pEntry,
  287. OUT PCHAR pDestBuffer,
  288. IN OUT PULONG pBytesCopied
  289. );
  290. NTSTATUS
  291. UlpCreateSafeDirectory(
  292. IN PUNICODE_STRING pDirectoryName
  293. );
  294. __inline
  295. ULONG
  296. UlpGetMonthDays(
  297. IN PTIME_FIELDS pDueTime
  298. )
  299. {
  300. ULONG NumDays = 31;
  301. if ( (4 == pDueTime->Month) || // April
  302. (6 == pDueTime->Month) || // June
  303. (9 == pDueTime->Month) || // September
  304. (11 == pDueTime->Month) // November
  305. )
  306. {
  307. NumDays = 30;
  308. }
  309. if (2 == pDueTime->Month) // February
  310. {
  311. if ((pDueTime->Year % 4 == 0 &&
  312. pDueTime->Year % 100 != 0) ||
  313. pDueTime->Year % 400 == 0 )
  314. {
  315. //
  316. // Leap year
  317. //
  318. NumDays = 29;
  319. }
  320. else
  321. {
  322. NumDays = 28;
  323. }
  324. }
  325. return NumDays;
  326. }
  327. NTSTATUS
  328. UlpCalculateTimeToExpire(
  329. PTIME_FIELDS pFields,
  330. HTTP_LOGGING_PERIOD LogPeriod,
  331. PULONG pTimeRemaining
  332. );
  333. VOID
  334. UlpInitializeTimers(
  335. VOID
  336. );
  337. VOID
  338. UlpTerminateTimers(
  339. VOID
  340. );
  341. VOID
  342. UlpSetLogTimer(
  343. IN PTIME_FIELDS pFields
  344. );
  345. VOID
  346. UlpSetBufferTimer(
  347. VOID
  348. );
  349. NTSTATUS
  350. UlpRecycleLogFile(
  351. IN PUL_LOG_FILE_ENTRY pEntry
  352. );
  353. __inline
  354. ULONG UlpWeekOfMonth(
  355. IN PTIME_FIELDS fields
  356. );
  357. VOID
  358. UlpConstructFileName(
  359. IN HTTP_LOGGING_PERIOD period,
  360. IN PCWSTR prefix,
  361. OUT PUNICODE_STRING filename,
  362. IN PTIME_FIELDS fields,
  363. IN OUT PULONG sequenceNu OPTIONAL
  364. );
  365. __inline
  366. BOOLEAN
  367. UlpIsLogFileOverFlow(
  368. IN PUL_LOG_FILE_ENTRY pEntry,
  369. IN ULONG ReqdBytes
  370. );
  371. __inline
  372. VOID
  373. UlpIncrementBytesWritten(
  374. IN PUL_LOG_FILE_ENTRY pEntry,
  375. IN ULONG BytesWritten
  376. );
  377. NTSTATUS
  378. UlpUpdateLogFlags(
  379. OUT PUL_LOG_FILE_ENTRY pEntry,
  380. IN PHTTP_CONFIG_GROUP_LOGGING pCfgOld,
  381. IN PHTTP_CONFIG_GROUP_LOGGING pCfgNew
  382. );
  383. NTSTATUS
  384. UlpUpdateLogTruncateSize(
  385. OUT PUL_LOG_FILE_ENTRY pEntry,
  386. IN PHTTP_CONFIG_GROUP_LOGGING pCfgOld,
  387. IN PHTTP_CONFIG_GROUP_LOGGING pCfgNew,
  388. OUT BOOLEAN * pHaveToReCycle
  389. );
  390. NTSTATUS
  391. UlpUpdatePeriod(
  392. OUT PUL_LOG_FILE_ENTRY pEntry,
  393. IN PHTTP_CONFIG_GROUP_LOGGING pCfgOld,
  394. IN PHTTP_CONFIG_GROUP_LOGGING pCfgNew
  395. );
  396. NTSTATUS
  397. UlpUpdateFormat(
  398. OUT PUL_LOG_FILE_ENTRY pEntry,
  399. IN PHTTP_CONFIG_GROUP_LOGGING pCfgOld,
  400. IN PHTTP_CONFIG_GROUP_LOGGING pCfgNew
  401. );
  402. NTSTATUS
  403. UlpGrowLogEntry(
  404. IN PUL_CONFIG_GROUP_OBJECT pConfigGroup,
  405. IN PUL_LOG_FILE_ENTRY pOldEntry
  406. );
  407. NTSTATUS
  408. UlpDebugCalculateTimeToExpire(
  409. PTIME_FIELDS pDueTime,
  410. HTTP_LOGGING_PERIOD LogPeriod,
  411. PULONG pTimeRemaining
  412. );
  413. VOID
  414. UlpGetGMTOffset();
  415. NTSTATUS
  416. UlpInitializeLogBufferGranularity();
  417. NTSTATUS
  418. UlpFlushLogFile(
  419. IN PUL_LOG_FILE_ENTRY pFile
  420. );
  421. VOID
  422. UlLogHttpCacheHitWorker(
  423. IN PUL_WORK_ITEM pWorkItem
  424. );
  425. NTSTATUS
  426. UlpWriteToLogFile(
  427. IN PUL_LOG_FILE_ENTRY pFile,
  428. IN ULONG RecordSize,
  429. IN PCHAR pRecord,
  430. IN ULONG UsedOffset1,
  431. IN ULONG UsedOffset2
  432. );
  433. NTSTATUS
  434. UlpWriteToLogFileShared(
  435. IN PUL_LOG_FILE_ENTRY pFile,
  436. IN ULONG RecordSize,
  437. IN PCHAR pRecord,
  438. IN ULONG UsedOffset1,
  439. IN ULONG UsedOffset2
  440. );
  441. NTSTATUS
  442. UlpWriteToLogFileExclusive(
  443. IN PUL_LOG_FILE_ENTRY pFile,
  444. IN ULONG RecordSize,
  445. IN PCHAR pRecord,
  446. IN ULONG UsedOffset1,
  447. IN ULONG UsedOffset2
  448. );
  449. NTSTATUS
  450. UlpWriteToLogFileDebug(
  451. IN PUL_LOG_FILE_ENTRY pFile,
  452. IN ULONG RecordSize,
  453. IN PCHAR pRecord,
  454. IN ULONG UsedOffset1,
  455. IN ULONG UsedOffset2
  456. );
  457. VOID
  458. UlpInitializeLogCache(
  459. VOID
  460. );
  461. VOID
  462. UlpGenerateDateAndTimeFields(
  463. IN HTTP_LOGGING_TYPE LogType,
  464. IN LARGE_INTEGER CurrentTime,
  465. OUT PCHAR pDate,
  466. OUT PULONG pDateLength,
  467. OUT PCHAR pTime,
  468. OUT PULONG pTimeLength
  469. );
  470. VOID
  471. UlpGetDateTimeFields(
  472. IN HTTP_LOGGING_TYPE LogType,
  473. OUT PCHAR pDate,
  474. OUT PULONG pDateLength,
  475. OUT PCHAR pTime,
  476. OUT PULONG pTimeLength
  477. );
  478. NTSTATUS
  479. UlpQueryDirectory(
  480. IN OUT PUL_LOG_FILE_ENTRY pEntry
  481. );
  482. VOID
  483. UlWaitForBufferIoToComplete(
  484. VOID
  485. );
  486. VOID
  487. UlpBufferFlushAPC(
  488. IN PVOID ApcContext,
  489. IN PIO_STATUS_BLOCK pIoStatusBlock,
  490. IN ULONG Reserved
  491. );
  492. VOID
  493. UlpLogCloseHandleWorker(
  494. IN PUL_WORK_ITEM pWorkItem
  495. );
  496. VOID
  497. UlpLogCloseHandle(
  498. IN PUL_LOG_FILE_ENTRY pEntry
  499. );
  500. __inline
  501. NTSTATUS
  502. FASTCALL
  503. UlpReallocLogLine(
  504. IN PUL_LOG_DATA_BUFFER pLogData,
  505. IN ULONG NewSize
  506. )
  507. {
  508. ULONG BytesNeeded = ALIGN_UP(NewSize, PVOID);
  509. ASSERT(NewSize > UL_LOG_LINE_BUFFER_SIZE);
  510. pLogData->Line =
  511. (PCHAR) UL_ALLOCATE_ARRAY(
  512. PagedPool,
  513. CHAR,
  514. BytesNeeded,
  515. UL_LOG_DATA_BUFFER_POOL_TAG
  516. );
  517. if (pLogData->Line == NULL)
  518. {
  519. pLogData->Length = 0;
  520. return STATUS_INSUFFICIENT_RESOURCES;
  521. }
  522. pLogData->Length = BytesNeeded;
  523. return STATUS_SUCCESS;
  524. }
  525. __inline
  526. ULONG
  527. FASTCALL
  528. UlpCalcLogLineLengthW3C(
  529. IN PHTTP_LOG_FIELDS_DATA pLogData,
  530. IN ULONG Flags,
  531. IN ULONG Utf8Multiplier
  532. )
  533. {
  534. ULONG Length = 0;
  535. // Now see precisely how much we may need:
  536. // Format specific maximum possible required length calculation for
  537. // the incoming log line. The numbers generated here are considerably
  538. // greater than the actual number. As we add maximum size for number
  539. // fields and Utf8 and Codepage conversions also double the amount
  540. // for UserName & URI Stem fields. Since we do not use temporary buffer
  541. // to hold fields until send completion, we have to make an early estimation
  542. // but we have to make sure it's safe as well.
  543. //
  544. Length = (ULONG)(
  545. ((Flags & MD_EXTLOG_DATE) ? 11 : 0) +
  546. ((Flags & MD_EXTLOG_TIME) ? 9 : 0) +
  547. ((Flags & MD_EXTLOG_CLIENT_IP) ? 2 + pLogData->ClientIpLength : 0) +
  548. ((Flags & MD_EXTLOG_USERNAME) ? 2 + pLogData->UserNameLength * Utf8Multiplier : 0) +
  549. ((Flags & MD_EXTLOG_SITE_NAME) ? 2 + pLogData->ServiceNameLength : 0) +
  550. ((Flags & MD_EXTLOG_COMPUTER_NAME) ? 2 + pLogData->ServerNameLength : 0) +
  551. ((Flags & MD_EXTLOG_SERVER_IP) ? 2 + pLogData->ServerIpLength : 0) +
  552. ((Flags & MD_EXTLOG_METHOD) ? 2 + pLogData->MethodLength : 0) +
  553. ((Flags & MD_EXTLOG_URI_STEM) ? 2 + pLogData->UriStemLength * Utf8Multiplier : 0) +
  554. ((Flags & MD_EXTLOG_URI_QUERY) ? 2 + pLogData->UriQueryLength : 0) +
  555. ((Flags & MD_EXTLOG_HTTP_STATUS) ? 2 + MAX_ULONG_STR : 0) + // ProtocolStatus
  556. ((Flags & MD_EXTLOG_WIN32_STATUS) ? 2 + MAX_ULONG_STR : 0) + // Win32 Status
  557. ((Flags & MD_EXTLOG_SERVER_PORT) ? 2 + MAX_ULONG_STR : 0) + // ServerPort
  558. ((Flags & MD_EXTLOG_PROTOCOL_VERSION) ? 2 + UL_HTTP_VERSION_LENGTH : 0) + // Version
  559. ((Flags & MD_EXTLOG_USER_AGENT) ? 2 + pLogData->UserAgentLength : 0) +
  560. ((Flags & MD_EXTLOG_COOKIE) ? 2 + pLogData->CookieLength : 0) +
  561. ((Flags & MD_EXTLOG_REFERER) ? 2 + pLogData->ReferrerLength : 0) +
  562. ((Flags & MD_EXTLOG_HOST) ? 2 + pLogData->HostLength : 0) +
  563. ((Flags & MD_EXTLOG_BYTES_SENT) ? 2 + MAX_ULONGLONG_STR : 0) + // BytesSent
  564. ((Flags & MD_EXTLOG_BYTES_RECV) ? 2 + MAX_ULONGLONG_STR : 0) + // BytesReceived
  565. ((Flags & MD_EXTLOG_TIME_TAKEN) ? 2 + MAX_ULONGLONG_STR : 0) + // TimeTaken
  566. (3) // \r\n\0
  567. )
  568. ;
  569. return Length;
  570. }
  571. __inline
  572. ULONG
  573. FASTCALL
  574. UlpRecalcLogLineLengthW3C(
  575. IN ULONG Flags,
  576. IN PUL_INTERNAL_REQUEST pRequest,
  577. IN ULONG LengthOfFieldsFrmCache
  578. )
  579. {
  580. ULONG NewLength = LengthOfFieldsFrmCache;
  581. ASSERT(UL_IS_VALID_INTERNAL_REQUEST(pRequest));
  582. // Max Overhead for the fix length fields which will be appended
  583. // post-cache-hit;
  584. // Date & Time : 11 + 9
  585. // UserName : 2
  586. // ClientIp : MAX_IPV4_STRING_LENGTH + 1 (16)
  587. // PStatus : MAX_ULONG_STR + 1 (11)
  588. // PVersion : UL_HTTP_VERSION_LENGTH + 1
  589. // BSent : MAX_ULONGLONG_STR + 1 (21)
  590. // TTaken : MAX_ULONGLONG_STR + 1
  591. // BReceived : MAX_ULONGLONG_STR + 1
  592. // \r\n\0 : 3
  593. // TOTAL : 124
  594. NewLength += 128;
  595. // And now add the variable length fields
  596. if ((Flags & MD_EXTLOG_USER_AGENT) &&
  597. pRequest->HeaderValid[HttpHeaderUserAgent])
  598. {
  599. ASSERT( pRequest->Headers[HttpHeaderUserAgent].HeaderLength ==
  600. strlen((const CHAR *)pRequest->Headers[HttpHeaderUserAgent].pHeader));
  601. NewLength += 2 + pRequest->Headers[HttpHeaderUserAgent].HeaderLength;
  602. }
  603. if ((Flags & MD_EXTLOG_COOKIE) &&
  604. pRequest->HeaderValid[HttpHeaderCookie])
  605. {
  606. ASSERT( pRequest->Headers[HttpHeaderCookie].HeaderLength ==
  607. strlen((const CHAR *)pRequest->Headers[HttpHeaderCookie].pHeader));
  608. NewLength += 2 + pRequest->Headers[HttpHeaderCookie].HeaderLength;
  609. }
  610. if ((Flags & MD_EXTLOG_REFERER) &&
  611. pRequest->HeaderValid[HttpHeaderReferer])
  612. {
  613. ASSERT( pRequest->Headers[HttpHeaderReferer].HeaderLength ==
  614. strlen((const CHAR *)pRequest->Headers[HttpHeaderReferer].pHeader));
  615. NewLength += 2 + pRequest->Headers[HttpHeaderReferer].HeaderLength;
  616. }
  617. if ((Flags & MD_EXTLOG_HOST) &&
  618. pRequest->HeaderValid[HttpHeaderHost])
  619. {
  620. ASSERT( pRequest->Headers[HttpHeaderHost].HeaderLength ==
  621. strlen((const CHAR *)pRequest->Headers[HttpHeaderHost].pHeader));
  622. NewLength += 2 + pRequest->Headers[HttpHeaderHost].HeaderLength;
  623. }
  624. return NewLength;
  625. }
  626. #ifdef __cplusplus
  627. }; // extern "C"
  628. #endif
  629. #endif // _ULLOGP_H_