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.

1211 lines
34 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. elflpc.c
  5. Abstract:
  6. This file contains the routines that deal with the LPC port in the
  7. eventlog service.
  8. Author:
  9. Rajen Shah (rajens) 10-Jul-1991
  10. Revision History:
  11. --*/
  12. //
  13. // INCLUDES
  14. //
  15. #include <eventp.h>
  16. #include <ntiolog.h> // For IO_ERROR_LOG_[MESSAGE/PACKET]
  17. #include <ntiologc.h> // QUOTA error codes
  18. #include <elfkrnl.h>
  19. #include <stdlib.h>
  20. #include <memory.h>
  21. #include <elfextrn.h> // Computername
  22. #include <nt.h> // DbgPrint prototype
  23. #include <ntrtl.h> // DbgPrint prototype
  24. #include <ntdef.h>
  25. #include <ntstatus.h>
  26. #include <nt.h>
  27. #include <ntrtl.h>
  28. #include <nturtl.h>
  29. #include <windef.h>
  30. #include <lmcons.h>
  31. #include <string.h>
  32. #include <lmerr.h>
  33. #include <elfmsg.h>
  34. //
  35. // Global value for the "system" module
  36. //
  37. PLOGMODULE SystemModule = NULL;
  38. NTSTATUS
  39. SetUpLPCPort(
  40. VOID
  41. )
  42. /*++
  43. Routine Description:
  44. This routine sets up the LPC port for the service.
  45. Arguments:
  46. None
  47. Return Value:
  48. --*/
  49. {
  50. NTSTATUS status;
  51. UNICODE_STRING SystemString;
  52. UNICODE_STRING unicodePortName;
  53. OBJECT_ATTRIBUTES objectAttributes;
  54. PORT_MESSAGE connectionRequest;
  55. ELF_LOG0(LPC,
  56. "SetUpLPCPort: Enter\n");
  57. //
  58. // We're going to need this every time, so just get it once
  59. //
  60. ASSERT(SystemModule == NULL);
  61. //
  62. // Get the system module to log driver events
  63. //
  64. RtlInitUnicodeString(&SystemString, ELF_SYSTEM_MODULE_NAME);
  65. SystemModule = GetModuleStruc(&SystemString);
  66. //
  67. // The System log and its default module should have been created by now.
  68. //
  69. ASSERT(_wcsicmp(SystemModule->ModuleName, ELF_SYSTEM_MODULE_NAME) == 0);
  70. //
  71. // Initialize the handles to zero so that we can determine what to do
  72. // if we need to clean up.
  73. //
  74. ElfConnectionPortHandle = NULL;
  75. ElfCommunicationPortHandle = NULL;
  76. //
  77. // Create the LPC port.
  78. //
  79. RtlInitUnicodeString( &unicodePortName, ELF_PORT_NAME_U );
  80. InitializeObjectAttributes(
  81. &objectAttributes,
  82. &unicodePortName,
  83. OBJ_CASE_INSENSITIVE,
  84. NULL,
  85. NULL
  86. );
  87. status = NtCreatePort(&ElfConnectionPortHandle,
  88. &objectAttributes,
  89. 0,
  90. ELF_PORT_MAX_MESSAGE_LENGTH,
  91. ELF_PORT_MAX_MESSAGE_LENGTH * 32);
  92. if (!NT_SUCCESS(status))
  93. {
  94. ELF_LOG2(ERROR,
  95. "SetUpLPCPort: Error creating LPC port %ws %#x\n",
  96. ELF_PORT_NAME_U,
  97. status);
  98. }
  99. ELF_LOG1(LPC,
  100. "SetUpLPCPort: Exiting with status %#x\n",
  101. status);
  102. return status;
  103. }
  104. LPWSTR
  105. ElfpCopyString(
  106. LPWSTR Destination,
  107. LPWSTR Source,
  108. ULONG Length
  109. )
  110. /*++
  111. Routine Description:
  112. Copies a string to the destination. Correctly NUL terminates
  113. the string.
  114. Arguments:
  115. Destination - place where string is to be copied
  116. Source - string that may or may not be NUL terminated
  117. Length - length in bytes of string being copied. May include NUL
  118. Return Value:
  119. LPWSTR to first WCHAR past NUL
  120. --*/
  121. {
  122. //
  123. // Copy the data
  124. //
  125. RtlMoveMemory(Destination, Source, Length);
  126. //
  127. // Make sure it's NULL terminated
  128. //
  129. if (Length != 0)
  130. {
  131. Destination += Length / sizeof(WCHAR) - 1;
  132. if (*Destination != L'\0')
  133. {
  134. Destination++;
  135. *Destination = L'\0';
  136. }
  137. }
  138. else
  139. {
  140. *Destination = L'0';
  141. }
  142. return Destination + 1;
  143. }
  144. NTSTATUS
  145. ElfProcessIoLPCPacket(
  146. ULONG PacketLength,
  147. PIO_ERROR_LOG_MESSAGE pIoErrorLogMessage
  148. )
  149. /*++
  150. Routine Description:
  151. This routine takes the packet received from the LPC port and processes it.
  152. The logfile will be system, the module name will be the driver that
  153. generated the packet, the SID will always be NULL and
  154. there will always be one string, which will be the device name.
  155. It extracts the information from the LPC packet, and then calls the
  156. common routine to do the work of formatting the data into
  157. an event record and writing it out to the log file.
  158. Arguments:
  159. pIoErrorLogMessage - Pointer to the data portion of the packet just
  160. received through the LPC port.
  161. Return Value:
  162. Status of this operation.
  163. --*/
  164. {
  165. NTSTATUS status;
  166. ELF_REQUEST_RECORD Request;
  167. WRITE_PKT WritePkt;
  168. ULONG RecordLength;
  169. PEVENTLOGRECORD EventLogRecord;
  170. LPWSTR DestinationString, SourceString;
  171. PBYTE BinaryData;
  172. ULONG PadSize;
  173. LARGE_INTEGER Time;
  174. ULONG TimeWritten;
  175. PULONG pEndLength;
  176. ULONG i = 0;
  177. PWCHAR pwch;
  178. PWCHAR pwStart;
  179. PWCHAR pwEnd;
  180. ULONG StringLength;
  181. WCHAR LocalComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  182. ULONG ComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
  183. BOOL bOK;
  184. PacketLength = min(pIoErrorLogMessage->Size, PacketLength);
  185. try
  186. {
  187. // Get the computer name
  188. bOK = GetComputerNameW(LocalComputerName, &ComputerNameLength);
  189. if(bOK == FALSE)
  190. {
  191. ELF_LOG1(ERROR,
  192. "ElfProcessIoLPCPacket: failed calling GetComputerNameW, last error 0x%x\n",
  193. GetLastError());
  194. return STATUS_UNSUCCESSFUL;
  195. }
  196. ComputerNameLength = (ComputerNameLength+1)*sizeof(WCHAR); // account for the NULL
  197. //
  198. // Validate the packet, First make sure there are the correct
  199. // number of NULL terminated strings, and remember the
  200. // total number of bytes to copy
  201. //
  202. pwStart = pwch = (PWCHAR) ((PBYTE) pIoErrorLogMessage +
  203. pIoErrorLogMessage->EntryData.StringOffset);
  204. pwEnd = (PWCHAR) ((PBYTE) pIoErrorLogMessage + PacketLength);
  205. while (pwch < pwEnd
  206. &&
  207. i < pIoErrorLogMessage->EntryData.NumberOfStrings)
  208. {
  209. if (*pwch == L'\0')
  210. {
  211. i++;
  212. }
  213. pwch++;
  214. }
  215. StringLength = (ULONG) (pwch - pwStart) * sizeof(WCHAR);
  216. //
  217. // Now make sure everything in the packet is true
  218. //
  219. if ((i != pIoErrorLogMessage->EntryData.NumberOfStrings)
  220. ||
  221. (pIoErrorLogMessage->DriverNameOffset
  222. + pIoErrorLogMessage->DriverNameLength >= PacketLength)
  223. ||
  224. (pIoErrorLogMessage->EntryData.StringOffset >= PacketLength)
  225. ||
  226. (FIELD_OFFSET(IO_ERROR_LOG_MESSAGE, EntryData)
  227. + FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  228. + (ULONG) pIoErrorLogMessage->EntryData.DumpDataSize >= PacketLength))
  229. {
  230. //
  231. // It's a bad packet, log it and return
  232. //
  233. ELF_LOG0(ERROR,
  234. "ElfProcessIoLPCPacket: Bad LPC packet -- dumping it to System log\n");
  235. ElfpCreateElfEvent(EVENT_BadDriverPacket,
  236. EVENTLOG_ERROR_TYPE,
  237. 0, // EventCategory
  238. 0, // NumberOfStrings
  239. NULL, // Strings
  240. pIoErrorLogMessage, // Data
  241. PacketLength, // Datalength
  242. 0, // flags
  243. FALSE); // for security file
  244. return STATUS_UNSUCCESSFUL;
  245. }
  246. }
  247. except (EXCEPTION_EXECUTE_HANDLER)
  248. {
  249. //
  250. // It's a bad packet, log it and return
  251. //
  252. ELF_LOG1(ERROR,
  253. "ElfProcessIoLPCPacket: Exception %#x caught processing I/O LPC packet\n",
  254. GetExceptionCode());
  255. ElfpCreateElfEvent(EVENT_BadDriverPacket,
  256. EVENTLOG_ERROR_TYPE,
  257. 0, // EventCategory
  258. 0, // NumberOfStrings
  259. NULL, // Strings
  260. NULL, // Data
  261. 0, // Datalength
  262. 0, // flags
  263. FALSE); // for security file
  264. return STATUS_UNSUCCESSFUL;
  265. }
  266. //
  267. // The packet should be an IO_ERROR_LOG_MESSAGE
  268. //
  269. ASSERT(pIoErrorLogMessage->Type == IO_TYPE_ERROR_MESSAGE);
  270. //
  271. // Set up write packet in request packet
  272. //
  273. Request.Pkt.WritePkt = &WritePkt;
  274. Request.Flags = 0;
  275. //
  276. // Generate any additional information needed in the record.
  277. //
  278. //
  279. // TIMEWRITTEN
  280. // We need to generate a time when the log is written. This
  281. // gets written in the log so that we can use it to test the
  282. // retention period when wrapping the file.
  283. //
  284. NtQuerySystemTime(&Time);
  285. RtlTimeToSecondsSince1970(
  286. &Time,
  287. &TimeWritten
  288. );
  289. //
  290. // Determine how big a buffer is needed for the eventlog record.
  291. //
  292. RecordLength = sizeof(EVENTLOGRECORD)
  293. + ComputerNameLength // computer name
  294. + 2 * sizeof(WCHAR) // terminating NULLs
  295. + PacketLength
  296. - FIELD_OFFSET(IO_ERROR_LOG_MESSAGE, EntryData)
  297. + sizeof(RecordLength); // final len
  298. //
  299. // Determine how many pad bytes are needed to align to a DWORD
  300. // boundary.
  301. //
  302. PadSize = sizeof(ULONG) - (RecordLength % sizeof(ULONG));
  303. RecordLength += PadSize; // True size needed
  304. //
  305. // Allocate the buffer for the Eventlog record
  306. //
  307. EventLogRecord = (PEVENTLOGRECORD) ElfpAllocateBuffer(RecordLength);
  308. if (EventLogRecord != (PEVENTLOGRECORD) NULL)
  309. {
  310. //
  311. // Fill up the event record
  312. //
  313. EventLogRecord->Length = RecordLength;
  314. RtlTimeToSecondsSince1970(&pIoErrorLogMessage->TimeStamp,
  315. &EventLogRecord->TimeGenerated);
  316. EventLogRecord->Reserved = ELF_LOG_FILE_SIGNATURE;
  317. EventLogRecord->TimeWritten = TimeWritten;
  318. EventLogRecord->EventID = pIoErrorLogMessage->EntryData.ErrorCode;
  319. //
  320. // Set EventType based on the high order nibble of
  321. // pIoErrorLogMessage->EntryData.ErrorCode
  322. //
  323. if (NT_INFORMATION(pIoErrorLogMessage->EntryData.ErrorCode))
  324. {
  325. EventLogRecord->EventType = EVENTLOG_INFORMATION_TYPE;
  326. }
  327. else if (NT_WARNING(pIoErrorLogMessage->EntryData.ErrorCode))
  328. {
  329. EventLogRecord->EventType = EVENTLOG_WARNING_TYPE;
  330. }
  331. else if (NT_ERROR(pIoErrorLogMessage->EntryData.ErrorCode))
  332. {
  333. EventLogRecord->EventType = EVENTLOG_ERROR_TYPE;
  334. }
  335. else
  336. {
  337. //
  338. // Unknown, set to error
  339. //
  340. ELF_LOG1(LPC,
  341. "ElfProcessIoLPCPacket: Unknown EventType (high nibble of ID %#x)\n",
  342. EventLogRecord->EventID);
  343. EventLogRecord->EventType = EVENTLOG_ERROR_TYPE;
  344. }
  345. EventLogRecord->NumStrings = pIoErrorLogMessage->EntryData.NumberOfStrings;
  346. EventLogRecord->EventCategory = pIoErrorLogMessage->EntryData.EventCategory;
  347. EventLogRecord->StringOffset = sizeof(EVENTLOGRECORD)
  348. + pIoErrorLogMessage->DriverNameLength
  349. + ComputerNameLength;
  350. EventLogRecord->DataLength = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  351. + pIoErrorLogMessage->EntryData.DumpDataSize;
  352. EventLogRecord->DataOffset = EventLogRecord->StringOffset + StringLength;
  353. //
  354. // Quota events contain a SID.
  355. //
  356. if (pIoErrorLogMessage->EntryData.ErrorCode == IO_FILE_QUOTA_LIMIT
  357. ||
  358. pIoErrorLogMessage->EntryData.ErrorCode == IO_FILE_QUOTA_THRESHOLD)
  359. {
  360. PFILE_QUOTA_INFORMATION pFileQuotaInformation =
  361. (PFILE_QUOTA_INFORMATION) pIoErrorLogMessage->EntryData.DumpData;
  362. ELF_LOG0(LPC,
  363. "ElfProcessIoLPCPacket: Event is a Quota event\n");
  364. EventLogRecord->UserSidLength = pFileQuotaInformation->SidLength;
  365. EventLogRecord->UserSidOffset = EventLogRecord->DataOffset
  366. + FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  367. + FIELD_OFFSET(FILE_QUOTA_INFORMATION, Sid);
  368. EventLogRecord->DataLength = EventLogRecord->UserSidOffset -
  369. EventLogRecord->DataOffset;
  370. }
  371. else
  372. {
  373. EventLogRecord->UserSidLength = 0;
  374. EventLogRecord->UserSidOffset = 0;
  375. }
  376. //
  377. // Fill in the variable-length fields
  378. //
  379. //
  380. // MODULENAME
  381. //
  382. // Use the driver name as the module name, since its location is
  383. // described by an offset from the start of the IO_ERROR_LOG_MESSAGE
  384. // turn it into a pointer
  385. //
  386. DestinationString = (LPWSTR) ((LPBYTE) EventLogRecord + sizeof(EVENTLOGRECORD));
  387. SourceString = (LPWSTR) ((LPBYTE) pIoErrorLogMessage
  388. + pIoErrorLogMessage->DriverNameOffset);
  389. DestinationString = ElfpCopyString(DestinationString,
  390. SourceString,
  391. pIoErrorLogMessage->DriverNameLength);
  392. //
  393. // COMPUTERNAME
  394. //
  395. DestinationString = ElfpCopyString(DestinationString,
  396. LocalComputerName,
  397. ComputerNameLength);
  398. //
  399. // STRINGS
  400. //
  401. DestinationString = ElfpCopyString(DestinationString, pwStart, StringLength);
  402. //
  403. // BINARY DATA
  404. //
  405. BinaryData = (LPBYTE) DestinationString;
  406. RtlMoveMemory(BinaryData,
  407. &pIoErrorLogMessage->EntryData,
  408. FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  409. + pIoErrorLogMessage->EntryData.DumpDataSize);
  410. //
  411. // LENGTH at end of record
  412. //
  413. pEndLength = (PULONG) ((LPBYTE) EventLogRecord + RecordLength - sizeof(ULONG));
  414. *pEndLength = RecordLength;
  415. //
  416. // Set up request packet.
  417. // Link event log record into the request structure.
  418. //
  419. Request.Module = SystemModule;
  420. Request.LogFile = Request.Module->LogFile;
  421. Request.Command = ELF_COMMAND_WRITE;
  422. Request.Pkt.WritePkt->Buffer = (PVOID) EventLogRecord;
  423. Request.Pkt.WritePkt->Datasize = RecordLength;
  424. //
  425. // Perform the operation
  426. //
  427. ElfPerformRequest( &Request );
  428. //
  429. // Replicate the event if part of a cluster
  430. //
  431. ElfpSaveEventBuffer(SystemModule, EventLogRecord, RecordLength);
  432. status = Request.Status; // Set status of WRITE
  433. }
  434. else
  435. {
  436. ELF_LOG0(ERROR,
  437. "ElfProcessIoLPCPacket: Unable to allocate memory for EventLogRecord\n");
  438. status = STATUS_NO_MEMORY;
  439. }
  440. return status;
  441. }
  442. NTSTATUS
  443. ElfProcessSmLPCPacket(
  444. ULONG PacketLength,
  445. PSM_ERROR_LOG_MESSAGE SmErrorLogMessage
  446. )
  447. /*++
  448. Routine Description:
  449. This routine takes the packet received from the LPC port and processes it.
  450. The packet is an SM_ERROR_LOG_MESSAGE. The logfile will be system, the
  451. module name will be SMSS, the SID will always be NULL and
  452. there will always be one string, which will be the filename
  453. It extracts the information from the LPC packet, and then calls the
  454. common routine to do the work of formatting the data into
  455. an event record and writing it out to the log file.
  456. Arguments:
  457. SmErrorLogMessage - Pointer to the data portion of the packet just
  458. received through the LPC port.
  459. Return Value:
  460. Status of this operation.
  461. --*/
  462. {
  463. NTSTATUS status;
  464. ELF_REQUEST_RECORD Request;
  465. WRITE_PKT WritePkt;
  466. ULONG RecordLength;
  467. PEVENTLOGRECORD EventLogRecord;
  468. LPWSTR DestinationString, SourceString;
  469. PBYTE BinaryData;
  470. ULONG PadSize;
  471. LARGE_INTEGER Time;
  472. ULONG TimeWritten;
  473. PULONG pEndLength;
  474. WCHAR LocalComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  475. ULONG ComputerNameLength = MAX_COMPUTERNAME_LENGTH + 1;
  476. BOOL bOK;
  477. try
  478. {
  479. // Get the computer name
  480. bOK = GetComputerNameW(LocalComputerName, &ComputerNameLength);
  481. if(bOK == FALSE)
  482. {
  483. ELF_LOG1(ERROR,
  484. "ElfProcessIoLPCPacket: failed calling GetComputerNameW, last error 0x%x\n",
  485. GetLastError());
  486. return STATUS_UNSUCCESSFUL;
  487. }
  488. ComputerNameLength = (ComputerNameLength+1)*sizeof(WCHAR);
  489. //
  490. // Validate the packet.
  491. //
  492. if (PacketLength < sizeof(SM_ERROR_LOG_MESSAGE)
  493. ||
  494. //
  495. // Offset begins before header
  496. //
  497. SmErrorLogMessage->StringOffset < sizeof(*SmErrorLogMessage)
  498. ||
  499. //
  500. // Offset begins after packet
  501. //
  502. SmErrorLogMessage->StringOffset >= PacketLength
  503. ||
  504. //
  505. // Length of string longer than packet
  506. //
  507. SmErrorLogMessage->StringLength > PacketLength
  508. ||
  509. //
  510. // String end after end of packet
  511. //
  512. SmErrorLogMessage->StringOffset
  513. + SmErrorLogMessage->StringLength > PacketLength
  514. )
  515. {
  516. RtlRaiseStatus(STATUS_UNSUCCESSFUL);
  517. }
  518. }
  519. except (EXCEPTION_EXECUTE_HANDLER)
  520. {
  521. //
  522. // It's a bad packet, log it and return
  523. //
  524. ELF_LOG1(ERROR,
  525. "ElfProcessSmLPCPacket: Exception %#x caught processing SMSS LPC packet\n",
  526. GetExceptionCode());
  527. ELF_LOG3(ERROR,
  528. "SmErrorLogMessage->StringOffset %#x\n"
  529. "\tPacketLength %#x\n"
  530. "\tSmErrorLogMessage->StringLength %#x\n",
  531. SmErrorLogMessage->StringOffset,
  532. PacketLength,
  533. SmErrorLogMessage->StringLength);
  534. ElfpCreateElfEvent(EVENT_BadDriverPacket,
  535. EVENTLOG_ERROR_TYPE,
  536. 0, // EventCategory
  537. 0, // NumberOfStrings
  538. NULL, // Strings
  539. NULL, // Data
  540. 0, // Datalength
  541. 0, // flags
  542. FALSE); // for security file
  543. return STATUS_UNSUCCESSFUL;
  544. }
  545. //
  546. // Set up write packet in request packet
  547. //
  548. Request.Pkt.WritePkt = &WritePkt;
  549. Request.Flags = 0;
  550. //
  551. // Generate any additional information needed in the record.
  552. //
  553. //
  554. // Determine how big a buffer is needed for the eventlog record.
  555. // We overestimate string lengths rather than probing for
  556. // terminating NUL's
  557. //
  558. RecordLength = sizeof(EVENTLOGRECORD)
  559. + sizeof(L"system")
  560. + ComputerNameLength + sizeof(WCHAR)
  561. + SmErrorLogMessage->StringLength + sizeof(WCHAR)
  562. + sizeof(RecordLength);
  563. //
  564. // Since the RecordLength at the end must be ULONG aligned, we round
  565. // up the total size to be ULONG aligned.
  566. //
  567. RecordLength += sizeof(ULONG) - (RecordLength % sizeof(ULONG));
  568. //
  569. // Allocate the buffer for the Eventlog record
  570. //
  571. EventLogRecord = (PEVENTLOGRECORD) ElfpAllocateBuffer(RecordLength);
  572. if (EventLogRecord == NULL)
  573. {
  574. ELF_LOG0(ERROR,
  575. "ElfProcessSmLPCPacket: Unable to allocate memory for EventLogRecord\n");
  576. return STATUS_NO_MEMORY;
  577. }
  578. //
  579. // Fill up the event record
  580. //
  581. EventLogRecord->Length = RecordLength;
  582. EventLogRecord->Reserved = ELF_LOG_FILE_SIGNATURE;
  583. RtlTimeToSecondsSince1970(&SmErrorLogMessage->TimeStamp,
  584. &EventLogRecord->TimeGenerated);
  585. NtQuerySystemTime(&Time);
  586. RtlTimeToSecondsSince1970(&Time, &EventLogRecord->TimeWritten);
  587. EventLogRecord->EventID = SmErrorLogMessage->Status;
  588. //
  589. // set EventType based on the high order nibble of
  590. // the eventID
  591. //
  592. if (NT_INFORMATION(EventLogRecord->EventID))
  593. {
  594. EventLogRecord->EventType = EVENTLOG_INFORMATION_TYPE;
  595. }
  596. else if (NT_WARNING(EventLogRecord->EventID))
  597. {
  598. EventLogRecord->EventType = EVENTLOG_WARNING_TYPE;
  599. }
  600. else if (NT_ERROR(EventLogRecord->EventID))
  601. {
  602. EventLogRecord->EventType = EVENTLOG_ERROR_TYPE;
  603. }
  604. else
  605. {
  606. //
  607. // Unknown, set to error
  608. //
  609. ELF_LOG1(LPC,
  610. "ElfProcessSmLPCPacket: Unknown EventType (high nibble of ID %#x)\n",
  611. EventLogRecord->EventID);
  612. EventLogRecord->EventType = EVENTLOG_ERROR_TYPE;
  613. }
  614. //
  615. // There is a single string; it is the name of the file being
  616. // replaced
  617. //
  618. EventLogRecord->NumStrings = 1;
  619. EventLogRecord->EventCategory = ELF_CATEGORY_SYSTEM_EVENT;
  620. //
  621. // Nothing for ReservedFlags
  622. // Nothing for ClosingRecordNumber
  623. //
  624. EventLogRecord->StringOffset = sizeof(EVENTLOGRECORD)
  625. + sizeof( L"system" )
  626. + ComputerNameLength;
  627. //
  628. // No SID's present
  629. //
  630. EventLogRecord->UserSidLength = 0;
  631. EventLogRecord->UserSidOffset = 0;
  632. EventLogRecord->DataLength = 0;
  633. EventLogRecord->DataOffset = 0;
  634. //
  635. // Fill in the variable-length fields
  636. //
  637. // MODULENAME
  638. //
  639. // SMSS
  640. //
  641. DestinationString = (LPWSTR) ((LPBYTE) EventLogRecord + sizeof(EVENTLOGRECORD));
  642. DestinationString = ElfpCopyString(DestinationString,
  643. L"system",
  644. sizeof(L"system"));
  645. //
  646. // COMPUTERNAME
  647. //
  648. DestinationString = ElfpCopyString(DestinationString,
  649. LocalComputerName,
  650. ComputerNameLength);
  651. //
  652. // STRING
  653. //
  654. SourceString = (LPWSTR) ((LPBYTE) SmErrorLogMessage + SmErrorLogMessage->StringOffset);
  655. ELF_LOG2(LPC,
  656. "ElfProcessSmLPCPacket: String is '%*ws'\n",
  657. SmErrorLogMessage->StringLength,
  658. SourceString);
  659. DestinationString = ElfpCopyString(DestinationString,
  660. SourceString,
  661. SmErrorLogMessage->StringLength);
  662. //
  663. // LENGTH at end of record
  664. //
  665. pEndLength = (PULONG) ((LPBYTE) EventLogRecord + RecordLength - sizeof(ULONG));
  666. *pEndLength = RecordLength;
  667. //
  668. // Set up request packet.
  669. // Link event log record into the request structure.
  670. //
  671. Request.Module = SystemModule;
  672. Request.LogFile = Request.Module->LogFile;
  673. Request.Command = ELF_COMMAND_WRITE;
  674. Request.Pkt.WritePkt->Buffer = (PVOID) EventLogRecord;
  675. Request.Pkt.WritePkt->Datasize = RecordLength;
  676. //
  677. // Perform the operation
  678. //
  679. ElfPerformRequest( &Request );
  680. //
  681. // Replicate the event if part of a cluster
  682. //
  683. ElfpSaveEventBuffer(SystemModule, EventLogRecord, RecordLength);
  684. return Request.Status;
  685. }
  686. void
  687. LeaveLPCThread(VOID)
  688. {
  689. ELF_LOG0(TRACE, "Elf: LPC thread got a terminate message\n");
  690. ExitThread(0);
  691. }
  692. NTSTATUS
  693. ElfProcessLPCCalls(
  694. VOID
  695. )
  696. /*++
  697. Routine Description:
  698. This routine waits for messages to come through the LPC port to
  699. the system thread. When one does, it calls the appropriate routine to
  700. handle the API, then replies to the system thread indicating that the
  701. call has completed if the message was a request, if it was a datagram,
  702. it just waits for the next message.
  703. Arguments:
  704. Return Value:
  705. --*/
  706. {
  707. NTSTATUS status;
  708. BOOL SendReply = FALSE;
  709. ELF_REPLY_MESSAGE replyMessage;
  710. PELF_PORT_MSG receiveMessage;
  711. PHANDLE PortConnectionHandle;
  712. //
  713. // Loop dispatching API requests.
  714. //
  715. receiveMessage = ElfpAllocateBuffer(ELF_PORT_MAX_MESSAGE_LENGTH + sizeof(PORT_MESSAGE));
  716. if (!receiveMessage)
  717. {
  718. ELF_LOG0(ERROR,
  719. "ElfProcessLPCCalls: Unable to allocate memory for receiveMessage\n");
  720. return STATUS_NO_MEMORY;
  721. }
  722. while (TRUE)
  723. {
  724. //
  725. // On the first call to NtReplyWaitReceivePort, don't send a
  726. // reply since there's nobody to whom to reply. However, on
  727. // subsequent calls send a reply to the message from the prior
  728. // time if that message wasn't an LPC_DATAGRAM.
  729. //
  730. status = NtReplyWaitReceivePort(
  731. ElfConnectionPortHandle,
  732. (PVOID) &PortConnectionHandle,
  733. (PPORT_MESSAGE) (SendReply ? &replyMessage : NULL),
  734. (PPORT_MESSAGE) receiveMessage
  735. );
  736. if (!NT_SUCCESS(status))
  737. {
  738. ELF_LOG1(ERROR,
  739. "ElfProcessLPCCalls: NtReplyWaitReceivePort failed %#x\n",
  740. status);
  741. return status;
  742. }
  743. ELF_LOG0(LPC,
  744. "ElfProcessLPCCalls: Received message\n");
  745. if (EventlogShutdown)
  746. LeaveLPCThread();
  747. //
  748. // Take the record received and perform the operation. Strip off
  749. // the PortMessage and just send the packet.
  750. //
  751. //
  752. // Set up the response message to be sent on the next call to
  753. // NtReplyWaitReceivePort if this wasn't a datagram.
  754. // 'status' contains the status to return from this call.
  755. // Only process messages that are LPC_REQUEST or LPC_DATAGRAM
  756. //
  757. if (receiveMessage->PortMessage.u2.s2.Type == LPC_REQUEST
  758. ||
  759. receiveMessage->PortMessage.u2.s2.Type == LPC_DATAGRAM)
  760. {
  761. ELF_LOG1(LPC,
  762. "ElfProcessLPCCalls: LPC message type = %ws\n",
  763. (receiveMessage->PortMessage.u2.s2.Type == LPC_REQUEST ? "LPC_REQUEST" :
  764. "LPC_DATAGRAM"));
  765. if (receiveMessage->MessageType == IO_ERROR_LOG)
  766. {
  767. ELF_LOG0(LPC,
  768. "ElfProcessLPCCalls: SM_IO_LOG\n");
  769. status = ElfProcessIoLPCPacket(receiveMessage->PortMessage.u1.s1.DataLength,
  770. &receiveMessage->u.IoErrorLogMessage);
  771. }
  772. else if (receiveMessage->MessageType == SM_ERROR_LOG)
  773. {
  774. ELF_LOG0(LPC,
  775. "ElfProcessLPCCalls: SM_ERROR_LOG\n");
  776. status = ElfProcessSmLPCPacket(receiveMessage->PortMessage.u1.s1.DataLength,
  777. &receiveMessage->u.SmErrorLogMessage);
  778. }
  779. else
  780. {
  781. ELF_LOG1(ERROR,
  782. "ElfProcessLPCCalls: Unknown MessageType %#x\n",
  783. receiveMessage->MessageType);
  784. status = STATUS_UNSUCCESSFUL;
  785. }
  786. if (receiveMessage->PortMessage.u2.s2.Type == LPC_REQUEST)
  787. {
  788. replyMessage.PortMessage.u1.s1.DataLength = sizeof(replyMessage)
  789. - sizeof(PORT_MESSAGE);
  790. replyMessage.PortMessage.u1.s1.TotalLength = sizeof(replyMessage);
  791. replyMessage.PortMessage.u2.ZeroInit = 0;
  792. replyMessage.PortMessage.ClientId
  793. = receiveMessage->PortMessage.ClientId;
  794. replyMessage.PortMessage.MessageId
  795. = receiveMessage->PortMessage.MessageId;
  796. replyMessage.Status = status;
  797. SendReply = TRUE;
  798. }
  799. else
  800. {
  801. SendReply = FALSE;
  802. }
  803. }
  804. else if (receiveMessage->PortMessage.u2.s2.Type == LPC_CONNECTION_REQUEST)
  805. {
  806. PHANDLE pSavedHandle = NULL;
  807. BOOLEAN Accept = TRUE;
  808. ELF_LOG0(LPC,
  809. "ElfProcessLPCCalls: Processing connection request\n");
  810. pSavedHandle = ElfpAllocateBuffer(sizeof (HANDLE));
  811. if (pSavedHandle)
  812. {
  813. status = NtAcceptConnectPort(pSavedHandle,
  814. pSavedHandle,
  815. &receiveMessage->PortMessage,
  816. Accept,
  817. NULL,
  818. NULL);
  819. } else {
  820. ELF_LOG0(ERROR, "ElfProcessLPCCalls: Unable to allocate LPC handle\n");
  821. status = STATUS_NO_MEMORY;
  822. }
  823. if (!Accept)
  824. {
  825. if(pSavedHandle)
  826. {
  827. ElfpFreeBuffer(pSavedHandle);
  828. pSavedHandle = NULL;
  829. }
  830. continue;
  831. }
  832. if (NT_SUCCESS(status))
  833. {
  834. status = NtCompleteConnectPort(*pSavedHandle);
  835. if (!NT_SUCCESS(status))
  836. {
  837. ELF_LOG1(ERROR,
  838. "ElfProcessLPCCalls: NtAcceptConnectPort failed %#x\n",
  839. status);
  840. NtClose(*pSavedHandle);
  841. }
  842. }
  843. if (!NT_SUCCESS(status))
  844. {
  845. ELF_LOG1(ERROR,
  846. "ElfProcessLPCCalls: Cleaning up failed connect\n", status);
  847. if(pSavedHandle)
  848. {
  849. ElfpFreeBuffer(pSavedHandle);
  850. pSavedHandle = NULL;
  851. }
  852. }
  853. }
  854. else if (receiveMessage->PortMessage.u2.s2.Type == LPC_PORT_CLOSED)
  855. {
  856. ELF_LOG0(LPC,
  857. "ElfProcessLPCCalls: Processing port closed\n");
  858. ASSERT(PortConnectionHandle != NULL);
  859. NtClose(*PortConnectionHandle);
  860. ElfpFreeBuffer(PortConnectionHandle);
  861. }
  862. else
  863. {
  864. //
  865. // We received a message type we didn't expect, probably due to
  866. // error.
  867. //
  868. ELF_LOG1(ERROR,
  869. "ElfProcessLPCCalls: Unknown message type %#x received on LPC port\n",
  870. receiveMessage->PortMessage.u2.s2.Type);
  871. }
  872. }
  873. } // ElfProcessLPCCalls
  874. DWORD
  875. MainLPCThread(
  876. LPVOID LPCThreadParm
  877. )
  878. /*++
  879. Routine Description:
  880. This is the main thread that monitors the LPC port from the I/O system.
  881. It takes care of creating the LPC port, and waiting for input, which
  882. it then transforms into the right operation on the event log.
  883. Arguments:
  884. NONE
  885. Return Value:
  886. NONE
  887. --*/
  888. {
  889. NTSTATUS Status;
  890. ELF_LOG0(LPC,
  891. "MainLPCThread: Inside LPC thread\n");
  892. Status = SetUpLPCPort();
  893. if (NT_SUCCESS(Status))
  894. {
  895. //
  896. // Loop forever. This thread will be killed when the service terminates.
  897. //
  898. while (TRUE)
  899. {
  900. Status = ElfProcessLPCCalls ();
  901. }
  902. }
  903. ELF_LOG1(ERROR,
  904. "MainLPCThread: SetUpLPCPort failed %#x\n",
  905. Status);
  906. return Status;
  907. UNREFERENCED_PARAMETER(LPCThreadParm);
  908. }
  909. BOOL
  910. StartLPCThread(
  911. VOID
  912. )
  913. /*++
  914. Routine Description:
  915. This routine starts up the thread that monitors the LPC port.
  916. Arguments:
  917. NONE
  918. Return Value:
  919. TRUE if thread creation succeeded, FALSE otherwise.
  920. Note:
  921. --*/
  922. {
  923. DWORD error;
  924. DWORD ThreadId;
  925. ELF_LOG0(LPC,
  926. "StartLPCThread: Start up the LPC thread\n");
  927. //
  928. // Start up the actual thread.
  929. //
  930. LPCThreadHandle = CreateThread(NULL, // lpThreadAttributes
  931. 0, // dwStackSize
  932. MainLPCThread, // lpStartAddress
  933. NULL, // lpParameter
  934. 0L, // dwCreationFlags
  935. &ThreadId); // lpThreadId
  936. if (LPCThreadHandle == NULL)
  937. {
  938. error = GetLastError();
  939. ELF_LOG1(ERROR,
  940. "MainLPCThread: CreateThread failed %d\n",
  941. error);
  942. return FALSE;
  943. }
  944. return TRUE;
  945. }