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.

1235 lines
30 KiB

  1. /*++
  2. Copyright (c) 2000-2002 Microsoft Corporation
  3. Module Name:
  4. logutil.h
  5. Abstract:
  6. Various utilities for both raw & normal logging.
  7. Author:
  8. Ali E. Turkoglu (aliTu) 05-Oct-2001
  9. Revision History:
  10. ---
  11. --*/
  12. #ifndef _LOGUTIL_H_
  13. #define _LOGUTIL_H_
  14. //
  15. // Forwarders.
  16. //
  17. typedef struct _UL_INTERNAL_REQUEST *PUL_INTERNAL_REQUEST;
  18. typedef struct _UL_URI_CACHE_ENTRY *PUL_URI_CACHE_ENTRY;
  19. typedef struct _HTTP_RAWLOGID *PHTTP_RAWLOGID;
  20. ///////////////////////////////////////////////////////////////////////////////
  21. //
  22. // Definitions for the HTTP Logging Modules
  23. //
  24. ///////////////////////////////////////////////////////////////////////////////
  25. //
  26. // Some directory name related Macros.
  27. //
  28. #define UL_LOCAL_PATH_PREFIX (L"\\??\\")
  29. #define UL_LOCAL_PATH_PREFIX_LENGTH (WCSLEN_LIT(UL_LOCAL_PATH_PREFIX))
  30. #define UL_UNC_PATH_PREFIX (L"\\dosdevices\\UNC")
  31. #define UL_UNC_PATH_PREFIX_LENGTH (WCSLEN_LIT(UL_UNC_PATH_PREFIX))
  32. #define UL_SYSTEM_ROOT_PREFIX (L"\\SystemRoot")
  33. #define UL_SYSTEM_ROOT_PREFIX_LENGTH (WCSLEN_LIT(UL_SYSTEM_ROOT_PREFIX))
  34. #define UL_MAX_PATH_PREFIX_LENGTH (UL_UNC_PATH_PREFIX_LENGTH)
  35. __inline
  36. ULONG
  37. UlpGetDirNameOffset(
  38. IN PWSTR pFullName
  39. )
  40. {
  41. if (wcsncmp(pFullName,
  42. UL_LOCAL_PATH_PREFIX,
  43. UL_LOCAL_PATH_PREFIX_LENGTH
  44. ) == 0 )
  45. {
  46. return UL_LOCAL_PATH_PREFIX_LENGTH;
  47. }
  48. else
  49. if(wcsncmp(pFullName,
  50. UL_UNC_PATH_PREFIX,
  51. UL_UNC_PATH_PREFIX_LENGTH
  52. ) == 0 )
  53. {
  54. return UL_UNC_PATH_PREFIX_LENGTH;
  55. }
  56. else
  57. {
  58. //
  59. // Must be an error log file directory,
  60. // use the whole string.
  61. //
  62. return 0;
  63. }
  64. }
  65. __inline
  66. PWSTR
  67. UlpGetLastDirOrFile(
  68. IN PUNICODE_STRING pFullName
  69. )
  70. {
  71. PWCHAR pw;
  72. ASSERT(pFullName != NULL);
  73. ASSERT(pFullName->Length != 0);
  74. ASSERT(pFullName->Buffer != NULL);
  75. pw = &pFullName->Buffer[(pFullName->Length/sizeof(WCHAR)) - 1];
  76. while( *pw != UNICODE_NULL && *pw != L'\\' )
  77. {
  78. pw--;
  79. }
  80. ASSERT(*pw != UNICODE_NULL);
  81. return pw;
  82. }
  83. //
  84. // Maximum possible log file name length depends on the sequence number.
  85. // Only the size based recycling will produce filenames as long as this.
  86. // u_extend is the biggest one among ansi, binary and error logging file
  87. // names;
  88. //
  89. // i.e. "\u_extend1234567890.log"
  90. //
  91. #define UL_MAX_FILE_NAME_SUFFIX_LENGTH (32)
  92. #define UL_MAX_FILE_NAME_SUFFIX_SIZE \
  93. (UL_MAX_FILE_NAME_SUFFIX_LENGTH * sizeof(WCHAR))
  94. C_ASSERT(UL_MAX_FILE_NAME_SUFFIX_LENGTH > \
  95. ( \
  96. WCSLEN_LIT(L"\\u_extend") \
  97. + \
  98. MAX_ULONG_STR \
  99. + \
  100. WCSLEN_LIT(L".log") \
  101. ));
  102. //
  103. // Upper limit for the log file directory name will be enforced when WAS
  104. // does the logging configuration for the site. 212 has been picked to
  105. // give the maximum space to the directoy name w/o violating the MAX_PATH
  106. // after we add the prefix & suffix. Any number higher than this will cause
  107. // the compile time assert to raise.
  108. //
  109. #define UL_MAX_FULL_PATH_DIR_NAME_LENGTH (212)
  110. #define UL_MAX_FULL_PATH_DIR_NAME_SIZE (UL_MAX_FULL_PATH_DIR_NAME_LENGTH * sizeof(WCHAR))
  111. C_ASSERT(UL_MAX_FULL_PATH_DIR_NAME_LENGTH <=
  112. (MAX_PATH - UL_MAX_PATH_PREFIX_LENGTH - UL_MAX_FILE_NAME_SUFFIX_LENGTH));
  113. //
  114. // The amount of buffer allocated for directory search query during
  115. // initialization. Pick this big enough to avoid too many querries
  116. // 4K provides enough size for 40 something filenames. Increase it
  117. // for faster startups with too many sites and/or too many log files
  118. //
  119. #define UL_DIRECTORY_SEARCH_BUFFER_SIZE (4*1024)
  120. C_ASSERT(UL_DIRECTORY_SEARCH_BUFFER_SIZE >=
  121. (sizeof(FILE_DIRECTORY_INFORMATION) + UL_MAX_FILE_NAME_SUFFIX_SIZE + sizeof(WCHAR)));
  122. //
  123. // Some macros regarding log field limits.
  124. //
  125. #define MAX_LOG_EXTEND_FIELD_LEN (4096)
  126. //
  127. // Method field has its own field limitation.
  128. //
  129. #define MAX_LOG_METHOD_FIELD_LEN (100)
  130. //
  131. // UserName field has its own field limitation.
  132. //
  133. #define MAX_LOG_USERNAME_FIELD_LEN (256)
  134. //
  135. // Simple macros to check log format type validity
  136. //
  137. #define IS_VALID_ANSI_LOGGING_TYPE(lt) \
  138. ((lt) == HttpLoggingTypeW3C || \
  139. (lt) == HttpLoggingTypeIIS || \
  140. (lt) == HttpLoggingTypeNCSA )
  141. #define IS_VALID_BINARY_LOGGING_TYPE(lt) \
  142. ((lt) == HttpLoggingTypeRaw)
  143. #define IS_VALID_SELECTIVE_LOGGING_TYPE(lt) \
  144. ((lt) == HttpLogAllRequests || \
  145. (lt) == HttpLogSuccessfulRequests || \
  146. (lt) == HttpLogErrorRequests )
  147. #define IS_VALID_LOGGING_PERIOD(lp) \
  148. ((lp) < HttpLoggingPeriodMaximum)
  149. //
  150. // Even if LocalRollTimeRollover is set there will be one log
  151. // recycle timer which will be aligned properly for the beginning
  152. // of each hour, both for GMT and Local timezones.
  153. //
  154. typedef enum _UL_LOG_TIMER_PERIOD_TYPE
  155. {
  156. UlLogTimerPeriodNone = 0,
  157. UlLogTimerPeriodGMT,
  158. UlLogTimerPeriodLocal,
  159. UlLogTimerPeriodBoth, // When and where GMT & Local are the same
  160. UlLogTimerPeriodMaximum
  161. } UL_LOG_TIMER_PERIOD_TYPE, *PUL_LOG_TIMER_PERIOD_TYPE;
  162. //
  163. // For Log File ReCycling based on Local and/or GMT time.
  164. //
  165. typedef struct _UL_LOG_TIMER
  166. {
  167. //
  168. // Timer itself and the corresponding Dpc object.
  169. //
  170. KTIMER Timer;
  171. KDPC DpcObject;
  172. UL_SPIN_LOCK SpinLock;
  173. //
  174. // Initially a negative value i.e. -15, 15 minutes to first wakeup
  175. // once the first wakeup happens then it becomes positive i.e. 4,
  176. // that means 4 periods of "DEFAULT_LOG_TIMER_GRANULARITY" until
  177. // the next wakeup.
  178. //
  179. UL_LOG_TIMER_PERIOD_TYPE PeriodType;
  180. SHORT Period;
  181. //
  182. // Spinlock to protect the following state parameters
  183. //
  184. BOOLEAN Initialized;
  185. BOOLEAN Started;
  186. } UL_LOG_TIMER, *PUL_LOG_TIMER;
  187. //
  188. // Structure to hold a log file buffer
  189. //
  190. typedef struct _UL_LOG_FILE_BUFFER
  191. {
  192. //
  193. // PagedPool
  194. //
  195. //
  196. // This MUST be the first field in the structure. This is the linkage
  197. // used by the lookaside package for storing entries in the lookaside
  198. // list.
  199. //
  200. SLIST_ENTRY LookasideEntry;
  201. //
  202. // Signature is UL_LOG_FILE_BUFFER_POOL_TAG.
  203. //
  204. ULONG Signature;
  205. //
  206. // I/O status block for UlpBufferFlushAPC.
  207. //
  208. IO_STATUS_BLOCK IoStatusBlock;
  209. //
  210. // Bytes used in the allocated buffered space.
  211. //
  212. LONG BufferUsed;
  213. //
  214. // The real buffered space for log records.
  215. //
  216. PUCHAR Buffer;
  217. } UL_LOG_FILE_BUFFER, *PUL_LOG_FILE_BUFFER;
  218. #define IS_VALID_LOG_FILE_BUFFER( entry ) \
  219. HAS_VALID_SIGNATURE(entry, UL_LOG_FILE_BUFFER_POOL_TAG)
  220. //
  221. // Following structure is used for two reasons;
  222. // 1. To be able to close the handle on threadpool to avoid
  223. // attach/detach (to system process) bugchecks.
  224. // 2. To be able to do the defered log file creation. When a
  225. // a request comes in file entry will allocate a file handle
  226. // structure and create/open a file.
  227. //
  228. typedef struct _UL_LOG_FILE_HANDLE
  229. {
  230. //
  231. // Signature is UL_LOG_FILE_HANDLE_POOL_TAG.
  232. //
  233. ULONG Signature;
  234. //
  235. // To be able to close the file handle on threadpool.
  236. //
  237. UL_WORK_ITEM WorkItem;
  238. //
  239. // The open file handle. Note that this handle is only valid
  240. // in the context of the system process. Therefore we open it
  241. // with kernel flag set and we close it on our threadpool.
  242. //
  243. HANDLE hFile;
  244. } UL_LOG_FILE_HANDLE, *PUL_LOG_FILE_HANDLE;
  245. #define IS_VALID_LOG_FILE_HANDLE( entry ) \
  246. HAS_VALID_SIGNATURE(entry, UL_LOG_FILE_HANDLE_POOL_TAG)
  247. //
  248. // Temp Log buffer holds the captured data from user until logging
  249. // for the request is done. Both Binary & Normal logging uses this
  250. // structure. Sizes are in bytes.
  251. //
  252. #define UL_ANSI_LOG_LINE_BUFFER_SIZE (4096)
  253. #define UL_BINARY_LOG_LINE_BUFFER_SIZE (512)
  254. #define UL_ERROR_LOG_BUFFER_SIZE (768)
  255. typedef struct _UL_BINARY_LOG_DATA
  256. {
  257. //
  258. // If the field is captured, its respective pointer points to its
  259. // beginning in the external buffer. If field is cached, its id is
  260. // provided in the same log line buffer.
  261. //
  262. PUCHAR pUriStem;
  263. PHTTP_RAWLOGID pUriStemID;
  264. PUCHAR pUriQuery;
  265. PUCHAR pUserName;
  266. USHORT UriStemSize;
  267. USHORT UriQuerySize;
  268. USHORT UserNameSize;
  269. UCHAR Method;
  270. UCHAR Version;
  271. } UL_BINARY_LOG_DATA, *PUL_BINARY_LOG_DATA;
  272. typedef struct _UL_STR_LOG_DATA
  273. {
  274. //
  275. // Format & Flags for normal (ansi) logging.
  276. //
  277. HTTP_LOGGING_TYPE Format;
  278. ULONG Flags;
  279. //
  280. // This fields are used to track the format of the partially
  281. // stored log line in the below buffer.
  282. //
  283. USHORT Offset1;
  284. USHORT Offset2;
  285. USHORT Offset3;
  286. } UL_STR_LOG_DATA, *PUL_STR_LOG_DATA;
  287. typedef struct _UL_LOG_DATA_BUFFER
  288. {
  289. //
  290. // This MUST be the first field in the structure. This is the linkage
  291. // used by the lookaside package for storing entries in the lookaside
  292. // list.
  293. //
  294. SLIST_ENTRY LookasideEntry;
  295. //
  296. // Signature is UL_BINARY_LOG_DATA_BUFFER_POOL_TAG
  297. // or UL_ANSI_LOG_DATA_BUFFER_POOL_TAG.
  298. //
  299. ULONG Signature;
  300. //
  301. // A work item, used for queuing to a worker thread.
  302. //
  303. UL_WORK_ITEM WorkItem;
  304. //
  305. // Our private pointer to the Internal Request structure to ensure
  306. // the request will be around around until we are done. Upon send
  307. // completion we may need to read few fields from request.
  308. //
  309. PUL_INTERNAL_REQUEST pRequest;
  310. //
  311. // The total amount of send_response bytes.
  312. //
  313. ULONGLONG BytesTransferred;
  314. //
  315. // Status fields captured from user data. They can be overwritten
  316. // according to the send completion results.
  317. //
  318. ULONG Win32Status;
  319. USHORT ProtocolStatus;
  320. USHORT SubStatus;
  321. USHORT ServerPort;
  322. union
  323. {
  324. USHORT Value;
  325. struct
  326. {
  327. USHORT CacheAndSendResponse:1; // Do not restore back from cache
  328. USHORT Binary:1; // Logging type binary
  329. USHORT IsFromLookaside:1; // Destroy carefully
  330. };
  331. } Flags;
  332. //
  333. // Logging Type specific fields, either binary or normal logging.
  334. //
  335. union
  336. {
  337. UL_STR_LOG_DATA Str;
  338. UL_BINARY_LOG_DATA Binary;
  339. } Data;
  340. //
  341. // Length of the buffer. It gets allocated from a lookaside list and
  342. // could be 512 byte (Binary Log) or 4k (Normal Log) by default.
  343. // It is allocated at the end of this structure.
  344. //
  345. USHORT Used;
  346. USHORT Size;
  347. PUCHAR Line;
  348. } UL_LOG_DATA_BUFFER, *PUL_LOG_DATA_BUFFER;
  349. #define IS_VALID_LOG_DATA_BUFFER( entry ) \
  350. ( (entry != NULL) && \
  351. ((entry)->Signature == UL_BINARY_LOG_DATA_BUFFER_POOL_TAG) || \
  352. ((entry)->Signature == UL_ANSI_LOG_DATA_BUFFER_POOL_TAG))
  353. #define LOG_UPDATE_WIN32STATUS(pLogData,Status) \
  354. do { \
  355. if (STATUS_SUCCESS != (Status)) \
  356. { \
  357. ASSERT((pLogData) != NULL); \
  358. \
  359. (pLogData)->Win32Status = HttpNtStatusToWin32Status(Status); \
  360. } \
  361. } while (FALSE, FALSE)
  362. #define LOG_SET_WIN32STATUS(pLogData,Status) \
  363. if (pLogData) \
  364. { \
  365. (pLogData)->Win32Status = HttpNtStatusToWin32Status(Status); \
  366. } \
  367. else \
  368. { \
  369. ASSERT(!"Null LogData Pointer !"); \
  370. }
  371. //
  372. // 64K Default log file buffer.
  373. //
  374. #define DEFAULT_MAX_LOG_BUFFER_SIZE (0x00010000)
  375. //
  376. // Buffer flush out period in minutes.
  377. //
  378. #define DEFAULT_BUFFER_TIMER_PERIOD_MINUTES (1)
  379. //
  380. // Maximum allowed idle time for a log entry. After this time
  381. // its file will automatically be closed. In buffer periods.
  382. //
  383. #define DEFAULT_MAX_FILE_IDLE_TIME (15)
  384. //
  385. // Maximum allowed sequence number for an existing log file in the
  386. // log directory.
  387. //
  388. #define MAX_ALLOWED_SEQUENCE_NUMBER (0xFFFFFF)
  389. //
  390. // Ellipsis are used to show that a long event log message was truncated.
  391. // Ellipsis and its size (in bytes including UNICODE_NULL.)
  392. //
  393. #define UL_ELLIPSIS_WSTR L"..."
  394. #define UL_ELLIPSIS_SIZE (sizeof(UL_ELLIPSIS_WSTR))
  395. //
  396. // UlCopyHttpVersion doesn't convert version lengths
  397. // bigger than this.
  398. //
  399. #define UL_HTTP_VERSION_LENGTH (8)
  400. //
  401. // Cached Date header string.
  402. //
  403. #define DATE_LOG_FIELD_LENGTH (15)
  404. #define TIME_LOG_FIELD_LENGTH (8)
  405. typedef struct _UL_LOG_DATE_AND_TIME_CACHE
  406. {
  407. CHAR Date[DATE_LOG_FIELD_LENGTH+1];
  408. ULONG DateLength;
  409. CHAR Time[TIME_LOG_FIELD_LENGTH+1];
  410. ULONG TimeLength;
  411. LARGE_INTEGER LastSystemTime;
  412. } UL_LOG_DATE_AND_TIME_CACHE, *PUL_LOG_DATE_AND_TIME_CACHE;
  413. ///////////////////////////////////////////////////////////////////////////////
  414. //
  415. // Exported function calls
  416. //
  417. ///////////////////////////////////////////////////////////////////////////////
  418. NTSTATUS
  419. UlInitializeLogUtil(
  420. VOID
  421. );
  422. VOID
  423. UlTerminateLogUtil(
  424. VOID
  425. );
  426. NTSTATUS
  427. UlBuildLogDirectory(
  428. IN PUNICODE_STRING pSrcDirName,
  429. IN OUT PUNICODE_STRING pDstDirName
  430. );
  431. NTSTATUS
  432. UlRefreshFileName(
  433. IN PUNICODE_STRING pDirectory,
  434. OUT PUNICODE_STRING pFileName,
  435. OUT PWSTR *ppShortName
  436. );
  437. VOID
  438. UlConstructFileName(
  439. IN HTTP_LOGGING_PERIOD period,
  440. IN PCWSTR prefix,
  441. IN PCWSTR extension,
  442. OUT PUNICODE_STRING filename,
  443. IN PTIME_FIELDS fields,
  444. IN BOOLEAN Utf8Enabled,
  445. IN OUT PULONG sequenceNu // OPTIONAL
  446. );
  447. NTSTATUS
  448. UlCreateSafeDirectory(
  449. IN PUNICODE_STRING pDirectoryName,
  450. OUT PBOOLEAN pUncShare,
  451. OUT PBOOLEAN pACLSupport
  452. );
  453. NTSTATUS
  454. UlFlushLogFileBuffer(
  455. IN OUT PUL_LOG_FILE_BUFFER *ppLogBuffer,
  456. IN PUL_LOG_FILE_HANDLE pLogFile,
  457. IN BOOLEAN WaitForComplete,
  458. OUT PULONGLONG pTotalWritten
  459. );
  460. VOID
  461. UlpWaitForIoCompletion(
  462. VOID
  463. );
  464. VOID
  465. UlpCloseLogFileWorker(
  466. IN PUL_WORK_ITEM pWorkItem
  467. );
  468. VOID
  469. UlCloseLogFile(
  470. IN OUT PUL_LOG_FILE_HANDLE *ppLogFile
  471. );
  472. NTSTATUS
  473. UlQueryDirectory(
  474. IN OUT PUNICODE_STRING pFileName,
  475. IN OUT PWSTR pShortName,
  476. IN PCWSTR Prefix,
  477. IN PCWSTR ExtensionPlusDot,
  478. OUT PULONG pSequenceNumber,
  479. OUT PULONGLONG pTotalWritten
  480. );
  481. ULONGLONG
  482. UlGetLogFileLength(
  483. IN HANDLE hFile
  484. );
  485. /***************************************************************************++
  486. Routine Description:
  487. UlGetMonthDays :
  488. Shamelessly stolen from IIS 5.1 Logging code and adapted here.
  489. Arguments:
  490. PTIME_FIELDS - Current Time Fields
  491. Return Value:
  492. ULONG - Number of days in the month.
  493. --***************************************************************************/
  494. __inline
  495. ULONG
  496. UlGetMonthDays(
  497. IN PTIME_FIELDS pDueTime
  498. )
  499. {
  500. ULONG NumDays = 31;
  501. if ( (4 == pDueTime->Month) || // April
  502. (6 == pDueTime->Month) || // June
  503. (9 == pDueTime->Month) || // September
  504. (11 == pDueTime->Month) // November
  505. )
  506. {
  507. NumDays = 30;
  508. }
  509. if (2 == pDueTime->Month) // February
  510. {
  511. if ((pDueTime->Year % 4 == 0 &&
  512. pDueTime->Year % 100 != 0) ||
  513. pDueTime->Year % 400 == 0 )
  514. {
  515. //
  516. // Leap year
  517. //
  518. NumDays = 29;
  519. }
  520. else
  521. {
  522. NumDays = 28;
  523. }
  524. }
  525. return NumDays;
  526. }
  527. VOID
  528. UlSetLogTimer(
  529. IN PUL_LOG_TIMER pTimer
  530. );
  531. VOID
  532. UlSetBufferTimer(
  533. IN PUL_LOG_TIMER pTimer
  534. );
  535. NTSTATUS
  536. UlCalculateTimeToExpire(
  537. PTIME_FIELDS pDueTime,
  538. HTTP_LOGGING_PERIOD LogPeriod,
  539. PULONG pTimeRemaining
  540. );
  541. __inline
  542. PUL_LOG_DATA_BUFFER
  543. UlReallocLogDataBuffer(
  544. IN ULONG LogLineSize,
  545. IN BOOLEAN IsBinary
  546. )
  547. {
  548. PUL_LOG_DATA_BUFFER pLogDataBuffer = NULL;
  549. ULONG Tag = UL_ANSI_LOG_DATA_BUFFER_POOL_TAG;
  550. USHORT BytesNeeded = (USHORT) ALIGN_UP(LogLineSize, PVOID);
  551. //
  552. // It should be bigger than the default size for each buffer
  553. // logging type.
  554. //
  555. if (IsBinary)
  556. {
  557. Tag = UL_BINARY_LOG_DATA_BUFFER_POOL_TAG;
  558. ASSERT(LogLineSize > UL_BINARY_LOG_LINE_BUFFER_SIZE);
  559. }
  560. else
  561. {
  562. ASSERT(LogLineSize > UL_ANSI_LOG_LINE_BUFFER_SIZE);
  563. }
  564. pLogDataBuffer =
  565. UL_ALLOCATE_STRUCT_WITH_SPACE(
  566. PagedPool,
  567. UL_LOG_DATA_BUFFER,
  568. BytesNeeded,
  569. Tag
  570. );
  571. if (pLogDataBuffer)
  572. {
  573. pLogDataBuffer->Signature = Tag;
  574. pLogDataBuffer->Used = 0;
  575. pLogDataBuffer->Size = BytesNeeded;
  576. pLogDataBuffer->Line = (PUCHAR) (pLogDataBuffer + 1);
  577. pLogDataBuffer->Flags.Value = 0;
  578. pLogDataBuffer->Flags.IsFromLookaside = 0;
  579. if (IsBinary)
  580. {
  581. pLogDataBuffer->Flags.Binary = 1;
  582. }
  583. UlInitializeWorkItem(&pLogDataBuffer->WorkItem);
  584. }
  585. return pLogDataBuffer;
  586. }
  587. VOID
  588. UlDestroyLogDataBufferWorker(
  589. IN PUL_WORK_ITEM pWorkItem
  590. );
  591. /***************************************************************************++
  592. Routine Description:
  593. Wrapper function to ensure we are not touching to paged-pool allocated
  594. large log buffer on elevated IRQL. It's important that this function has
  595. been written with the assumption of Request doesn't go away until we
  596. properly execute the possible passive worker. This is indeed the case
  597. because request(with the embedded logdata) has been refcounted up by the
  598. logdata.
  599. Arguments:
  600. pLogData - The buffer to be destroyed
  601. --***************************************************************************/
  602. __inline
  603. VOID
  604. UlDestroyLogDataBuffer(
  605. IN PUL_LOG_DATA_BUFFER pLogData
  606. )
  607. {
  608. //
  609. // Sanity check
  610. //
  611. ASSERT(pLogData);
  612. //
  613. // If we are running on elevated IRQL and large log line allocated
  614. // then queue a passive worker otherwise complete inline.
  615. //
  616. if (!pLogData->Flags.IsFromLookaside)
  617. {
  618. UL_CALL_PASSIVE( &pLogData->WorkItem,
  619. &UlDestroyLogDataBufferWorker );
  620. }
  621. else
  622. {
  623. UlDestroyLogDataBufferWorker( &pLogData->WorkItem );
  624. }
  625. }
  626. VOID
  627. UlProbeLogData(
  628. IN PHTTP_LOG_FIELDS_DATA pLogData,
  629. IN KPROCESSOR_MODE RequestorMode
  630. );
  631. __inline
  632. NTSTATUS
  633. UlCopyLogFileDir(
  634. IN OUT PUNICODE_STRING pOldDir,
  635. IN PUNICODE_STRING pNewDir
  636. )
  637. {
  638. PWSTR pNewBuffer = NULL;
  639. ASSERT(pOldDir);
  640. ASSERT(pNewDir);
  641. pNewBuffer =
  642. (PWSTR) UL_ALLOCATE_ARRAY(
  643. PagedPool,
  644. UCHAR,
  645. pNewDir->MaximumLength,
  646. UL_CG_LOGDIR_POOL_TAG
  647. );
  648. if(pNewBuffer == NULL)
  649. {
  650. return STATUS_NO_MEMORY;
  651. }
  652. if (pOldDir->Buffer != NULL)
  653. {
  654. UL_FREE_POOL(pOldDir->Buffer,UL_CG_LOGDIR_POOL_TAG);
  655. }
  656. pOldDir->Buffer = pNewBuffer;
  657. RtlCopyMemory(
  658. pOldDir->Buffer,
  659. pNewDir->Buffer,
  660. pNewDir->MaximumLength
  661. );
  662. pOldDir->Length = pNewDir->Length;
  663. pOldDir->MaximumLength = pNewDir->MaximumLength;
  664. return STATUS_SUCCESS;
  665. }
  666. NTSTATUS
  667. UlCheckLogDirectory(
  668. IN PUNICODE_STRING pDirName
  669. );
  670. NTSTATUS
  671. UlpCheckLogDirectory(
  672. IN PVOID pContext
  673. );
  674. BOOLEAN
  675. UlUpdateLogTruncateSize(
  676. IN ULONG NewTruncateSize,
  677. IN OUT PULONG pCurrentTruncateSize,
  678. IN OUT PULONG pEntryTruncateSize,
  679. IN ULARGE_INTEGER EntryTotalWritten
  680. );
  681. ULONG
  682. UlpInitializeLogBufferGranularity();
  683. #define HTTP_MAX_EVENT_LOG_DATA_SIZE \
  684. ((ERROR_LOG_MAXIMUM_SIZE - sizeof(IO_ERROR_LOG_PACKET) + sizeof(ULONG)) & ~3)
  685. NTSTATUS
  686. UlWriteEventLogEntry(
  687. IN NTSTATUS EventCode,
  688. IN ULONG UniqueEventValue,
  689. IN USHORT NumStrings,
  690. IN PWSTR * pStringArray OPTIONAL,
  691. IN ULONG DataSize,
  692. IN PVOID Data OPTIONAL
  693. );
  694. //
  695. // Sanity check. An event log entry must be able to hold the ellipsis string
  696. // and NTSTATUS error code. UlEventLogOneString() depends on this condition.
  697. //
  698. C_ASSERT(HTTP_MAX_EVENT_LOG_DATA_SIZE >= UL_ELLIPSIS_SIZE + sizeof(NTSTATUS));
  699. NTSTATUS
  700. UlEventLogOneStringEntry(
  701. IN NTSTATUS EventCode,
  702. IN PWSTR pMessage,
  703. IN BOOLEAN WriteErrorCode,
  704. IN NTSTATUS ErrorCode OPTIONAL
  705. );
  706. //
  707. // Following structure is used for distinguishing the event log entry
  708. // based on the type of logging issuing the create failure.
  709. //
  710. typedef enum _UL_LOG_EVENT_LOG_TYPE
  711. {
  712. UlEventLogNormal,
  713. UlEventLogBinary,
  714. UlEventLogError,
  715. UlEventLogMaximum
  716. } UL_LOG_EVENT_LOG_TYPE, *PUL_LOG_EVENT_LOG_TYPE;
  717. NTSTATUS
  718. UlEventLogCreateFailure(
  719. IN NTSTATUS Failure,
  720. IN UL_LOG_EVENT_LOG_TYPE LoggingType,
  721. IN PUNICODE_STRING pFullName,
  722. IN ULONG SiteId
  723. );
  724. NTSTATUS
  725. UlBuildSecurityToLogFile(
  726. OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
  727. IN PSID pSid
  728. );
  729. NTSTATUS
  730. UlQueryLogFileSecurity(
  731. IN HANDLE hFile,
  732. IN BOOLEAN UncShare,
  733. IN BOOLEAN Opened
  734. );
  735. //
  736. // Normally when the log file is created by http.sys the owner
  737. // will be the admin alias "SeAliasAdminsSid". However when the
  738. // log files is created on a UNC share following macro will fail
  739. // even though it is created by http.sys on a different machine
  740. // in that case the owner will be DOMAIN\ServerName.
  741. //
  742. #define IS_VALID_OWNER(Owner) \
  743. (RtlEqualSid((Owner), \
  744. SeExports->SeLocalSystemSid \
  745. ) || \
  746. RtlEqualSid((Owner), \
  747. SeExports->SeAliasAdminsSid \
  748. ))
  749. //
  750. // Used for queueing buffer flushes. Passed into
  751. // to the worker below as a context.
  752. //
  753. typedef struct _LOG_IO_FLUSH_OBJ
  754. {
  755. PUL_LOG_FILE_HANDLE pLogFile;
  756. PUL_LOG_FILE_BUFFER pLogBuffer;
  757. } LOG_IO_FLUSH_OBJ, *PLOG_IO_FLUSH_OBJ;
  758. NTSTATUS
  759. UlpFlushLogFileBufferWorker(
  760. IN PVOID pContext
  761. );
  762. //
  763. // Types and API for queueing logging I/O for
  764. // passive execution under threadpool.
  765. //
  766. typedef
  767. NTSTATUS
  768. (*PUL_LOG_IO_ROUTINE)(
  769. IN PVOID pContext
  770. );
  771. typedef struct _LOG_IO_SYNC_OBJ
  772. {
  773. //
  774. // Pointer to log file entry or directory name
  775. //
  776. PVOID pContext;
  777. //
  778. // Handler for the above context.
  779. //
  780. PUL_LOG_IO_ROUTINE pHandler;
  781. //
  782. // For queueing to the high priority.
  783. //
  784. UL_WORK_ITEM WorkItem;
  785. //
  786. // Used for wait until handler is done.
  787. //
  788. KEVENT Event;
  789. //
  790. // Result of the handler's work.
  791. //
  792. NTSTATUS Status;
  793. } LOG_IO_SYNC_OBJ, *PLOG_IO_SYNC_OBJ;
  794. NTSTATUS
  795. UlQueueLoggingRoutine(
  796. IN PVOID pContext,
  797. IN PUL_LOG_IO_ROUTINE pHandler
  798. );
  799. VOID
  800. UlpQueueLoggingRoutineWorker(
  801. IN PUL_WORK_ITEM pWorkItem
  802. );
  803. VOID
  804. UlpInitializeLogCache(
  805. VOID
  806. );
  807. VOID
  808. UlpGenerateDateAndTimeFields(
  809. IN HTTP_LOGGING_TYPE LogType,
  810. IN LARGE_INTEGER CurrentTime,
  811. OUT PCHAR pDate,
  812. OUT PULONG pDateLength,
  813. OUT PCHAR pTime,
  814. OUT PULONG pTimeLength
  815. );
  816. VOID
  817. UlGetDateTimeFields(
  818. IN HTTP_LOGGING_TYPE LogType,
  819. OUT PCHAR pDate,
  820. OUT PULONG pDateLength,
  821. OUT PCHAR pTime,
  822. OUT PULONG pTimeLength
  823. );
  824. /***************************************************************************++
  825. Routine Description:
  826. For a given HTTP_VERSION this function will build a version string in
  827. the provided log data buffer, at exactly UL_HTTP_VERSION_LENGTH.
  828. Arguments:
  829. psz: Pointer to log data buffer. Enough space is assumed to be allocated.
  830. version: To be converted to string.
  831. chSeparator
  832. Returns:
  833. the pointer to the log data buffer after the separator.
  834. --***************************************************************************/
  835. __inline
  836. PCHAR
  837. UlCopyHttpVersion(
  838. IN OUT PCHAR psz,
  839. IN HTTP_VERSION version,
  840. IN CHAR chSeparator
  841. )
  842. {
  843. //
  844. // Do the fast lookup first
  845. //
  846. if (HTTP_EQUAL_VERSION(version, 1, 1))
  847. {
  848. psz = UlStrPrintStr(psz, "HTTP/1.1", chSeparator);
  849. }
  850. else if (HTTP_EQUAL_VERSION(version, 1, 0))
  851. {
  852. psz = UlStrPrintStr(psz, "HTTP/1.0", chSeparator);
  853. }
  854. else if (HTTP_EQUAL_VERSION(version, 0, 9))
  855. {
  856. psz = UlStrPrintStr(psz, "HTTP/0.9", chSeparator);
  857. }
  858. else
  859. {
  860. //
  861. // Otherwise string convert but do not exceed the deafult size of
  862. // UL_HTTP_VERSION_LENGTH.
  863. //
  864. if (version.MajorVersion < 10 &&
  865. version.MinorVersion < 10)
  866. {
  867. psz = UlStrPrintStr(
  868. psz,
  869. "HTTP/",
  870. (CHAR) (version.MajorVersion + '0')
  871. );
  872. *psz++ = '.';
  873. *psz++ = (CHAR) (version.MinorVersion + '0');
  874. *psz++ = chSeparator;
  875. }
  876. else
  877. {
  878. psz = UlStrPrintStr(psz, "HTTP/?.?", chSeparator);
  879. }
  880. }
  881. return psz;
  882. }
  883. #if DBG
  884. NTSTATUS
  885. UlValidateLogFileOwner(
  886. IN HANDLE hFile
  887. );
  888. __inline
  889. VOID
  890. UlpTraceOwnerDetails(
  891. PSID Owner,
  892. BOOLEAN OwnerDefaulted
  893. )
  894. {
  895. NTSTATUS Status;
  896. UNICODE_STRING OwnerSID;
  897. ASSERT(RtlValidSid(Owner));
  898. Status =
  899. RtlConvertSidToUnicodeString(
  900. &OwnerSID,
  901. Owner,
  902. TRUE
  903. );
  904. if (NT_SUCCESS(Status))
  905. {
  906. UlTrace2Either(BINARY_LOGGING, LOGGING,
  907. ("Http!UlpTraceOwnerDetails: "
  908. "handle owned by <%s> OwnerDefaulted <%s>\n"
  909. "SID -> <%S>\n\n",
  910. RtlEqualSid(
  911. Owner,
  912. SeExports->SeLocalSystemSid) ? "System" :
  913. RtlEqualSid(
  914. Owner,
  915. SeExports->SeAliasAdminsSid) ? "Admin" : "Other",
  916. OwnerDefaulted == TRUE ? "Yes" : "No",
  917. OwnerSID.Buffer
  918. ));
  919. RtlFreeUnicodeString(&OwnerSID);
  920. }
  921. }
  922. #define TRACE_LOG_FILE_OWNER(Owner,OwnerDefaulted) \
  923. IF_DEBUG2EITHER(LOGGING,BINARY_LOGGING) \
  924. { \
  925. UlpTraceOwnerDetails((Owner),(OwnerDefaulted)); \
  926. }
  927. #else
  928. #define TRACE_LOG_FILE_OWNER(Owner,OwnerDefaulted) NOP_FUNCTION
  929. #endif // DBG
  930. USHORT
  931. UlComputeCachedLogDataLength(
  932. IN PUL_LOG_DATA_BUFFER pLogData
  933. );
  934. VOID
  935. UlCopyCachedLogData(
  936. IN PUL_LOG_DATA_BUFFER pLogData,
  937. IN USHORT LogDataLength,
  938. IN PUL_URI_CACHE_ENTRY pEntry
  939. );
  940. NTSTATUS
  941. UlQueryAttributeInfo(
  942. IN HANDLE hFile,
  943. OUT PBOOLEAN pSupportsPersistentACL
  944. );
  945. NTSTATUS
  946. UlCreateLogFile(
  947. IN PUNICODE_STRING pFileName,
  948. IN BOOLEAN UncShare,
  949. IN BOOLEAN ACLSupport,
  950. OUT PHANDLE pFileHandle
  951. );
  952. BOOLEAN
  953. UlIsValidLogDirectory(
  954. IN PUNICODE_STRING pDir,
  955. IN BOOLEAN UncSupported,
  956. IN BOOLEAN SystemRootSupported
  957. );
  958. NTSTATUS
  959. UlCheckLoggingConfig(
  960. IN PHTTP_CONTROL_CHANNEL_BINARY_LOGGING pBinaryConfig,
  961. IN PHTTP_CONFIG_GROUP_LOGGING pAnsiConfig
  962. );
  963. #endif // _LOGUTIL_H_