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.

5073 lines
143 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. ELFAPI.C
  5. Abstract:
  6. This module contains the server end of the Elf APIs.
  7. Author:
  8. Rajen Shah (rajens) 29-Jul-1991
  9. Revision History:
  10. 14-May-01 a-jyotig
  11. Removed impersonation from ElfrClearELFW as it is no longer required to
  12. identify the client that clears a log.
  13. 02-Mar-01 drbeck
  14. Modified ElfrClearELFW to impersonate client so that a SACL placed on the
  15. system event log will correctly identify the client that clears a log.
  16. 10-Sep-1998 jschwart
  17. Added ElfrGetLogInformation (GetEventlogInformation) API
  18. 30-Jan-1995 MarkBl
  19. Backup operators are allowed to open the security log, but only
  20. to perform backup operations. All other operations are prohibited.
  21. 13-Oct-1993 Danl
  22. ElfrOpenELA: Fixed Memory Leak bug where it was not calling
  23. RtlFreeUnicodeString for pRegModuleNameU and PModuleNameU.
  24. 29-Jul-1991 RajenS
  25. Created
  26. --*/
  27. /****
  28. @doc EXTERNAL INTERFACES EVTLOG
  29. ****/
  30. #include <eventp.h>
  31. #include <elfcfg.h>
  32. #include <stdio.h> // swprintf
  33. #include <stdlib.h>
  34. #include <memory.h>
  35. #include <clussprt.h>
  36. #include <tstr.h>
  37. #include <strsafe.h>
  38. //
  39. // Maximum number of ChangeNotify requests per context handle
  40. //
  41. #define MAX_NOTIFY_REQUESTS 5
  42. //
  43. // Batch queue support. Note that only in cluster machines resources will be allocated
  44. // for batch queue support. For non-cluster machines, the following few bytes are the
  45. // only ones allocated.
  46. //
  47. #define MAX_BATCH_QUEUE_ELEMENTS 256
  48. PBATCH_QUEUE_ELEMENT g_pBatchQueueElement = NULL;
  49. DWORD g_dwFirstFreeIndex = 0;
  50. RTL_CRITICAL_SECTION g_CSBatchQueue;
  51. LPDWORD g_pcbRecordsOfSameType = NULL;
  52. LPDWORD g_pdwRecordType = NULL;
  53. PPROPINFO g_pPropagatedInfo = NULL;
  54. HANDLE g_hBatchingSupportTimer = NULL;
  55. HANDLE g_hBatchingSupportTimerQueue = NULL;
  56. BOOL g_fBatchingSupportInitialized = FALSE;
  57. //
  58. // PROTOTYPES
  59. //
  60. NTSTATUS
  61. ElfpOpenELW (
  62. IN EVENTLOG_HANDLE_W UNCServerName,
  63. IN PRPC_UNICODE_STRING ModuleName,
  64. IN PRPC_UNICODE_STRING RegModuleName,
  65. IN ULONG MajorVersion,
  66. IN ULONG MinorVersion,
  67. OUT PIELF_HANDLE LogHandle,
  68. IN ULONG DesiredAccess
  69. );
  70. NTSTATUS
  71. ElfpOpenELA (
  72. IN EVENTLOG_HANDLE_A UNCServerName,
  73. IN PRPC_STRING ModuleName,
  74. IN PRPC_STRING RegModuleName,
  75. IN ULONG MajorVersion,
  76. IN ULONG MinorVersion,
  77. OUT PIELF_HANDLE LogHandle,
  78. IN ULONG DesiredAccess
  79. );
  80. VOID
  81. FreePUStringArray (
  82. IN PUNICODE_STRING * pUStringArray,
  83. IN USHORT NumStrings
  84. );
  85. NTSTATUS
  86. VerifyElfHandle(
  87. IN IELF_HANDLE LogHandle
  88. );
  89. NTSTATUS
  90. VerifyAnsiString(
  91. IN PANSI_STRING pAString
  92. );
  93. NTSTATUS
  94. ElfpClusterRpcAccessCheck(
  95. VOID
  96. );
  97. //
  98. // These APIs only have one interface, since they don't take or return strings
  99. //
  100. NTSTATUS
  101. ElfrNumberOfRecords(
  102. IN IELF_HANDLE LogHandle,
  103. OUT PULONG NumberOfRecords
  104. )
  105. /*++
  106. Routine Description:
  107. This is the RPC server entry point for the ElfrCurrentRecord API.
  108. Arguments:
  109. LogHandle - The context-handle for this module's call.
  110. NumberOfRecords - Where to return the total number of records in the
  111. log file.
  112. Return Value:
  113. Returns an NTSTATUS code.
  114. --*/
  115. {
  116. PLOGMODULE Module;
  117. NTSTATUS Status;
  118. //
  119. // Check the handle before proceeding.
  120. //
  121. Status = VerifyElfHandle(LogHandle);
  122. if (!NT_SUCCESS(Status))
  123. {
  124. ELF_LOG1(ERROR,
  125. "ElfrNumberOfRecords: VerifyElfHandle failed %#x\n",
  126. Status);
  127. return Status;
  128. }
  129. //
  130. // Insure the caller has read access.
  131. //
  132. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_READ))
  133. {
  134. ELF_LOG0(ERROR,
  135. "ElfrNumberOfRecords: LogHandle doesn't have read access\n");
  136. return STATUS_ACCESS_DENIED;
  137. }
  138. //
  139. // Verify additional arguments.
  140. //
  141. if (NumberOfRecords == NULL)
  142. {
  143. ELF_LOG0(ERROR,
  144. "ElfrNumberOfRecords: NumberOfRecords is NULL\n");
  145. return STATUS_INVALID_PARAMETER;
  146. }
  147. //
  148. // This condition is TRUE iff a backup operator has opened the security
  149. // log. In this case deny access, since backup operators are allowed
  150. // only backup operation on the security log.
  151. //
  152. if (LogHandle->GrantedAccess & ELF_LOGFILE_BACKUP)
  153. {
  154. ELF_LOG0(ERROR,
  155. "ElfrNumberOfRecords: Handle is a backup handle\n");
  156. return STATUS_ACCESS_DENIED;
  157. }
  158. //
  159. // If the OldestRecordNumber is 0, that means we have an empty
  160. // file, else we calculate the difference between the oldest
  161. // and next record numbers
  162. //
  163. Module = FindModuleStrucFromAtom(LogHandle->Atom);
  164. if (Module != NULL)
  165. {
  166. *NumberOfRecords = Module->LogFile->OldestRecordNumber == 0 ? 0 :
  167. Module->LogFile->CurrentRecordNumber -
  168. Module->LogFile->OldestRecordNumber;
  169. }
  170. else
  171. {
  172. ELF_LOG0(ERROR,
  173. "ElfrNumberOfRecords: No module struc associated with atom\n");
  174. Status = STATUS_INVALID_HANDLE;
  175. }
  176. return Status;
  177. }
  178. NTSTATUS
  179. ElfrOldestRecord(
  180. IN IELF_HANDLE LogHandle,
  181. OUT PULONG OldestRecordNumber
  182. )
  183. {
  184. PLOGMODULE Module;
  185. NTSTATUS Status;
  186. //
  187. // Check the handle before proceeding.
  188. //
  189. Status = VerifyElfHandle(LogHandle);
  190. if (!NT_SUCCESS(Status))
  191. {
  192. ELF_LOG1(ERROR,
  193. "ElfrOldestRecord: VerifyElfHandle failed %#x\n",
  194. Status);
  195. return Status;
  196. }
  197. //
  198. // Insure the caller has read access.
  199. //
  200. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_READ))
  201. {
  202. ELF_LOG0(ERROR,
  203. "ElfrOldestRecord: LogHandle doesn't have read access\n");
  204. return STATUS_ACCESS_DENIED;
  205. }
  206. //
  207. // Verify additional arguments.
  208. //
  209. if (OldestRecordNumber == NULL)
  210. {
  211. ELF_LOG0(ERROR,
  212. "ElfrOldestRecord: OldestRecordNumber is NULL\n");
  213. return STATUS_INVALID_PARAMETER;
  214. }
  215. //
  216. // This condition is TRUE iff a backup operator has opened the security
  217. // log. In this case deny access, since backup operators are allowed
  218. // only backup operation on the security log.
  219. //
  220. if (LogHandle->GrantedAccess & ELF_LOGFILE_BACKUP)
  221. {
  222. ELF_LOG0(ERROR,
  223. "ElfrOldestRecord: Handle is a backup handle\n");
  224. return STATUS_ACCESS_DENIED;
  225. }
  226. Module = FindModuleStrucFromAtom (LogHandle->Atom);
  227. if (Module != NULL)
  228. {
  229. *OldestRecordNumber = Module->LogFile->OldestRecordNumber;
  230. }
  231. else
  232. {
  233. ELF_LOG0(ERROR,
  234. "ElfrOldestRecord: No module struc associated with atom\n");
  235. Status = STATUS_INVALID_HANDLE;
  236. }
  237. return Status;
  238. }
  239. NTSTATUS
  240. CheckFileValidity(PUNICODE_STRING pUFileName)
  241. {
  242. NTSTATUS Status;
  243. Status = I_RpcMapWin32Status(RpcImpersonateClient(NULL));
  244. if (NT_SUCCESS(Status))
  245. {
  246. Status = VerifyFileIsFile(pUFileName);
  247. if (!NT_SUCCESS(Status))
  248. {
  249. ELF_LOG1(ERROR,
  250. "CheckFileValidity: VerifyFileIsFile failed %#x\n",
  251. Status);
  252. RpcRevertToSelf();
  253. return Status;
  254. }
  255. Status = I_RpcMapWin32Status(RpcRevertToSelf());
  256. }
  257. else
  258. {
  259. ELF_LOG1(ERROR,
  260. "CheckFileValidity: RpcImpersonateClient failed %#x\n",
  261. Status);
  262. }
  263. return Status;
  264. }
  265. NTSTATUS
  266. ElfrChangeNotify(
  267. IN IELF_HANDLE LogHandle,
  268. IN RPC_CLIENT_ID ClientId,
  269. IN ULONG Event
  270. )
  271. {
  272. NTSTATUS Status;
  273. NTSTATUS RpcStatus;
  274. OBJECT_ATTRIBUTES ObjectAttributes;
  275. HANDLE ProcessHandle = NULL;
  276. HANDLE EventHandle;
  277. PLOGMODULE Module;
  278. PNOTIFIEE Notifiee;
  279. CLIENT_ID tempCli;
  280. //
  281. // Check the handle before proceeding.
  282. //
  283. Status = VerifyElfHandle(LogHandle);
  284. if (!NT_SUCCESS(Status))
  285. {
  286. ELF_LOG1(ERROR,
  287. "ElfrChangeNotify: VerifyElfHandle failed %#x\n",
  288. Status);
  289. return Status;
  290. }
  291. //
  292. // Ensure the caller has read access.
  293. //
  294. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_READ))
  295. {
  296. ELF_LOG0(ERROR,
  297. "ElfrChangeNotify: LogHandle doesn't have read access\n");
  298. return STATUS_ACCESS_DENIED;
  299. }
  300. //
  301. // First make sure that this is a local call and that it is not a
  302. // handle that was created for a backup log file
  303. //
  304. if (LogHandle->Flags & ELF_LOG_HANDLE_REMOTE_HANDLE ||
  305. LogHandle->Flags & ELF_LOG_HANDLE_BACKUP_LOG)
  306. {
  307. ELF_LOG1(ERROR,
  308. "ElfrChangeNotify: Handle is for a %ws log\n",
  309. LogHandle->Flags & ELF_LOG_HANDLE_REMOTE_HANDLE ? L"remote" :
  310. L"backup");
  311. return STATUS_INVALID_HANDLE;
  312. }
  313. //
  314. // This condition is TRUE iff a backup operator has opened the security
  315. // log. In this case deny access, since backup operators are allowed
  316. // only backup operation on the security log.
  317. //
  318. if (LogHandle->GrantedAccess & ELF_LOGFILE_BACKUP)
  319. {
  320. ELF_LOG0(ERROR,
  321. "ElfrChangeNotify: Handle is a backup handle\n");
  322. return STATUS_ACCESS_DENIED;
  323. }
  324. //
  325. // Make sure the client has the right to open this process
  326. //
  327. RpcStatus = RpcImpersonateClient(NULL);
  328. if (RpcStatus != RPC_S_OK)
  329. {
  330. ELF_LOG1(ERROR,
  331. "ElfrChangeNotify: RpcImpersonateClient failed %#x\n",
  332. RpcStatus);
  333. return I_RpcMapWin32Status(RpcStatus);
  334. }
  335. //
  336. // First get a handle to the process using the passed in ClientId. Note
  337. // that the ClientId is supplied by the client so a rogue client may
  338. // supply any client ID. However, because we impersonate when opening
  339. // the process we don't get any additional access the client doesn't have.
  340. //
  341. InitializeObjectAttributes(&ObjectAttributes,
  342. NULL, // UNICODE string
  343. 0, // Attributes
  344. NULL, // Root directory
  345. NULL); // Security descriptor
  346. #ifdef _WIN64
  347. tempCli.UniqueProcess = (HANDLE)ULongToPtr(ClientId.UniqueProcess);
  348. tempCli.UniqueThread = (HANDLE)ULongToPtr(ClientId.UniqueThread);
  349. Status = NtOpenProcess(&ProcessHandle,
  350. PROCESS_DUP_HANDLE,
  351. &ObjectAttributes,
  352. &tempCli);
  353. #else
  354. Status = NtOpenProcess(&ProcessHandle,
  355. PROCESS_DUP_HANDLE,
  356. &ObjectAttributes,
  357. (PCLIENT_ID) &ClientId);
  358. #endif
  359. RpcStatus = RpcRevertToSelf();
  360. if (RpcStatus != RPC_S_OK)
  361. {
  362. ELF_LOG1(ERROR,
  363. "ElfrChangeNotify: RpcRevertToSelf failed %#x\n",
  364. RpcStatus);
  365. }
  366. if (NT_SUCCESS(Status))
  367. {
  368. //
  369. // Now dupe the handle they passed in for the event
  370. //
  371. Status = NtDuplicateObject(ProcessHandle,
  372. LongToHandle(Event),
  373. NtCurrentProcess(),
  374. &EventHandle,
  375. 0,
  376. 0,
  377. DUPLICATE_SAME_ACCESS);
  378. if (NT_SUCCESS(Status))
  379. {
  380. //
  381. // Create a new NOTIFIEE control block to link in
  382. //
  383. Notifiee = ElfpAllocateBuffer(sizeof(NOTIFIEE));
  384. if (Notifiee)
  385. {
  386. //
  387. // Fill in the fields
  388. //
  389. Notifiee->Handle = LogHandle;
  390. Notifiee->Event = EventHandle;
  391. //
  392. // Find the LOGFILE associated with this handle
  393. //
  394. Module = FindModuleStrucFromAtom(LogHandle->Atom);
  395. if (Module != NULL)
  396. {
  397. //
  398. // Get exclusive access to the log file. This will ensure
  399. // no one else is accessing the file.
  400. //
  401. RtlAcquireResourceExclusive(&Module->LogFile->Resource,
  402. TRUE); // Wait until available
  403. //
  404. // Enforce the limit of ChangeNotify requests per context handle
  405. //
  406. if (LogHandle->dwNotifyRequests == MAX_NOTIFY_REQUESTS)
  407. {
  408. ELF_LOG1(ERROR,
  409. "ElfrChangeNotify: Already %d requests for this handle\n",
  410. MAX_NOTIFY_REQUESTS);
  411. NtClose(EventHandle);
  412. ElfpFreeBuffer(Notifiee);
  413. Status = STATUS_INSUFFICIENT_RESOURCES;
  414. }
  415. else
  416. {
  417. //
  418. // Insert the new notifiee into the list and increment this
  419. // context handle's ChangeNotify request count
  420. //
  421. InsertHeadList(&Module->LogFile->Notifiees,
  422. &Notifiee->Next);
  423. LogHandle->dwNotifyRequests++;
  424. }
  425. //
  426. // Free the resource
  427. //
  428. RtlReleaseResource ( &Module->LogFile->Resource );
  429. }
  430. else
  431. {
  432. ELF_LOG0(ERROR,
  433. "ElfrChangeNotify: No module struc associated with atom\n");
  434. NtClose(EventHandle);
  435. ElfpFreeBuffer(Notifiee);
  436. Status = STATUS_INVALID_HANDLE;
  437. }
  438. }
  439. else
  440. {
  441. ELF_LOG0(ERROR,
  442. "ElfrChangeNotify: Unable to allocate NOTIFIEE block\n");
  443. Status = STATUS_NO_MEMORY;
  444. //
  445. // Free the duplicated handle
  446. //
  447. CloseHandle(EventHandle);
  448. }
  449. }
  450. else
  451. {
  452. ELF_LOG1(ERROR,
  453. "ElfrChangeNotify: NtDuplicateObject failed %#x\n",
  454. Status);
  455. }
  456. }
  457. else
  458. {
  459. ELF_LOG1(ERROR,
  460. "ElfrChangeNotify: NtOpenProcess failed %#x\n",
  461. Status);
  462. if (Status == STATUS_INVALID_CID)
  463. {
  464. Status = STATUS_INVALID_HANDLE;
  465. }
  466. }
  467. if (ProcessHandle)
  468. {
  469. NtClose(ProcessHandle);
  470. }
  471. return Status;
  472. }
  473. NTSTATUS
  474. ElfrGetLogInformation(
  475. IN IELF_HANDLE LogHandle,
  476. IN ULONG InfoLevel,
  477. OUT PBYTE lpBuffer,
  478. IN ULONG cbBufSize,
  479. OUT PULONG pcbBytesNeeded
  480. )
  481. /*++
  482. Routine Description:
  483. This is the RPC server entry point for the ElfrGetLogInformation API.
  484. Arguments:
  485. LogHandle - The context-handle for this module's call.
  486. InfoLevel - Infolevel that specifies which information the user is requesting
  487. lpBuffer - Buffer into which to place the information
  488. cbBufSize - Size of lpBuffer, in bytes
  489. pcbBytesNeeded - Required size of the buffer
  490. Return Value:
  491. Returns an NTSTATUS code.
  492. --*/
  493. {
  494. NTSTATUS ntStatus;
  495. PLOGMODULE pLogModule;
  496. //
  497. // Check the handle before proceeding.
  498. //
  499. ntStatus = VerifyElfHandle(LogHandle);
  500. if (!NT_SUCCESS(ntStatus))
  501. {
  502. ELF_LOG1(ERROR,
  503. "ElfrGetLogInformation: VerifyElfHandle failed %#x\n",
  504. ntStatus);
  505. return ntStatus;
  506. }
  507. //
  508. // This condition is TRUE iff a backup operator has opened the security
  509. // log. In this case deny access, since backup operators are allowed
  510. // only backup operation on the security log.
  511. //
  512. if (LogHandle->GrantedAccess & ELF_LOGFILE_BACKUP)
  513. {
  514. ELF_LOG0(ERROR,
  515. "ElfrGetLogInformation: Handle is a backup handle\n");
  516. return STATUS_ACCESS_DENIED;
  517. }
  518. //
  519. // Take the appropriate actions based on the Infolevel
  520. //
  521. switch (InfoLevel)
  522. {
  523. case EVENTLOG_FULL_INFO:
  524. *pcbBytesNeeded = sizeof(EVENTLOG_FULL_INFORMATION);
  525. if (cbBufSize < *pcbBytesNeeded)
  526. {
  527. ELF_LOG2(ERROR,
  528. "ElfrGetLogInformation: buffer size = %d, required size = %d\n",
  529. cbBufSize,
  530. *pcbBytesNeeded);
  531. ntStatus = STATUS_BUFFER_TOO_SMALL;
  532. break;
  533. }
  534. //
  535. // Get the module associated with this log handle
  536. //
  537. pLogModule = FindModuleStrucFromAtom(LogHandle->Atom);
  538. if (pLogModule != NULL)
  539. {
  540. //
  541. // The caller has the permission for this operation. Note
  542. // that an access check is done when opening the log, so
  543. // there's no need to repeat it here.
  544. //
  545. ((LPEVENTLOG_FULL_INFORMATION)lpBuffer)->dwFull =
  546. (pLogModule->LogFile->Flags & ELF_LOGFILE_LOGFULL_WRITTEN ?
  547. TRUE :
  548. FALSE);
  549. ELF_LOG2(TRACE,
  550. "ElfrGetLogInformation: %ws log is %ws\n",
  551. pLogModule->LogFile->LogModuleName->Buffer,
  552. pLogModule->LogFile->Flags & ELF_LOGFILE_LOGFULL_WRITTEN ?
  553. L"full" :
  554. L"not full");
  555. }
  556. else
  557. {
  558. ELF_LOG0(ERROR,
  559. "ElfrGetLogInformation: No module struc associated with atom\n");
  560. ntStatus = STATUS_INVALID_HANDLE;
  561. }
  562. break;
  563. default:
  564. ELF_LOG1(ERROR,
  565. "ElfrGetLogInformation: Invalid InfoLevel %d\n",
  566. InfoLevel);
  567. ntStatus = STATUS_INVALID_LEVEL;
  568. break;
  569. }
  570. return ntStatus;
  571. }
  572. //
  573. // UNICODE APIs
  574. //
  575. NTSTATUS
  576. ElfrClearELFW (
  577. IN IELF_HANDLE LogHandle,
  578. IN PRPC_UNICODE_STRING BackupFileName
  579. )
  580. /*++
  581. Routine Description:
  582. This is the RPC server entry point for the ElfrClearELFW API.
  583. CleanExit lable was written to add some cleanup code. The cleanup code was
  584. removed later as it was not required but the lable is retained in order to
  585. add any cleanup code if required in future
  586. Arguments:
  587. LogHandle - The context-handle for this module's call. This must
  588. not have been returned from OpenBackupEventlog, or
  589. this call will fail with invalid handle.
  590. BackupFileName - Name of the file to back up the current log file.
  591. NULL implies not to back up the file.
  592. Return Value:
  593. Returns an NTSTATUS code.
  594. --*/
  595. {
  596. NTSTATUS Status;
  597. PLOGMODULE Module;
  598. ELF_REQUEST_RECORD Request;
  599. CLEAR_PKT ClearPkt;
  600. DWORD status = NO_ERROR;
  601. LPWSTR pwsClientSidString = NULL;
  602. LPWSTR pwsComputerName = NULL;
  603. PTOKEN_USER pToken = NULL;
  604. //
  605. // Check the handle before proceeding.
  606. //
  607. Status = VerifyElfHandle(LogHandle);
  608. if (!NT_SUCCESS(Status))
  609. {
  610. ELF_LOG1(ERROR,
  611. "ElfrClearELFW: VerifyElfHandle failed %#x\n",
  612. Status);
  613. goto CleanExit;
  614. }
  615. //
  616. // Ensure the caller has clear access.
  617. //
  618. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_CLEAR))
  619. {
  620. ELF_LOG0(ERROR,
  621. "ElfrClearELFW: LogHandle doesn't have clear access\n");
  622. Status = STATUS_ACCESS_DENIED;
  623. goto CleanExit;
  624. }
  625. //
  626. // Verify additional arguments.
  627. //
  628. if (BackupFileName != NULL)
  629. {
  630. Status = VerifyUnicodeString(BackupFileName);
  631. if (!NT_SUCCESS(Status))
  632. {
  633. ELF_LOG0(ERROR,
  634. "ElfrClearELFW: BackupFileName is an invalid Unicode string\n");
  635. goto CleanExit;
  636. }
  637. if(BackupFileName->Length > 0)
  638. {
  639. Status = VerifyFileIsFile (BackupFileName);
  640. if (!NT_SUCCESS(Status))
  641. {
  642. ELF_LOG2(ERROR,
  643. "ElfrClearELFW: VerifyFileIsFile of backup file %ws failed %#x\n",
  644. BackupFileName,
  645. Status);
  646. goto CleanExit;
  647. }
  648. }
  649. }
  650. //
  651. // Can't clear a backup log
  652. //
  653. if (LogHandle->Flags & ELF_LOG_HANDLE_BACKUP_LOG)
  654. {
  655. ELF_LOG0(ERROR,
  656. "ElfrClearELFW: Handle is for a backup log\n");
  657. Status = STATUS_INVALID_HANDLE;
  658. goto CleanExit;
  659. }
  660. //
  661. // This condition is TRUE iff a backup operator has opened the security
  662. // log. In this case deny access, since backup operators are allowed
  663. // only backup operation on the security log.
  664. //
  665. if (LogHandle->GrantedAccess & ELF_LOGFILE_BACKUP)
  666. {
  667. ELF_LOG0(ERROR,
  668. "ElfrClearELFW: Handle is a backup handle\n");
  669. Status = STATUS_ACCESS_DENIED;
  670. goto CleanExit;
  671. }
  672. //
  673. // Find the matching module structure
  674. //
  675. Module = FindModuleStrucFromAtom (LogHandle->Atom);
  676. Request.Pkt.ClearPkt = &ClearPkt;
  677. Request.Flags = 0;
  678. if (Module != NULL)
  679. {
  680. //
  681. // Verify that the caller has clear access to this logfile
  682. //
  683. if (!RtlAreAllAccessesGranted(LogHandle->GrantedAccess,
  684. ELF_LOGFILE_CLEAR))
  685. {
  686. ELF_LOG1(ERROR,
  687. "ElfrClearELFW: Caller does not have clear access to %ws log\n",
  688. Module->LogFile->LogModuleName->Buffer);
  689. Status = STATUS_ACCESS_DENIED;
  690. }
  691. if (NT_SUCCESS(Status))
  692. {
  693. //
  694. // Fill in the request packet
  695. //
  696. Request.Module = Module;
  697. Request.LogFile = Module->LogFile;
  698. Request.Command = ELF_COMMAND_CLEAR;
  699. Request.Status = STATUS_SUCCESS;
  700. Request.Pkt.ClearPkt->BackupFileName =
  701. (PUNICODE_STRING)BackupFileName;
  702. //
  703. // Call the worker routine to do the operation.
  704. //
  705. if (_wcsicmp(ELF_SECURITY_MODULE_NAME,
  706. Module->LogFile->LogModuleName->Buffer) == 0)
  707. {
  708. // for the security log, make sure that the most basic info is there
  709. // so that the cleared event audit will always succeed
  710. Status = ElfpGetClientSidString(&pwsClientSidString, &pToken);
  711. if (!NT_SUCCESS(Status))
  712. goto CleanExit;
  713. pwsComputerName = ElfpGetComputerName();
  714. if(pwsComputerName == NULL)
  715. {
  716. Status = STATUS_INSUFFICIENT_RESOURCES;
  717. goto CleanExit;
  718. }
  719. ElfPerformRequest(&Request);
  720. if (NT_SUCCESS(Request.Status))
  721. ElfpGenerateLogClearedEvent(LogHandle,pwsClientSidString,pwsComputerName,pToken);
  722. }
  723. else
  724. ElfPerformRequest(&Request);
  725. //
  726. // Extract status of operation from the request packet
  727. //
  728. Status = Request.Status;
  729. }
  730. }
  731. else
  732. {
  733. ELF_LOG0(ERROR,
  734. "ElfrClearELFW: No module struc associated with atom\n");
  735. Status = STATUS_INVALID_HANDLE;
  736. }
  737. CleanExit:
  738. if(pwsComputerName)
  739. ElfpFreeBuffer(pwsComputerName);
  740. if(pwsClientSidString)
  741. ElfpFreeBuffer(pwsClientSidString);
  742. if(pToken)
  743. ElfpFreeBuffer(pToken);
  744. return Status;
  745. }
  746. NTSTATUS
  747. ElfrBackupELFW (
  748. IN IELF_HANDLE LogHandle,
  749. IN PRPC_UNICODE_STRING BackupFileName
  750. )
  751. /*++
  752. Routine Description:
  753. This is the RPC server entry point for the ElfrBackupELFW API.
  754. Arguments:
  755. LogHandle - The context-handle for this module's call.
  756. BackupFileName - Name of the file to back up the current log file.
  757. Return Value:
  758. Returns an NTSTATUS code.
  759. --*/
  760. {
  761. NTSTATUS Status;
  762. PLOGMODULE Module;
  763. ELF_REQUEST_RECORD Request;
  764. BACKUP_PKT BackupPkt;
  765. //
  766. // Check the handle before proceeding.
  767. //
  768. Status = VerifyElfHandle(LogHandle);
  769. if (!NT_SUCCESS(Status))
  770. {
  771. ELF_LOG1(ERROR,
  772. "ElfrBackupELFW: VerifyElfHandle failed %#x\n",
  773. Status);
  774. return Status;
  775. }
  776. //
  777. // Ensure the caller has read access.
  778. // This has been removed by davj since backup should be verified via the priviledge
  779. // if (!(LogHandle->GrantedAccess & ELF_LOGFILE_READ))
  780. // {
  781. // ELF_LOG0(ERROR,
  782. // "ElfrBackupELFW: LogHandle doesn't have read access\n");
  783. //
  784. // return STATUS_ACCESS_DENIED;
  785. // }
  786. //
  787. // Make sure the client has SE_BACKUP_PRIVILEGE enabled. Note
  788. // that we attempted to enable this on the client side
  789. //
  790. if (ElfpTestClientPrivilege(SE_BACKUP_PRIVILEGE, NULL) != STATUS_SUCCESS)
  791. {
  792. ELF_LOG0(ERROR,
  793. "ElfrBackupELFW: Client does not have SE_BACKUP_PRIVILEGE\n");
  794. return(STATUS_PRIVILEGE_NOT_HELD);
  795. }
  796. //
  797. // Verify additional arguments.
  798. //
  799. Status = VerifyUnicodeString(BackupFileName);
  800. if (!NT_SUCCESS(Status))
  801. {
  802. ELF_LOG0(ERROR,
  803. "ElfrBackupELFW: BackupFileName is not a valid Unicode string\n");
  804. return Status;
  805. }
  806. //
  807. // A filename must be specified.
  808. //
  809. if (BackupFileName->Length == 0) {
  810. return(STATUS_INVALID_PARAMETER);
  811. }
  812. Status = CheckFileValidity(BackupFileName);
  813. if (!NT_SUCCESS(Status))
  814. {
  815. ELF_LOG0(ERROR,
  816. "ElfrBackupELFW: CheckFileValidity failed\n");
  817. return Status;
  818. }
  819. Request.Pkt.BackupPkt = &BackupPkt;
  820. Request.Flags = 0;
  821. //
  822. // Find the matching module structure
  823. //
  824. Module = FindModuleStrucFromAtom(LogHandle->Atom);
  825. if (Module != NULL)
  826. {
  827. //
  828. // Fill in the request packet
  829. Request.Module = Module;
  830. Request.LogFile = Module->LogFile;
  831. Request.Command = ELF_COMMAND_BACKUP;
  832. Request.Status = STATUS_SUCCESS;
  833. Request.Pkt.BackupPkt->BackupFileName =
  834. (PUNICODE_STRING)BackupFileName;
  835. //
  836. // Call the worker routine to do the operation.
  837. //
  838. ElfPerformRequest (&Request);
  839. //
  840. // Extract status of operation from the request packet
  841. //
  842. Status = Request.Status;
  843. }
  844. else
  845. {
  846. ELF_LOG0(ERROR,
  847. "ElfrBackupELFW: No module struc associated with atom\n");
  848. Status = STATUS_INVALID_HANDLE;
  849. }
  850. return Status;
  851. }
  852. NTSTATUS
  853. ElfrCloseEL (
  854. IN OUT PIELF_HANDLE LogHandle
  855. )
  856. /*++
  857. Routine Description:
  858. This is the RPC server entry point for the ElfrCloseEL API.
  859. Arguments:
  860. Return Value:
  861. Returns an NTSTATUS code.
  862. --*/
  863. {
  864. NTSTATUS Status;
  865. //
  866. // Check the handle before proceeding.
  867. //
  868. if (LogHandle == NULL)
  869. {
  870. ELF_LOG0(ERROR,
  871. "ElfrCloseEL: LogHandle is NULL\n");
  872. return STATUS_INVALID_PARAMETER;
  873. }
  874. Status = VerifyElfHandle(*LogHandle);
  875. if (!NT_SUCCESS(Status))
  876. {
  877. ELF_LOG1(ERROR,
  878. "ElfrCloseEL: VerifyElfHandle failed %#x\n",
  879. Status);
  880. return Status;
  881. }
  882. //
  883. // Call the rundown routine to do all the work
  884. //
  885. IELF_HANDLE_rundown(*LogHandle);
  886. *LogHandle = NULL; // so RPC knows it's closed
  887. return STATUS_SUCCESS;
  888. }
  889. NTSTATUS
  890. ElfrDeregisterEventSource(
  891. IN OUT PIELF_HANDLE LogHandle
  892. )
  893. /*++
  894. Routine Description:
  895. This is the RPC server entry point for the ElfrDeregisterEventSource API.
  896. Arguments:
  897. Return Value:
  898. Returns an NTSTATUS code.
  899. --*/
  900. {
  901. NTSTATUS Status;
  902. if (LogHandle == NULL)
  903. {
  904. ELF_LOG0(ERROR,
  905. "ElfrDeregisterEventSource: LogHandle is NULL\n");
  906. return STATUS_INVALID_PARAMETER;
  907. }
  908. //
  909. // Check the handle before proceeding.
  910. //
  911. Status = VerifyElfHandle(*LogHandle);
  912. if (!NT_SUCCESS(Status))
  913. {
  914. ELF_LOG1(ERROR,
  915. "ElfrDeregisterEventSource: VerifyElfHandle failed %#x\n",
  916. Status);
  917. return Status;
  918. }
  919. //
  920. // This condition is TRUE iff a backup operator has opened the security
  921. // log. In this case deny access, since backup operators are allowed
  922. // only backup operation on the security log.
  923. //
  924. if ((*LogHandle)->GrantedAccess & ELF_LOGFILE_BACKUP)
  925. {
  926. ELF_LOG0(ERROR,
  927. "ElfrDeregisterEventSource: Handle is a backup handle\n");
  928. return STATUS_ACCESS_DENIED;
  929. }
  930. //
  931. // Call the rundown routine to do all the work
  932. //
  933. IELF_HANDLE_rundown(*LogHandle);
  934. *LogHandle = NULL; // so RPC knows it's closed
  935. return STATUS_SUCCESS;
  936. }
  937. NTSTATUS
  938. ElfrOpenBELW (
  939. IN EVENTLOG_HANDLE_W UNCServerName,
  940. IN PRPC_UNICODE_STRING BackupFileName,
  941. IN ULONG MajorVersion,
  942. IN ULONG MinorVersion,
  943. OUT PIELF_HANDLE LogHandle
  944. )
  945. /*++
  946. Routine Description:
  947. This is the RPC server entry point for the ElfrOpenBELW API. It creates
  948. a module structure $BACKUPnnn where nnn is a unique number for every backup
  949. log that is opened. It then calls ElfpOpenELW to actually open the file.
  950. Arguments:
  951. UNCServerName - Not used.
  952. BackupFileName - Name of the backup log file.
  953. MajorVersion/MinorVersion - The version of the client.
  954. LogHandle - Pointer to the place where the pointer to the
  955. context handle structure will be placed.
  956. Return Value:
  957. Returns an NTSTATUS code and, if no error, a "handle".
  958. --*/
  959. {
  960. NTSTATUS Status;
  961. UNICODE_STRING BackupStringW;
  962. LPWSTR BackupModuleName;
  963. PLOGMODULE pModule;
  964. DWORD dwModuleNumber;
  965. //
  966. // Size of buffer (in bytes) required for a UNICODE string of $BACKUPnnn
  967. //
  968. #define SIZEOF_BACKUP_MODULE_NAME 64
  969. UNREFERENCED_PARAMETER(UNCServerName);
  970. //
  971. // Check arguments.
  972. //
  973. Status = VerifyUnicodeString(BackupFileName);
  974. if (!NT_SUCCESS(Status))
  975. {
  976. ELF_LOG0(ERROR,
  977. "ElfrOpenBELW: BackupFileName is not a Unicode string\n");
  978. return Status;
  979. }
  980. //
  981. // A filename must be specified.
  982. //
  983. if (BackupFileName->Length == 0)
  984. {
  985. ELF_LOG0(ERROR,
  986. "ElfrOpenBELW: Length of BackupFileName is 0\n");
  987. return STATUS_INVALID_PARAMETER;
  988. }
  989. if (LogHandle == NULL)
  990. {
  991. ELF_LOG0(ERROR,
  992. "ElfrOpenBELW: LogHandle is NULL\n");
  993. return STATUS_INVALID_PARAMETER;
  994. }
  995. //
  996. // Create a unique module name by incrementing a global value
  997. //
  998. BackupModuleName = ElfpAllocateBuffer(SIZEOF_BACKUP_MODULE_NAME);
  999. if (BackupModuleName == NULL)
  1000. {
  1001. ELF_LOG0(ERROR,
  1002. "ElfrOpenBELW: Unable to allocate memory for BackupModuleName\n");
  1003. return STATUS_NO_MEMORY;
  1004. }
  1005. //
  1006. // Serialize read, increment of the global backup module number.
  1007. // Note: double-timing the log file list critical section so as to not
  1008. // require another critical section specifically dedicated to this
  1009. // operation.
  1010. //
  1011. RtlEnterCriticalSection (&LogFileCritSec);
  1012. dwModuleNumber = BackupModuleNumber++;
  1013. RtlLeaveCriticalSection (&LogFileCritSec);
  1014. StringCbPrintf(BackupModuleName, SIZEOF_BACKUP_MODULE_NAME,
  1015. L"$BACKUP%06d", dwModuleNumber);
  1016. RtlInitUnicodeString(&BackupStringW, BackupModuleName);
  1017. ELF_LOG2(TRACE,
  1018. "ElfrOpenBELW: Backing up module %ws to file %ws\n",
  1019. BackupModuleName,
  1020. BackupFileName->Buffer);
  1021. //
  1022. // Call SetupDataStruct to build the module and log data structures
  1023. // and actually open the file.
  1024. //
  1025. // NOTE: If this call is successful, the Unicode String Buffer for
  1026. // BackupStringW (otherwise known as BackupModuleName) will be attached
  1027. // to the LogModule structure, and should not be free'd.
  1028. //
  1029. Status = SetUpDataStruct(
  1030. BackupFileName, // Filename
  1031. 0, // Max size, it will use actual
  1032. 0, // retention period, not used for bkup
  1033. &BackupStringW, // Module name
  1034. NULL, // Handle to registry, not used
  1035. ElfBackupLog, // Log type
  1036. LOGPOPUP_NEVER_SHOW,
  1037. ELF_DEFAULT_AUTOBACKUP);
  1038. if (!NT_SUCCESS(Status))
  1039. {
  1040. ELF_LOG3(ERROR,
  1041. "ElfrOpenBELW: SetUpDataStruct for file %ws (module %ws) failed %#x\n",
  1042. BackupFileName->Buffer,
  1043. BackupModuleName,
  1044. Status);
  1045. ElfpFreeBuffer(BackupModuleName);
  1046. return Status;
  1047. }
  1048. //
  1049. // Call ElfOpenELW to actually open the log file and get a handle.
  1050. //
  1051. Status = ElfpOpenELW(NULL,
  1052. (PRPC_UNICODE_STRING) &BackupStringW,
  1053. NULL,
  1054. MajorVersion,
  1055. MinorVersion,
  1056. LogHandle,
  1057. ELF_LOGFILE_READ);
  1058. if (NT_SUCCESS(Status))
  1059. {
  1060. //
  1061. // Mark this as a handle for a backup log, so we can clean up
  1062. // differently when it's closed, as well as disallow clear, backup
  1063. // and write operations.
  1064. //
  1065. (*LogHandle)->Flags |= ELF_LOG_HANDLE_BACKUP_LOG;
  1066. }
  1067. else
  1068. {
  1069. ELF_LOG3(ERROR,
  1070. "ElfrOpenBELW: ElfpOpenELW for file %ws (module %ws) failed %#x\n",
  1071. BackupFileName->Buffer,
  1072. BackupModuleName,
  1073. Status);
  1074. //
  1075. // If we couldn't open the log file, then we need to tear down
  1076. // the DataStruct we set up with SetUpDataStruct.
  1077. //
  1078. pModule = GetModuleStruc(&BackupStringW);
  1079. //
  1080. // We'd better be unlinking the same module we just created
  1081. //
  1082. ASSERT(_wcsicmp(pModule->ModuleName, BackupModuleName) == 0);
  1083. Status = ElfpCloseLogFile(pModule->LogFile, ELF_LOG_CLOSE_BACKUP, TRUE);
  1084. UnlinkLogModule(pModule);
  1085. DeleteAtom(pModule->ModuleAtom);
  1086. ElfpFreeBuffer(pModule->ModuleName);
  1087. ElfpFreeBuffer(pModule);
  1088. }
  1089. return Status;
  1090. }
  1091. NTSTATUS
  1092. ElfrRegisterEventSourceW (
  1093. IN EVENTLOG_HANDLE_W UNCServerName,
  1094. IN PRPC_UNICODE_STRING ModuleName,
  1095. IN PRPC_UNICODE_STRING RegModuleName,
  1096. IN ULONG MajorVersion,
  1097. IN ULONG MinorVersion,
  1098. OUT PIELF_HANDLE LogHandle
  1099. )
  1100. /*++
  1101. Routine Description:
  1102. This is the RPC server entry point for the ElfrRegisterEventSourceW API.
  1103. This routine allocates a structure for the context handle, finds
  1104. the matching module name and fills in the data. It returns the
  1105. pointer to the handle structure.
  1106. Arguments:
  1107. UNCServerName - Not used.
  1108. ModuleName - Name of the module that is making this call.
  1109. RegModuleName - Not used.
  1110. MajorVersion/MinorVersion - The version of the client.
  1111. LogHandle - Pointer to the place where the pointer to the
  1112. context handle structure will be placed.
  1113. Return Value:
  1114. Returns an NTSTATUS code and, if no error, a "handle".
  1115. Note:
  1116. For now, just call ElfpOpenELW.
  1117. --*/
  1118. {
  1119. //
  1120. // All arguments checked in ElfpOpenELW.
  1121. //
  1122. return ElfpOpenELW(UNCServerName,
  1123. ModuleName,
  1124. RegModuleName,
  1125. MajorVersion,
  1126. MinorVersion,
  1127. LogHandle,
  1128. ELF_LOGFILE_WRITE);
  1129. }
  1130. NTSTATUS
  1131. ElfrOpenELW (
  1132. IN EVENTLOG_HANDLE_W UNCServerName,
  1133. IN PRPC_UNICODE_STRING ModuleName,
  1134. IN PRPC_UNICODE_STRING RegModuleName,
  1135. IN ULONG MajorVersion,
  1136. IN ULONG MinorVersion,
  1137. OUT PIELF_HANDLE LogHandle
  1138. )
  1139. /*++
  1140. Routine Description:
  1141. This is the RPC server entry point for the ElfrOpenELW API.
  1142. This routine allocates a structure for the context handle, finds
  1143. the matching module name and fills in the data. It returns the
  1144. pointer to the handle structure.
  1145. Arguments:
  1146. UNCServerName - Not used.
  1147. ModuleName - Name of the module that is making this call.
  1148. RegModuleName - Not used.
  1149. MajorVersion/MinorVersion - The version of the client.
  1150. LogHandle - Pointer to the place where the pointer to the
  1151. context handle structure will be placed.
  1152. Return Value:
  1153. Returns an NTSTATUS code and, if no error, a "handle".
  1154. --*/
  1155. {
  1156. //
  1157. // All arguments checked in ElfpOpenELW.
  1158. //
  1159. return ElfpOpenELW(UNCServerName,
  1160. ModuleName,
  1161. RegModuleName,
  1162. MajorVersion,
  1163. MinorVersion,
  1164. LogHandle,
  1165. ELF_LOGFILE_READ);
  1166. }
  1167. NTSTATUS
  1168. ElfpOpenELW (
  1169. IN EVENTLOG_HANDLE_W UNCServerName,
  1170. IN PRPC_UNICODE_STRING ModuleName,
  1171. IN PRPC_UNICODE_STRING RegModuleName,
  1172. IN ULONG MajorVersion,
  1173. IN ULONG MinorVersion,
  1174. OUT PIELF_HANDLE LogHandle,
  1175. IN ULONG DesiredAccess
  1176. )
  1177. /*++
  1178. Routine Description:
  1179. Looks alot like ElfrOpenELW but also gets passed a DesiredAccess.
  1180. Arguments:
  1181. UNCServerName - Not used.
  1182. ModuleName - Name of the module that is making this call.
  1183. RegModuleName - Not used.
  1184. MajorVersion/MinorVersion - The version of the client.
  1185. LogHandle - Pointer to the place where the pointer to the
  1186. context handle structure will be placed.
  1187. DesiredAccess - Indicates the access desired for this logfile.
  1188. Return Value:
  1189. Returns an NTSTATUS code and, if no error, a "handle".
  1190. --*/
  1191. {
  1192. NTSTATUS Status;
  1193. PLOGMODULE Module;
  1194. IELF_HANDLE LogIHandle;
  1195. BOOL ForSecurityLog = FALSE;
  1196. //
  1197. // Check arguments.
  1198. //
  1199. Status = VerifyUnicodeString(ModuleName);
  1200. if (!NT_SUCCESS(Status))
  1201. {
  1202. ELF_LOG0(ERROR,
  1203. "ElfpOpenELW: ModuleName is not a Unicode string\n");
  1204. return Status;
  1205. }
  1206. if (LogHandle == NULL)
  1207. {
  1208. ELF_LOG0(ERROR,
  1209. "ElfpOpenELW: LogHandle is NULL\n");
  1210. return STATUS_INVALID_PARAMETER;
  1211. }
  1212. //
  1213. // Allocate a new structure for the context handle
  1214. //
  1215. LogIHandle = (IELF_HANDLE) ElfpAllocateBuffer (
  1216. sizeof (*LogIHandle)
  1217. + ModuleName->Length
  1218. + sizeof (WCHAR)
  1219. );
  1220. if (LogIHandle)
  1221. {
  1222. //
  1223. // Find the module structure in order to pull out the Atom.
  1224. //
  1225. // GetModuleStruc *always* succeeds! (returns default if module
  1226. // not found).
  1227. //
  1228. Module = GetModuleStruc((PUNICODE_STRING) ModuleName);
  1229. //
  1230. // Validate the caller has appropriate access to this logfile.
  1231. // If this is the security log, then check privilege instead.
  1232. //
  1233. if (_wcsicmp(ELF_SECURITY_MODULE_NAME, Module->LogFile->LogModuleName->Buffer) == 0)
  1234. {
  1235. ELF_LOG0(TRACE,
  1236. "ElfpOpenELW: Opening Security log\n");
  1237. ForSecurityLog = TRUE;
  1238. }
  1239. LogIHandle->Flags = 0;
  1240. RtlAcquireResourceExclusive(&Module->LogFile->Resource,
  1241. TRUE); // Wait until available
  1242. Status = ElfpAccessCheckAndAudit(
  1243. L"EventLog", // SubSystemName
  1244. L"LogFile", // ObjectTypeName
  1245. Module->ModuleName, // ObjectName
  1246. LogIHandle, // Context handle - required?
  1247. Module->LogFile->Sd, // Security Descriptor
  1248. DesiredAccess, // Requested Access
  1249. NULL, // GENERIC_MAPPING
  1250. ForSecurityLog
  1251. );
  1252. RtlReleaseResource(&Module->LogFile->Resource);
  1253. if (NT_SUCCESS(Status))
  1254. {
  1255. LogIHandle->Atom = Module->ModuleAtom;
  1256. LogIHandle->NameLength = ModuleName->Length + sizeof(WCHAR);
  1257. RtlCopyMemory(LogIHandle->Name, ModuleName->Buffer, ModuleName->Length);
  1258. LogIHandle->Name[ModuleName->Length / sizeof(WCHAR)] = L'\0';
  1259. LogIHandle->MajorVersion = MajorVersion; // Store the version
  1260. LogIHandle->MinorVersion = MinorVersion; // of the client
  1261. //
  1262. // Initialize seek positions to zero.
  1263. //
  1264. LogIHandle->SeekRecordPos = 0;
  1265. LogIHandle->SeekBytePos = 0;
  1266. LogIHandle->dwNotifyRequests = 0;
  1267. //
  1268. // Link in this structure to the list of context handles
  1269. //
  1270. LogIHandle->Signature = ELF_CONTEXTHANDLE_SIGN; // DEBUG
  1271. LinkContextHandle (LogIHandle);
  1272. *LogHandle = LogIHandle; // Set return handle
  1273. Status = STATUS_SUCCESS; // Set return status
  1274. }
  1275. else
  1276. {
  1277. ELF_LOG1(TRACE,
  1278. "ElfpOpenELW: ElfpAccessCheckAndAudit failed %#x\n",
  1279. Status);
  1280. ElfpFreeBuffer(LogIHandle);
  1281. }
  1282. }
  1283. else
  1284. {
  1285. ELF_LOG0(ERROR,
  1286. "ElfpOpenELW: Unable to allocate LogIHandle\n");
  1287. Status = STATUS_NO_MEMORY;
  1288. }
  1289. return Status;
  1290. UNREFERENCED_PARAMETER(UNCServerName);
  1291. UNREFERENCED_PARAMETER(RegModuleName);
  1292. }
  1293. NTSTATUS
  1294. w_ElfrReadEL (
  1295. IN ULONG Flags, // ANSI or UNICODE
  1296. IN IELF_HANDLE LogHandle,
  1297. IN ULONG ReadFlags,
  1298. IN ULONG RecordNumber,
  1299. IN ULONG NumberOfBytesToRead,
  1300. IN PBYTE Buffer,
  1301. OUT PULONG NumberOfBytesRead,
  1302. OUT PULONG MinNumberOfBytesNeeded
  1303. )
  1304. /*++
  1305. Routine Description:
  1306. This is the worker for the ElfrReadEL APIs.
  1307. Arguments:
  1308. Same as ElfrReadELW API except that Flags contains an indication
  1309. of whether this is ANSI or UNICODE.
  1310. Return Value:
  1311. Same as the main API.
  1312. NOTES:
  1313. We assume that the client-side has validated the flags to ensure that
  1314. only one type of each bit is set. No checking is done at the server end.
  1315. --*/
  1316. {
  1317. NTSTATUS Status;
  1318. PLOGMODULE Module;
  1319. ELF_REQUEST_RECORD Request;
  1320. READ_PKT ReadPkt;
  1321. memset(&ReadPkt, 0, sizeof(ReadPkt));
  1322. //
  1323. // Check the handle before proceeding.
  1324. //
  1325. Status = VerifyElfHandle(LogHandle);
  1326. if (!NT_SUCCESS(Status))
  1327. {
  1328. ELF_LOG1(ERROR,
  1329. "w_ElfrReadEL: VerifyElfHandle failed %#x\n",
  1330. Status);
  1331. return Status;
  1332. }
  1333. //
  1334. // Ensure the caller has read access.
  1335. //
  1336. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_READ))
  1337. {
  1338. ELF_LOG0(ERROR,
  1339. "w_ElfrReadEL: LogHandle does not have read access\n");
  1340. return STATUS_ACCESS_DENIED;
  1341. }
  1342. //
  1343. // Verify additional arguments.
  1344. //
  1345. if (Buffer == NULL || !NumberOfBytesRead || !MinNumberOfBytesNeeded)
  1346. {
  1347. ELF_LOG1(ERROR,
  1348. "w_ElfrReadEL: %ws\n",
  1349. (Buffer == NULL ? L"Buffer is NULL" :
  1350. (!NumberOfBytesRead ? L"NumberOfBytesRead is 0" :
  1351. L"MinNumberOfBytesNeeded is 0")));
  1352. return STATUS_INVALID_PARAMETER;
  1353. }
  1354. //
  1355. // The ELF_HANDLE_INVALID_FOR_READ flag bit would be set if the
  1356. // file changed underneath this handle.
  1357. //
  1358. if (LogHandle->Flags & ELF_LOG_HANDLE_INVALID_FOR_READ)
  1359. {
  1360. // ELF_LOG0(ERROR,
  1361. // "w_ElfrReadEL: Logfile changed under this handle -- invalid for read\n");
  1362. return STATUS_EVENTLOG_FILE_CHANGED;
  1363. }
  1364. //
  1365. // This condition is TRUE iff a backup operator has opened the security
  1366. // log. In this case deny access, since backup operators are allowed
  1367. // only backup operation on the security log.
  1368. //
  1369. if (LogHandle->GrantedAccess & ELF_LOGFILE_BACKUP)
  1370. {
  1371. ELF_LOG0(ERROR,
  1372. "w_ElfrReadEL: Handle is a backup handle\n");
  1373. return STATUS_ACCESS_DENIED;
  1374. }
  1375. Request.Pkt.ReadPkt = &ReadPkt; // Set up read packet in request packet
  1376. //
  1377. // Find the matching module structure
  1378. //
  1379. Module = FindModuleStrucFromAtom (LogHandle->Atom);
  1380. //
  1381. // Only continue if the module was found
  1382. //
  1383. if (Module != NULL)
  1384. {
  1385. ELF_LOG1(TRACE,
  1386. "w_ElfrReadEL: Performing read on module %ws\n",
  1387. Module->ModuleName);
  1388. //
  1389. // Fill in the request packet
  1390. //
  1391. Request.Module = Module;
  1392. Request.Flags = 0;
  1393. Request.LogFile = Module->LogFile;
  1394. Request.Command = ELF_COMMAND_READ;
  1395. Request.Status = STATUS_SUCCESS;
  1396. Request.Pkt.ReadPkt->ContextHandle = LogHandle;
  1397. Request.Pkt.ReadPkt->MinimumBytesNeeded = *MinNumberOfBytesNeeded;
  1398. Request.Pkt.ReadPkt->BufferSize = NumberOfBytesToRead;
  1399. Request.Pkt.ReadPkt->Buffer = (PVOID)Buffer;
  1400. Request.Pkt.ReadPkt->ReadFlags = ReadFlags;
  1401. Request.Pkt.ReadPkt->RecordNumber = RecordNumber;
  1402. Request.Pkt.ReadPkt->Flags = Flags; // Indicate UNICODE or ANSI
  1403. //
  1404. // Pass along whether the last read was in a forward or backward
  1405. // direction (affects how we treat being at EOF). Then reset the
  1406. // bit in the handle depending on what this read is.
  1407. //
  1408. if (LogHandle->Flags & ELF_LOG_HANDLE_LAST_READ_FORWARD)
  1409. {
  1410. Request.Pkt.ReadPkt->Flags |= ELF_LAST_READ_FORWARD;
  1411. }
  1412. if (ReadFlags & EVENTLOG_FORWARDS_READ)
  1413. {
  1414. LogHandle->Flags |= ELF_LOG_HANDLE_LAST_READ_FORWARD;
  1415. }
  1416. else
  1417. {
  1418. LogHandle->Flags &= ~(ELF_LOG_HANDLE_LAST_READ_FORWARD);
  1419. }
  1420. //
  1421. // Perform the operation
  1422. //
  1423. ElfPerformRequest(&Request);
  1424. //
  1425. // Set up return values
  1426. //
  1427. *NumberOfBytesRead = Request.Pkt.ReadPkt->BytesRead;
  1428. *MinNumberOfBytesNeeded = Request.Pkt.ReadPkt->MinimumBytesNeeded;
  1429. Status = Request.Status;
  1430. }
  1431. else
  1432. {
  1433. ELF_LOG0(ERROR,
  1434. "w_ElfrReadEL: No module associated with atom in LogHandle\n");
  1435. Status = STATUS_INVALID_HANDLE;
  1436. //
  1437. // Set the NumberOfBytesNeeded to zero since there are no bytes to
  1438. // transfer.
  1439. //
  1440. *NumberOfBytesRead = 0;
  1441. *MinNumberOfBytesNeeded = 0;
  1442. }
  1443. return Status;
  1444. }
  1445. NTSTATUS
  1446. ElfrReadELW (
  1447. IN IELF_HANDLE LogHandle,
  1448. IN ULONG ReadFlags,
  1449. IN ULONG RecordNumber,
  1450. IN ULONG NumberOfBytesToRead,
  1451. IN PBYTE Buffer,
  1452. OUT PULONG NumberOfBytesRead,
  1453. OUT PULONG MinNumberOfBytesNeeded
  1454. )
  1455. /*++
  1456. Routine Description:
  1457. This is the RPC server entry point for the ElfrReadELW API.
  1458. Arguments:
  1459. Return Value:
  1460. Returns an NTSTATUS code, NumberOfBytesRead if the read was successful
  1461. and MinNumberOfBytesNeeded if the buffer was not big enough.
  1462. --*/
  1463. {
  1464. //
  1465. // Call the worker with the UNICODE flag.
  1466. // All arguments checked in w_ElfrReadEL.
  1467. //
  1468. return w_ElfrReadEL(ELF_IREAD_UNICODE,
  1469. LogHandle,
  1470. ReadFlags,
  1471. RecordNumber,
  1472. NumberOfBytesToRead,
  1473. Buffer,
  1474. NumberOfBytesRead,
  1475. MinNumberOfBytesNeeded);
  1476. }
  1477. NTSTATUS
  1478. ElfrReportEventW (
  1479. IN IELF_HANDLE LogHandle,
  1480. IN ULONG EventTime,
  1481. IN USHORT EventType,
  1482. IN USHORT EventCategory OPTIONAL,
  1483. IN ULONG EventID,
  1484. IN USHORT NumStrings,
  1485. IN ULONG DataSize,
  1486. IN PRPC_UNICODE_STRING ComputerName,
  1487. IN PRPC_SID UserSid,
  1488. IN PRPC_UNICODE_STRING Strings[],
  1489. IN PBYTE Data,
  1490. IN USHORT Flags,
  1491. IN OUT PULONG RecordNumber OPTIONAL,
  1492. IN OUT PULONG TimeWritten OPTIONAL
  1493. )
  1494. /*++
  1495. Routine Description:
  1496. This is the RPC server entry point for the ElfrReportEventW API.
  1497. Arguments:
  1498. Return Value:
  1499. Returns an NTSTATUS code.
  1500. --*/
  1501. {
  1502. NTSTATUS Status;
  1503. PLOGMODULE Module;
  1504. ELF_REQUEST_RECORD Request;
  1505. WRITE_PKT WritePkt;
  1506. ULONG RecordLength;
  1507. ULONG StringOffset, DataOffset;
  1508. ULONG StringsSize;
  1509. USHORT i;
  1510. USHORT iFirstString = 0;
  1511. PVOID EventBuffer;
  1512. PEVENTLOGRECORD EventLogRecord;
  1513. PWSTR ReplaceStrings, SrcString;
  1514. PBYTE BinaryData;
  1515. PUNICODE_STRING UComputerName;
  1516. PWSTR UModuleName;
  1517. ULONG PadSize;
  1518. ULONG UserSidLength = 0; // Init to zero
  1519. ULONG UserSidOffset;
  1520. ULONG ModuleNameLen, ComputerNameLen; // Length in bytes
  1521. ULONG zero = 0; // For pad bytes
  1522. LARGE_INTEGER Time;
  1523. ULONG LogTimeWritten;
  1524. //
  1525. // These will be for Security Auditing to use for paired events.
  1526. //
  1527. // UNREFERENCED_PARAMETER(RecordNumber);
  1528. // UNREFERENCED_PARAMETER(TimeWritten);
  1529. //
  1530. // Check the handle before proceeding.
  1531. //
  1532. Status = VerifyElfHandle(LogHandle);
  1533. if (!NT_SUCCESS(Status))
  1534. {
  1535. ELF_LOG1(ERROR,
  1536. "ElfrReportEventW: VerifyElfHandle failed %#x\n",
  1537. Status);
  1538. return Status;
  1539. }
  1540. //
  1541. // Insure the caller has write access.
  1542. //
  1543. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_WRITE))
  1544. {
  1545. ELF_LOG0(ERROR,
  1546. "ElfrReportEventW: LogHandle does not have write access\n");
  1547. return STATUS_ACCESS_DENIED;
  1548. }
  1549. //
  1550. // Verify additional arguments.
  1551. //
  1552. Status = VerifyUnicodeString(ComputerName);
  1553. if (!NT_SUCCESS(Status))
  1554. {
  1555. ELF_LOG1(ERROR,
  1556. "ElfrReportEventW: ComputerName is not a valid Unicode string %#x\n",
  1557. Status);
  1558. return Status;
  1559. }
  1560. if (Strings == NULL && NumStrings != 0)
  1561. {
  1562. ELF_LOG1(ERROR,
  1563. "ElfrReportEventW: Strings is NULL and NumStrings is non-zero (%d)\n",
  1564. NumStrings);
  1565. return STATUS_INVALID_PARAMETER;
  1566. }
  1567. //
  1568. // This condition is TRUE iff a backup operator has opened the security
  1569. // log. In this case deny access, since backup operators are allowed
  1570. // only backup operation on the security log.
  1571. //
  1572. if (LogHandle->GrantedAccess & ELF_LOGFILE_BACKUP)
  1573. {
  1574. ELF_LOG0(ERROR,
  1575. "ElfrReportEventW: Handle is a backup handle\n");
  1576. return STATUS_ACCESS_DENIED;
  1577. }
  1578. //
  1579. // Make sure the SID passed in is valid
  1580. //
  1581. if (ARGUMENT_PRESENT(UserSid))
  1582. {
  1583. if (!IsValidSid(UserSid))
  1584. {
  1585. ELF_LOG0(ERROR,
  1586. "ElfrReportEventW: UserSid is invalid\n");
  1587. return STATUS_INVALID_PARAMETER;
  1588. }
  1589. }
  1590. //
  1591. // Verify the string arguments
  1592. //
  1593. for (i = 0; i < NumStrings; i++ )
  1594. {
  1595. Status = VerifyUnicodeString(Strings[i]);
  1596. if (!NT_SUCCESS(Status))
  1597. {
  1598. ELF_LOG2(ERROR,
  1599. "ElfrReportEventW: String %d is not a valid Unicode string %#x\n",
  1600. i,
  1601. Status);
  1602. return STATUS_INVALID_PARAMETER;
  1603. }
  1604. }
  1605. //
  1606. // Can't write to a backup log
  1607. //
  1608. if (LogHandle->Flags & ELF_LOG_HANDLE_BACKUP_LOG)
  1609. {
  1610. ELF_LOG0(ERROR,
  1611. "ElfrReportEventW: Handle is for a backup log\n");
  1612. return STATUS_INVALID_HANDLE;
  1613. }
  1614. //
  1615. // Make sure they didn't pass in a null pointer for the data, but tell
  1616. // me there was something there (I still think RPC should protect me from
  1617. // this!)
  1618. //
  1619. if (!Data && DataSize != 0)
  1620. {
  1621. ELF_LOG1(ERROR,
  1622. "ElfrReportEventW: Data is NULL and DataSize is non-zero (%d)\n",
  1623. DataSize);
  1624. return STATUS_INVALID_PARAMETER;
  1625. }
  1626. UComputerName = (PUNICODE_STRING)ComputerName;
  1627. // special hack for auditing. For the special event, the source name is packed
  1628. // into the first string and the actual event id is packed into the second string
  1629. if(gElfSecurityHandle == LogHandle && EventID == 573)
  1630. {
  1631. if(NumStrings < 2)
  1632. {
  1633. ELF_LOG0(ERROR,
  1634. "ElfrReportEventW: Special security event had insufficient number of strings\n");
  1635. return STATUS_INVALID_PARAMETER;
  1636. }
  1637. iFirstString = 2;
  1638. UModuleName = (PWSTR) Strings[0]->Buffer;
  1639. EventID = _wtoi(Strings[1]->Buffer);
  1640. ELF_LOG2(TRACE,
  1641. "ElfrReportEventW: Special 3rd party audit event. Source is %ws and event ID is %d\n",
  1642. UModuleName,
  1643. EventID);
  1644. }
  1645. else
  1646. {
  1647. UModuleName = LogHandle->Name;
  1648. iFirstString = 0;
  1649. }
  1650. Request.Pkt.WritePkt = &WritePkt; // Set up write packet in request packet
  1651. Request.Flags = 0;
  1652. //
  1653. // Find the matching module structure
  1654. //
  1655. Module = FindModuleStrucFromAtom (LogHandle->Atom);
  1656. if (Module != NULL)
  1657. {
  1658. //
  1659. // Generate any additional information needed in the record.
  1660. //
  1661. // Info that we have Info to generate
  1662. // ----------------- ----------------
  1663. // Modulename UserSidLength
  1664. // EventType Length
  1665. // EventID StringOffset
  1666. // NumStrings DataOffset
  1667. // Strings PadBytes
  1668. // DataLength LogTimeWritten
  1669. // Data
  1670. // UserSidOffset
  1671. // UserSid
  1672. // ComputerName
  1673. // TimeGenerated
  1674. //
  1675. // LogTimeWritten
  1676. // We need to generate a time when the log is written. This
  1677. // gets written in the log so that we can use it to test the
  1678. // retention period when wrapping the file.
  1679. //
  1680. NtQuerySystemTime(&Time);
  1681. RtlTimeToSecondsSince1970(&Time,
  1682. &LogTimeWritten);
  1683. //
  1684. // USERSIDLENTGH
  1685. //
  1686. if (UserSid)
  1687. {
  1688. UserSidLength = RtlLengthSid((PSID)UserSid);
  1689. ELF_LOG1(TRACE,
  1690. "ElfrReportEventW: Length of sid is %d\n",
  1691. UserSidLength);
  1692. }
  1693. //
  1694. // USERSIDOFFSET
  1695. //
  1696. // Extract the lengths from the STRING structure, and take care of
  1697. // the trailing NULLs.
  1698. //
  1699. ModuleNameLen = (wcslen(UModuleName) + 1) * sizeof (WCHAR);
  1700. ComputerNameLen = UComputerName->Length + sizeof(WCHAR);
  1701. ELF_LOG1(TRACE,
  1702. "ElfrReportEventW: Module name length (bytes) is %d\n",
  1703. ModuleNameLen);
  1704. ELF_LOG1(TRACE,
  1705. "ElfrReportEventW: Computer name length (bytes) is %d\n",
  1706. UComputerName->Length + sizeof(WCHAR));
  1707. UserSidOffset = sizeof(EVENTLOGRECORD) + ModuleNameLen + ComputerNameLen;
  1708. UserSidOffset = ALIGN_UP_64(UserSidOffset, sizeof(PVOID));
  1709. //
  1710. // STRING OFFSET:
  1711. //
  1712. StringOffset = UserSidOffset + UserSidLength;
  1713. //
  1714. // Calculate the length of strings so that we can see how
  1715. // much space is needed for that.
  1716. //
  1717. StringsSize = 0;
  1718. for (i = iFirstString; i < NumStrings; i++)
  1719. {
  1720. ELF_LOG3(TRACE,
  1721. "ElfrReportEventW: Length (bytes) of string %d (%ws) is %d\n",
  1722. i,
  1723. Strings[i]->Buffer,
  1724. Strings[i]->Length + sizeof(WCHAR));
  1725. StringsSize += Strings[i]->Length + sizeof(WCHAR);
  1726. }
  1727. //
  1728. // DATA OFFSET:
  1729. //
  1730. DataOffset = StringOffset + StringsSize;
  1731. //
  1732. // Determine how big a buffer is needed for the eventlog record.
  1733. //
  1734. RecordLength = DataOffset
  1735. + DataSize
  1736. + sizeof(RecordLength); // Size excluding pad bytes
  1737. ELF_LOG1(TRACE,
  1738. "ElfrReportEventW: RecordLength (no pad bytes) is %d\n",
  1739. RecordLength);
  1740. //
  1741. // Determine how many pad bytes are needed to align to a DWORD
  1742. // boundary.
  1743. //
  1744. PadSize = sizeof(ULONG) - (RecordLength % sizeof(ULONG));
  1745. RecordLength += PadSize; // True size needed
  1746. ELF_LOG2(TRACE,
  1747. "ElfrReportEventW: RecordLength (with %d pad bytes) is %d\n",
  1748. PadSize,
  1749. RecordLength);
  1750. //
  1751. // Allocate the buffer for the Eventlog record
  1752. //
  1753. EventBuffer = ElfpAllocateBuffer(RecordLength);
  1754. if (EventBuffer != NULL)
  1755. {
  1756. //
  1757. // Fill up the event record
  1758. //
  1759. EventLogRecord = (PEVENTLOGRECORD)EventBuffer;
  1760. EventLogRecord->Length = RecordLength;
  1761. EventLogRecord->TimeGenerated = EventTime;
  1762. EventLogRecord->Reserved = ELF_LOG_FILE_SIGNATURE;
  1763. EventLogRecord->TimeWritten = LogTimeWritten;
  1764. EventLogRecord->EventID = EventID;
  1765. EventLogRecord->EventType = EventType;
  1766. EventLogRecord->EventCategory = EventCategory;
  1767. EventLogRecord->ReservedFlags = Flags;
  1768. EventLogRecord->ClosingRecordNumber = 0;
  1769. EventLogRecord->NumStrings = NumStrings;
  1770. EventLogRecord->StringOffset = StringOffset;
  1771. EventLogRecord->DataLength = DataSize;
  1772. EventLogRecord->DataOffset = DataOffset;
  1773. EventLogRecord->UserSidLength = UserSidLength;
  1774. EventLogRecord->UserSidOffset = UserSidOffset;
  1775. //
  1776. // Fill in the variable-length fields
  1777. //
  1778. //
  1779. // STRINGS
  1780. //
  1781. ReplaceStrings = (PWSTR)((ULONG_PTR)EventLogRecord + (ULONG)StringOffset);
  1782. for (i = iFirstString; i < NumStrings; i++)
  1783. {
  1784. SrcString = (PWSTR) Strings[i]->Buffer;
  1785. ELF_LOG1(TRACE,
  1786. "ElfrReportEventW: Copying string %d into record\n",
  1787. i);
  1788. RtlCopyMemory(ReplaceStrings, SrcString, Strings[i]->Length);
  1789. ReplaceStrings[Strings[i]->Length / sizeof(WCHAR)] = L'\0';
  1790. ReplaceStrings = (PWSTR)((PBYTE) ReplaceStrings
  1791. + Strings[i]->Length
  1792. + sizeof(WCHAR));
  1793. }
  1794. //
  1795. // MODULENAME
  1796. //
  1797. BinaryData = (PBYTE) EventLogRecord + sizeof(EVENTLOGRECORD);
  1798. RtlCopyMemory(BinaryData,
  1799. UModuleName,
  1800. ModuleNameLen);
  1801. ELF_LOG1(TRACE,
  1802. "ElfrReportEventW: Copying module name (%ws) into record\n",
  1803. UModuleName);
  1804. //
  1805. // COMPUTERNAME
  1806. //
  1807. ReplaceStrings = (LPWSTR) (BinaryData + ModuleNameLen);
  1808. RtlCopyMemory(ReplaceStrings,
  1809. UComputerName->Buffer,
  1810. UComputerName->Length);
  1811. ReplaceStrings[UComputerName->Length / sizeof(WCHAR)] = L'\0';
  1812. ELF_LOG1(TRACE,
  1813. "ElfrReportEventW: Copying computer name (%ws) into record\n",
  1814. ReplaceStrings);
  1815. //
  1816. // USERSID
  1817. //
  1818. BinaryData = ((PBYTE) EventLogRecord) + UserSidOffset;
  1819. RtlCopyMemory(BinaryData,
  1820. UserSid,
  1821. UserSidLength);
  1822. //
  1823. // BINARY DATA
  1824. //
  1825. BinaryData = (PBYTE) ((ULONG_PTR)EventLogRecord + DataOffset);
  1826. if (Data)
  1827. {
  1828. RtlCopyMemory(BinaryData,
  1829. Data,
  1830. DataSize);
  1831. }
  1832. //
  1833. // PAD - Fill with zeros
  1834. //
  1835. BinaryData = (PBYTE) ((ULONG_PTR)BinaryData + DataSize);
  1836. RtlCopyMemory(BinaryData,
  1837. &zero,
  1838. PadSize);
  1839. //
  1840. // LENGTH at end of record
  1841. //
  1842. BinaryData = (PBYTE)((ULONG_PTR) BinaryData + PadSize); // Point after pad bytes
  1843. ((PULONG) BinaryData)[0] = RecordLength;
  1844. //
  1845. // Make sure we are in the right place
  1846. //
  1847. ASSERT ((ULONG_PTR)BinaryData
  1848. == (RecordLength + (ULONG_PTR)EventLogRecord) - sizeof(ULONG));
  1849. //
  1850. // Set up request packet.
  1851. // Link event log record into the request structure.
  1852. //
  1853. Request.Module = Module;
  1854. Request.LogFile = Request.Module->LogFile;
  1855. Request.Command = ELF_COMMAND_WRITE;
  1856. Request.Pkt.WritePkt->Buffer = (PVOID)EventBuffer;
  1857. Request.Pkt.WritePkt->Datasize = RecordLength;
  1858. //
  1859. // Perform the operation
  1860. //
  1861. ElfPerformRequest( &Request );
  1862. //
  1863. // Save the event for replication if this node is part of a cluster
  1864. //
  1865. ElfpSaveEventBuffer( Module, EventBuffer, RecordLength );
  1866. Status = Request.Status; // Set status of WRITE
  1867. }
  1868. else
  1869. {
  1870. ELF_LOG0(ERROR,
  1871. "ElfrReportEventW: Unable to allocate EventLogRecord\n");
  1872. Status = STATUS_NO_MEMORY;
  1873. }
  1874. }
  1875. else
  1876. {
  1877. ELF_LOG0(ERROR,
  1878. "ElfrReportEventW: No module associated with atom in LogHandle\n");
  1879. Status = STATUS_INVALID_HANDLE;
  1880. }
  1881. return Status;
  1882. }
  1883. //
  1884. // ANSI APIs
  1885. //
  1886. NTSTATUS
  1887. ElfrClearELFA (
  1888. IN IELF_HANDLE LogHandle,
  1889. IN PRPC_STRING BackupFileName
  1890. )
  1891. /*++
  1892. Routine Description:
  1893. This is the RPC server entry point for the ElfrClearELFA API.
  1894. Arguments:
  1895. LogHandle - The context-handle for this module's call.
  1896. BackupFileName - Name of the file to back up the current log file.
  1897. NULL implies not to back up the file.
  1898. Return Value:
  1899. Returns an NTSTATUS code.
  1900. --*/
  1901. {
  1902. NTSTATUS Status;
  1903. UNICODE_STRING BackupFileNameU;
  1904. //
  1905. // Check the handle before proceeding.
  1906. //
  1907. Status = VerifyElfHandle(LogHandle);
  1908. if (!NT_SUCCESS(Status))
  1909. {
  1910. ELF_LOG1(ERROR,
  1911. "ElfrClearELFA: VerifyElfHandle failed %#x\n",
  1912. Status);
  1913. return Status;
  1914. }
  1915. //
  1916. // Ensure the caller has clear access.
  1917. //
  1918. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_CLEAR))
  1919. {
  1920. ELF_LOG0(ERROR,
  1921. "ElfrClearELFA: Handle doesn't have clear access\n");
  1922. return STATUS_ACCESS_DENIED;
  1923. }
  1924. //
  1925. // Verify additional arguments.
  1926. //
  1927. Status = VerifyAnsiString((PANSI_STRING) BackupFileName);
  1928. if (!NT_SUCCESS(Status))
  1929. {
  1930. ELF_LOG1(ERROR,
  1931. "ElfrClearELFA: BackupFileName is not a valid Ansi string %#x\n",
  1932. Status);
  1933. return Status;
  1934. }
  1935. //
  1936. // Convert the BackupFileName to a UNICODE STRING and call the
  1937. // UNICODE API to do the work.
  1938. //
  1939. Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING) &BackupFileNameU,
  1940. (PANSI_STRING) BackupFileName,
  1941. TRUE);
  1942. if (NT_SUCCESS(Status))
  1943. {
  1944. Status = ElfrClearELFW(LogHandle,
  1945. (PRPC_UNICODE_STRING) &BackupFileNameU);
  1946. RtlFreeUnicodeString (&BackupFileNameU);
  1947. }
  1948. else
  1949. {
  1950. ELF_LOG2(ERROR,
  1951. "ElfrClearELFA: Conversion of Ansi string %s to Unicode failed %#x\n",
  1952. BackupFileName->Buffer,
  1953. Status);
  1954. }
  1955. return Status;
  1956. }
  1957. NTSTATUS
  1958. ElfrBackupELFA (
  1959. IN IELF_HANDLE LogHandle,
  1960. IN PRPC_STRING BackupFileName
  1961. )
  1962. /*++
  1963. Routine Description:
  1964. This is the RPC server entry point for the ElfrBackupELFA API.
  1965. Arguments:
  1966. LogHandle - The context-handle for this module's call.
  1967. BackupFileName - Name of the file to back up the current log file.
  1968. Return Value:
  1969. Returns an NTSTATUS code.
  1970. --*/
  1971. {
  1972. NTSTATUS Status;
  1973. UNICODE_STRING BackupFileNameU;
  1974. //
  1975. // Check the handle before proceeding.
  1976. //
  1977. Status = VerifyElfHandle(LogHandle);
  1978. if (!NT_SUCCESS(Status))
  1979. {
  1980. ELF_LOG1(ERROR,
  1981. "ElfrBackupELFA: VerifyElfHandle failed %#x\n",
  1982. Status);
  1983. return Status;
  1984. }
  1985. //
  1986. // Ensure the caller has backup access.
  1987. //
  1988. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_BACKUP))
  1989. {
  1990. ELF_LOG0(ERROR,
  1991. "ElfrBackupELFA: Handle does not have backup access\n");
  1992. return STATUS_ACCESS_DENIED;
  1993. }
  1994. //
  1995. // Verify additional arguments.
  1996. //
  1997. Status = VerifyAnsiString((PANSI_STRING) BackupFileName);
  1998. if (!NT_SUCCESS(Status))
  1999. {
  2000. ELF_LOG1(ERROR,
  2001. "ElfrBackupELFA: BackupFileName is not a valid Ansi string %#x\n",
  2002. Status);
  2003. return Status;
  2004. }
  2005. //
  2006. // Convert the BackupFileName to a UNICODE STRING and call the
  2007. // UNICODE API to do the work.
  2008. //
  2009. Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING) &BackupFileNameU,
  2010. (PANSI_STRING) BackupFileName,
  2011. TRUE);
  2012. if (NT_SUCCESS(Status))
  2013. {
  2014. Status = ElfrBackupELFW(LogHandle,
  2015. (PRPC_UNICODE_STRING) &BackupFileNameU);
  2016. RtlFreeUnicodeString(&BackupFileNameU);
  2017. }
  2018. else
  2019. {
  2020. ELF_LOG2(ERROR,
  2021. "ElfrBackupELFA: Conversion of Ansi string %s to Unicode failed %#x\n",
  2022. BackupFileName->Buffer,
  2023. Status);
  2024. }
  2025. return Status;
  2026. }
  2027. NTSTATUS
  2028. ElfrRegisterEventSourceA (
  2029. IN EVENTLOG_HANDLE_A UNCServerName,
  2030. IN PRPC_STRING ModuleName,
  2031. IN PRPC_STRING RegModuleName,
  2032. IN ULONG MajorVersion,
  2033. IN ULONG MinorVersion,
  2034. OUT PIELF_HANDLE LogHandle
  2035. )
  2036. /*++
  2037. Routine Description:
  2038. This is the RPC server entry point for the ElfrRegisterEventSourceA API.
  2039. This routine allocates a structure for the context handle, finds
  2040. the matching module name and fills in the data. It returns the
  2041. pointer to the handle structure.
  2042. Arguments:
  2043. UNCServerName - Not used.
  2044. ModuleName - Name of the module that is making this call.
  2045. RegModuleName - Not used.
  2046. MajorVersion/MinorVersion - The version of the client.
  2047. LogHandle - Pointer to the place where the pointer to the
  2048. context handle structure will be placed.
  2049. Return Value:
  2050. Returns an NTSTATUS code and, if no error, a "handle".
  2051. Note:
  2052. For now, just call ElfrOpenELA.
  2053. --*/
  2054. {
  2055. NTSTATUS Status;
  2056. PLOGMODULE Module;
  2057. UNICODE_STRING ModuleNameU;
  2058. //
  2059. // Check arguments.
  2060. //
  2061. // LogHandle check in ElfpOpenELA.
  2062. //
  2063. Status = VerifyAnsiString((PANSI_STRING) ModuleName);
  2064. if (!NT_SUCCESS(Status))
  2065. {
  2066. ELF_LOG1(ERROR,
  2067. "ElfrRegisterEventSourceA: ModuleName is not a valid Ansi string %#x\n",
  2068. Status);
  2069. return Status;
  2070. }
  2071. Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING) &ModuleNameU,
  2072. (PANSI_STRING) ModuleName,
  2073. TRUE);
  2074. if (!NT_SUCCESS(Status))
  2075. {
  2076. ELF_LOG2(ERROR,
  2077. "ElfrRegisterEventSourceA: Conversion of Ansi string %s "
  2078. "to Unicode failed %#x\n",
  2079. ModuleName->Buffer,
  2080. Status);
  2081. return Status;
  2082. }
  2083. Module = GetModuleStruc((PUNICODE_STRING) &ModuleNameU);
  2084. RtlFreeUnicodeString(&ModuleNameU);
  2085. return ElfpOpenELA(UNCServerName,
  2086. ModuleName,
  2087. RegModuleName,
  2088. MajorVersion,
  2089. MinorVersion,
  2090. LogHandle,
  2091. ELF_LOGFILE_WRITE);
  2092. }
  2093. NTSTATUS
  2094. ElfrOpenELA (
  2095. IN EVENTLOG_HANDLE_A UNCServerName,
  2096. IN PRPC_STRING ModuleName,
  2097. IN PRPC_STRING RegModuleName,
  2098. IN ULONG MajorVersion,
  2099. IN ULONG MinorVersion,
  2100. OUT PIELF_HANDLE LogHandle
  2101. )
  2102. /*++
  2103. Routine Description:
  2104. This is the RPC server entry point for the ElfrOpenEL API.
  2105. This routine allocates a structure for the context handle, finds
  2106. the matching module name and fills in the data. It returns the
  2107. pointer to the handle structure.
  2108. Arguments:
  2109. UNCServerName - Not used.
  2110. ModuleName - Name of the module that is making this call.
  2111. RegModuleName - Name of module to use to determine the log file.
  2112. MajorVersion/MinorVersion - The version of the client.
  2113. LogHandle - Pointer to the place where the pointer to the
  2114. context handle structure will be placed.
  2115. Return Value:
  2116. Returns an NTSTATUS code and, if no error, a "handle".
  2117. --*/
  2118. {
  2119. //
  2120. // All arguments checked in ElfpOpenELA.
  2121. //
  2122. return ElfpOpenELA(UNCServerName,
  2123. ModuleName,
  2124. RegModuleName,
  2125. MajorVersion,
  2126. MinorVersion,
  2127. LogHandle,
  2128. ELF_LOGFILE_READ);
  2129. }
  2130. NTSTATUS
  2131. ElfpOpenELA (
  2132. IN EVENTLOG_HANDLE_A UNCServerName,
  2133. IN PRPC_STRING ModuleName,
  2134. IN PRPC_STRING RegModuleName,
  2135. IN ULONG MajorVersion,
  2136. IN ULONG MinorVersion,
  2137. OUT PIELF_HANDLE LogHandle,
  2138. IN ULONG DesiredAccess
  2139. )
  2140. /*++
  2141. Routine Description:
  2142. Looks alot loke ElfrOpenELA, only this also takes a DesiredAccess parameter.
  2143. Arguments:
  2144. UNCServerName - Not used.
  2145. ModuleName - Name of the module that is making this call.
  2146. RegModuleName - Name of module to use to determine the log file.
  2147. MajorVersion/MinorVersion - The version of the client.
  2148. LogHandle - Pointer to the place where the pointer to the
  2149. context handle structure will be placed.
  2150. Return Value:
  2151. Returns an NTSTATUS code and, if no error, a "handle".
  2152. --*/
  2153. {
  2154. NTSTATUS Status;
  2155. UNICODE_STRING ModuleNameU;
  2156. //
  2157. // Check arguments.
  2158. //
  2159. Status = VerifyAnsiString((PANSI_STRING) ModuleName);
  2160. if (!NT_SUCCESS(Status))
  2161. {
  2162. ELF_LOG1(ERROR,
  2163. "ElfpOpenELA: ModuleName is not a valid Ansi string %#x\n",
  2164. Status);
  2165. return Status;
  2166. }
  2167. if (LogHandle == NULL)
  2168. {
  2169. ELF_LOG0(ERROR,
  2170. "ElfpOpenELA: LogHandle is NULL\n");
  2171. return STATUS_INVALID_PARAMETER;
  2172. }
  2173. //
  2174. // Convert the ModuleName and RegModulename to UNICODE STRINGs and call
  2175. // the UNICODE API to do the work.
  2176. //
  2177. Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING) &ModuleNameU,
  2178. (PANSI_STRING) ModuleName,
  2179. TRUE);
  2180. if (NT_SUCCESS(Status))
  2181. {
  2182. //
  2183. // We *KNOW* that the UNCServerName is not used
  2184. // by ElfpOpenELW so we save ourselves some work
  2185. // and just pass in a NULL.
  2186. //
  2187. Status = ElfpOpenELW((EVENTLOG_HANDLE_W) NULL,
  2188. (PRPC_UNICODE_STRING) &ModuleNameU,
  2189. NULL,
  2190. MajorVersion,
  2191. MinorVersion,
  2192. LogHandle,
  2193. DesiredAccess);
  2194. RtlFreeUnicodeString(&ModuleNameU);
  2195. }
  2196. else
  2197. {
  2198. ELF_LOG2(ERROR,
  2199. "ElfpOpenELA: Conversion of Ansi string %s to Unicode failed %#x\n",
  2200. ModuleName->Buffer,
  2201. Status);
  2202. }
  2203. return (Status);
  2204. UNREFERENCED_PARAMETER(UNCServerName);
  2205. }
  2206. NTSTATUS
  2207. ElfrOpenBELA (
  2208. IN EVENTLOG_HANDLE_A UNCServerName,
  2209. IN PRPC_STRING FileName,
  2210. IN ULONG MajorVersion,
  2211. IN ULONG MinorVersion,
  2212. OUT PIELF_HANDLE LogHandle
  2213. )
  2214. /*++
  2215. Routine Description:
  2216. This is the RPC server entry point for the ElfrOpenBEL API.
  2217. This routine allocates a structure for the context handle, finds
  2218. the matching module name and fills in the data. It returns the
  2219. pointer to the handle structure.
  2220. Arguments:
  2221. UNCServerName - Not used.
  2222. FileName - Filename of the logfile
  2223. MajorVersion/MinorVersion - The version of the client.
  2224. LogHandle - Pointer to the place where the pointer to the
  2225. context handle structure will be placed.
  2226. Return Value:
  2227. Returns an NTSTATUS code and, if no error, a "handle".
  2228. --*/
  2229. {
  2230. NTSTATUS Status;
  2231. UNICODE_STRING FileNameU;
  2232. //
  2233. // Check arguments.
  2234. //
  2235. Status = VerifyAnsiString((PANSI_STRING) FileName);
  2236. if (!NT_SUCCESS(Status))
  2237. {
  2238. ELF_LOG1(ERROR,
  2239. "ElfrOpenBELA: FileName is not a valid Ansi string %#x\n",
  2240. Status);
  2241. return Status;
  2242. }
  2243. //
  2244. // A filename must be specified.
  2245. //
  2246. if (FileName->Length == 0)
  2247. {
  2248. ELF_LOG0(ERROR,
  2249. "ElfrOpenBELA: Filename length is 0\n");
  2250. return STATUS_INVALID_PARAMETER;
  2251. }
  2252. if (LogHandle == NULL)
  2253. {
  2254. ELF_LOG0(ERROR,
  2255. "ElfrOpenBELA: LogHandle is NULL\n");
  2256. return STATUS_INVALID_PARAMETER;
  2257. }
  2258. //
  2259. // Convert the FileName to a UNICODE STRINGs and call
  2260. // the UNICODE API to do the work.
  2261. //
  2262. Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING) &FileNameU,
  2263. (PANSI_STRING) FileName,
  2264. TRUE);
  2265. if (NT_SUCCESS(Status))
  2266. {
  2267. //
  2268. // We *KNOW* that the UNCServerName is not used
  2269. // by ElfrOpenELW so we save ourselves some work
  2270. // and just pass in a NULL.
  2271. //
  2272. Status = ElfrOpenBELW ((EVENTLOG_HANDLE_W) NULL,
  2273. (PRPC_UNICODE_STRING) &FileNameU,
  2274. MajorVersion,
  2275. MinorVersion,
  2276. LogHandle);
  2277. RtlFreeUnicodeString(&FileNameU);
  2278. }
  2279. else
  2280. {
  2281. ELF_LOG2(ERROR,
  2282. "ElfrOpenBELA: Error converting Ansi string %s to Unicode %#x\n",
  2283. FileName->Buffer,
  2284. Status);
  2285. }
  2286. return Status;
  2287. UNREFERENCED_PARAMETER(UNCServerName);
  2288. }
  2289. NTSTATUS
  2290. ElfrReadELA (
  2291. IN IELF_HANDLE LogHandle,
  2292. IN ULONG ReadFlags,
  2293. IN ULONG RecordNumber,
  2294. IN ULONG NumberOfBytesToRead,
  2295. IN PBYTE Buffer,
  2296. OUT PULONG NumberOfBytesRead,
  2297. OUT PULONG MinNumberOfBytesNeeded
  2298. )
  2299. /*++
  2300. Routine Description:
  2301. This is the RPC server entry point for the ElfrReadEL API.
  2302. Arguments:
  2303. Return Value:
  2304. Returns an NTSTATUS code, NumberOfBytesRead if the read was successful
  2305. and MinNumberOfBytesNeeded if the buffer was not big enough.
  2306. --*/
  2307. {
  2308. //
  2309. // Call the worker with the ANSI flag.
  2310. // All arguments checked in w_ElfrReadEL.
  2311. //
  2312. return w_ElfrReadEL(ELF_IREAD_ANSI,
  2313. LogHandle,
  2314. ReadFlags,
  2315. RecordNumber,
  2316. NumberOfBytesToRead,
  2317. Buffer,
  2318. NumberOfBytesRead,
  2319. MinNumberOfBytesNeeded);
  2320. }
  2321. NTSTATUS
  2322. ConvertStringArrayToUnicode (
  2323. PUNICODE_STRING *pUStringArray,
  2324. PANSI_STRING *Strings,
  2325. USHORT NumStrings
  2326. )
  2327. /*++
  2328. Routine Description:
  2329. This routine takes an array of PANSI_STRINGs and generates an array of
  2330. PUNICODE_STRINGs. The destination array has already been allocated
  2331. by the caller, but the structures for the UNICODE_STRINGs will need
  2332. to be allocated by this routine.
  2333. Arguments:
  2334. pUStringArray - Array of PUNICODE_STRINGs.
  2335. Strings - Array of PANSI_STRINGs.
  2336. NumStrings - Number of elements in the arrays.
  2337. Return Value:
  2338. Returns an NTSTATUS code.
  2339. --*/
  2340. {
  2341. NTSTATUS Status = STATUS_SUCCESS;
  2342. USHORT i;
  2343. //
  2344. // For each string passed in, allocate a UNICODE_STRING buffer
  2345. // and set it to the UNICODE equivalent of the string passed in.
  2346. //
  2347. for (i = 0; i < NumStrings; i++)
  2348. {
  2349. if (Strings[i])
  2350. {
  2351. Status = VerifyAnsiString(Strings[i]);
  2352. if (!NT_SUCCESS(Status))
  2353. {
  2354. ELF_LOG2(ERROR,
  2355. "ConvertStringArrayToUnicode: String %d is not "
  2356. "a valid Ansi string %#x\n",
  2357. i,
  2358. Status);
  2359. break;
  2360. }
  2361. pUStringArray[i] = ElfpAllocateBuffer(sizeof(UNICODE_STRING));
  2362. if (pUStringArray[i])
  2363. {
  2364. pUStringArray[i]->Buffer = NULL;
  2365. Status = RtlAnsiStringToUnicodeString(pUStringArray[i],
  2366. (PANSI_STRING) Strings[i],
  2367. TRUE);
  2368. if (!NT_SUCCESS(Status))
  2369. {
  2370. ELF_LOG2(ERROR,
  2371. "ConvertStringArrayToUnicode: Conversion of Ansi string "
  2372. "%s to Unicode failed %#x\n",
  2373. Strings[i]->Buffer,
  2374. Status);
  2375. }
  2376. }
  2377. else
  2378. {
  2379. ELF_LOG2(ERROR,
  2380. "ConvertStringArrayToUnicode: Unable to allocate memory for "
  2381. "Unicode string %d (Ansi string %s)\n",
  2382. i,
  2383. Strings[i]->Buffer);
  2384. Status = STATUS_NO_MEMORY;
  2385. }
  2386. }
  2387. else
  2388. {
  2389. pUStringArray[i] = NULL;
  2390. }
  2391. if (!NT_SUCCESS(Status))
  2392. {
  2393. break; // Jump out of loop and return status
  2394. }
  2395. }
  2396. //
  2397. // Free any allocations on failure.
  2398. //
  2399. if (!NT_SUCCESS(Status))
  2400. {
  2401. ELF_LOG1(ERROR,
  2402. "ConvertStringArrayToUnicode: Function failed %#x\n",
  2403. Status);
  2404. FreePUStringArray(pUStringArray, (USHORT)(i + 1));
  2405. }
  2406. return Status;
  2407. }
  2408. VOID
  2409. FreePUStringArray (
  2410. PUNICODE_STRING *pUStringArray,
  2411. USHORT NumStrings
  2412. )
  2413. /*++
  2414. Routine Description:
  2415. This routine takes the PUNICODE_STRING array that was filled in by
  2416. ConvertStringArrayToUnicode and frees the buffer portion of
  2417. each unicode string and then the UNICODE structure itseld. It handles
  2418. the case where the array may not have been filled completely due
  2419. to insufficient memory.
  2420. Arguments:
  2421. pUStringArray - Array of PUNICODE_STRINGs.
  2422. NumStrings - Number of elements in the array.
  2423. Return Value:
  2424. NONE.
  2425. --*/
  2426. {
  2427. USHORT i;
  2428. for (i = 0; i < NumStrings; i++)
  2429. {
  2430. if (pUStringArray[i])
  2431. {
  2432. if (pUStringArray[i]->Buffer)
  2433. {
  2434. //
  2435. // Free the string buffer
  2436. //
  2437. RtlFreeUnicodeString(pUStringArray[i]);
  2438. }
  2439. //
  2440. // Free the UNICODE_STRING itself -- this may be allocated
  2441. // even if the string buffer isn't (if RtlAnsiStringToUnicodeString
  2442. // failed in the ConvertStringArrayToUnicode call)
  2443. //
  2444. ElfpFreeBuffer(pUStringArray[i]);
  2445. pUStringArray[i] = NULL;
  2446. }
  2447. }
  2448. }
  2449. NTSTATUS
  2450. ElfrReportEventA (
  2451. IN IELF_HANDLE LogHandle,
  2452. IN ULONG Time,
  2453. IN USHORT EventType,
  2454. IN USHORT EventCategory OPTIONAL,
  2455. IN ULONG EventID,
  2456. IN USHORT NumStrings,
  2457. IN ULONG DataSize,
  2458. IN PRPC_STRING ComputerName,
  2459. IN PRPC_SID UserSid,
  2460. IN PRPC_STRING Strings[],
  2461. IN PBYTE Data,
  2462. IN USHORT Flags,
  2463. IN OUT PULONG RecordNumber OPTIONAL,
  2464. IN OUT PULONG TimeWritten OPTIONAL
  2465. )
  2466. /*++
  2467. Routine Description:
  2468. This is the RPC server entry point for the ElfrReportEventA API.
  2469. Arguments:
  2470. Return Value:
  2471. Returns an NTSTATUS code.
  2472. --*/
  2473. {
  2474. NTSTATUS Status;
  2475. UNICODE_STRING ComputerNameU;
  2476. PUNICODE_STRING *pUStringArray = NULL;
  2477. //
  2478. // Check the handle before proceeding.
  2479. //
  2480. Status = VerifyElfHandle(LogHandle);
  2481. if (!NT_SUCCESS(Status))
  2482. {
  2483. ELF_LOG1(ERROR,
  2484. "ElfrReportEventA: VerifyElfHandle failed %#x\n",
  2485. Status);
  2486. return Status;
  2487. }
  2488. //
  2489. // Ensure the caller has write access.
  2490. //
  2491. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_WRITE))
  2492. {
  2493. ELF_LOG0(ERROR,
  2494. "ElfrReportEventA: Handle doesn't have write access\n");
  2495. return STATUS_ACCESS_DENIED;
  2496. }
  2497. //
  2498. // Verify additional arguments.
  2499. //
  2500. Status = VerifyAnsiString((PANSI_STRING) ComputerName);
  2501. if (!NT_SUCCESS(Status))
  2502. {
  2503. ELF_LOG1(ERROR,
  2504. "ElfrReportEventA: ComputerName is not a valid Ansi string %#x\n",
  2505. Status);
  2506. return Status;
  2507. }
  2508. if (Strings == NULL && NumStrings != 0)
  2509. {
  2510. ELF_LOG1(ERROR,
  2511. "ElfrReportEventA: Strings is NULL and NumStrings is non-zero (%d)\n",
  2512. NumStrings);
  2513. return STATUS_INVALID_PARAMETER;
  2514. }
  2515. //
  2516. // Convert the ComputerName to a UNICODE STRING and call the
  2517. // UNICODE API.
  2518. //
  2519. Status = RtlAnsiStringToUnicodeString((PUNICODE_STRING) &ComputerNameU,
  2520. (PANSI_STRING) ComputerName,
  2521. TRUE);
  2522. if (NT_SUCCESS(Status))
  2523. {
  2524. if (NumStrings)
  2525. {
  2526. pUStringArray = ElfpAllocateBuffer(NumStrings * sizeof(PUNICODE_STRING));
  2527. if (pUStringArray)
  2528. {
  2529. //
  2530. // Convert the array of STRINGs to an array of UNICODE-STRINGs
  2531. // before calling the unicode API.
  2532. // We can just use the array of Strings passed in since we
  2533. // don't need to use it anywhere else.
  2534. //
  2535. Status = ConvertStringArrayToUnicode(pUStringArray,
  2536. (PANSI_STRING *) Strings,
  2537. NumStrings);
  2538. }
  2539. else
  2540. {
  2541. ELF_LOG0(ERROR,
  2542. "ElfrReportEventA: Unable to allocate pUStringArray\n");
  2543. Status = STATUS_NO_MEMORY;
  2544. }
  2545. }
  2546. if (NT_SUCCESS(Status))
  2547. {
  2548. Status = ElfrReportEventW(LogHandle,
  2549. Time,
  2550. EventType,
  2551. EventCategory,
  2552. EventID,
  2553. NumStrings,
  2554. DataSize,
  2555. (PRPC_UNICODE_STRING) &ComputerNameU,
  2556. UserSid,
  2557. (PRPC_UNICODE_STRING*) pUStringArray,
  2558. Data,
  2559. Flags, // Flags | paired event
  2560. RecordNumber, // RecordNumber | support. not in
  2561. TimeWritten); // TimeWritten | product 1
  2562. FreePUStringArray(pUStringArray, NumStrings);
  2563. }
  2564. RtlFreeUnicodeString(&ComputerNameU);
  2565. }
  2566. else
  2567. {
  2568. ELF_LOG2(ERROR,
  2569. "ElfrReportEventA: Conversion of Ansi string %s to Unicode failed %#X\n",
  2570. ComputerName->Buffer,
  2571. Status);
  2572. }
  2573. ElfpFreeBuffer(pUStringArray);
  2574. return Status;
  2575. }
  2576. NTSTATUS
  2577. VerifyElfHandle(
  2578. IN IELF_HANDLE LogHandle
  2579. )
  2580. /*++
  2581. Routine Description:
  2582. Verify the handle via its DWORD signature.
  2583. Arguments:
  2584. LogHandle - Handle to verify.
  2585. Return Value:
  2586. STATUS_SUCCESS - Presumably valid handle.
  2587. STATUS_INVALID_HANDLE - Invalid handle.
  2588. --*/
  2589. {
  2590. NTSTATUS Status;
  2591. if (LogHandle != NULL)
  2592. {
  2593. try
  2594. {
  2595. if (LogHandle->Signature == ELF_CONTEXTHANDLE_SIGN)
  2596. {
  2597. Status = STATUS_SUCCESS;
  2598. }
  2599. else
  2600. {
  2601. ELF_LOG2(ERROR,
  2602. "VerifyElfHandle: Incorrect LogHandle signature %#x "
  2603. "(should be %#x)\n",
  2604. LogHandle->Signature,
  2605. ELF_CONTEXTHANDLE_SIGN);
  2606. Status = STATUS_INVALID_HANDLE;
  2607. }
  2608. }
  2609. except(EXCEPTION_EXECUTE_HANDLER)
  2610. {
  2611. ELF_LOG1(ERROR,
  2612. "VerifyElfHandle: Exception %#x caught while probing LogHandle\n",
  2613. GetExceptionCode());
  2614. Status = STATUS_INVALID_HANDLE;
  2615. }
  2616. }
  2617. else
  2618. {
  2619. ELF_LOG0(ERROR,
  2620. "VerifyElfHandle: LogHandle is NULL\n");
  2621. Status = STATUS_INVALID_HANDLE;
  2622. }
  2623. return Status;
  2624. }
  2625. ULONG
  2626. Safewcslen(
  2627. UNALIGNED WCHAR *p,
  2628. LONG MaxLength
  2629. )
  2630. /*++
  2631. Safewcslen - Strlen that won't exceed MaxLength
  2632. Routine Description:
  2633. This routine is called to determine the size of a UNICODE_STRING
  2634. Arguments:
  2635. p - The string to count.
  2636. MaxLength - The maximum length to look at.
  2637. Return Value:
  2638. Number of bytes in the string (or MaxLength)
  2639. --*/
  2640. {
  2641. ULONG Count = 0;
  2642. if (MaxLength && p)
  2643. {
  2644. while (MaxLength > 1 && *p++ != UNICODE_NULL)
  2645. {
  2646. MaxLength -= sizeof(WCHAR);
  2647. Count += sizeof(WCHAR);
  2648. }
  2649. }
  2650. return Count;
  2651. }
  2652. ULONG
  2653. Safestrlen(
  2654. UNALIGNED char *p,
  2655. LONG MaxLength
  2656. )
  2657. /*++
  2658. Safestrlen - Strlen that won't exceed MaxLength
  2659. Routine Description:
  2660. This routine is called to determine the length of an ANSI_STRING
  2661. Arguments:
  2662. p - The string to count.
  2663. MaxLength - The maximum length to look at.
  2664. Return Value:
  2665. Number of chars in the string (or MaxLength)
  2666. --*/
  2667. {
  2668. ULONG Count = 0;
  2669. if (p)
  2670. {
  2671. while (MaxLength > 0 && *p++ != '\0')
  2672. {
  2673. MaxLength--;
  2674. Count++;
  2675. }
  2676. }
  2677. return Count;
  2678. }
  2679. NTSTATUS
  2680. VerifyUnicodeString(
  2681. IN PUNICODE_STRING pUString
  2682. )
  2683. /*++
  2684. Routine Description:
  2685. Verify the unicode string. The string is invalid if:
  2686. The UNICODE_STRING structure ptr is NULL.
  2687. The MaximumLength field is invalid (too small).
  2688. The Length field is incorrect.
  2689. Arguments:
  2690. pUString - String to verify.
  2691. Return Value:
  2692. STATUS_SUCCESS - Valid string.
  2693. STATUS_INVALID_PARAMETER - I wonder.
  2694. --*/
  2695. {
  2696. NTSTATUS Status = STATUS_SUCCESS;
  2697. //
  2698. // Check validity of structure fields and actual string
  2699. // length vs. length value supplied
  2700. //
  2701. if (!pUString ||
  2702. pUString->MaximumLength < pUString->Length ||
  2703. pUString->MaximumLength == 1 ||
  2704. pUString->Length != Safewcslen(pUString->Buffer,
  2705. pUString->MaximumLength))
  2706. {
  2707. ELF_LOG1(ERROR,
  2708. "VerifyUnicodeString: String is invalid because %ws\n",
  2709. (!pUString ?
  2710. L"it's NULL" :
  2711. (pUString->MaximumLength < pUString->Length ? L"MaximumLength < Length" :
  2712. L"Length is incorrect")));
  2713. Status = STATUS_INVALID_PARAMETER;
  2714. }
  2715. return Status;
  2716. }
  2717. NTSTATUS
  2718. VerifyAnsiString(
  2719. IN PANSI_STRING pAString
  2720. )
  2721. /*++
  2722. Routine Description:
  2723. Verify the ansi string. The string is invalid if:
  2724. The ANSI_STRING structure ptr is NULL.
  2725. The MaximumLength field is invalid (too small).
  2726. The Length field is incorrect.
  2727. Arguments:
  2728. pAString - String to verify.
  2729. Return Value:
  2730. STATUS_SUCCESS - Valid string.
  2731. STATUS_INVALID_PARAMETER - I wonder.
  2732. --*/
  2733. {
  2734. NTSTATUS Status = STATUS_SUCCESS;
  2735. if (!pAString ||
  2736. pAString->MaximumLength < pAString->Length ||
  2737. pAString->Length != Safestrlen(pAString->Buffer,
  2738. pAString->MaximumLength))
  2739. {
  2740. ELF_LOG1(ERROR,
  2741. "VerifyAnsiString: String is invalid because %ws\n",
  2742. (!pAString ?
  2743. L"it's NULL" :
  2744. (pAString->MaximumLength < pAString->Length ? L"MaximumLength < Length" :
  2745. L"Length is incorrect")));
  2746. Status = STATUS_INVALID_PARAMETER;
  2747. }
  2748. return Status;
  2749. }
  2750. //SS:changes made to enable cluster wide event logging
  2751. /****
  2752. @func NTSTATUS | ElfrRegisterClusterSvc| This is the server entrypoint
  2753. for ElfRegisterClusterSvc. The cluster service registers
  2754. itself with the event log service to enable propagation of events
  2755. across the cluster. The binding handle to the cluster service for
  2756. propagation of events is obtained.
  2757. @parm IN EVENTLOG_HANDLE_W | UNCServerName | This parameter is ignored. It
  2758. is retained for correspondence with other elf apis.
  2759. @parm OUT PULONG | pulSize | A pointer to a long where the size of the
  2760. packed event information structure is returned.
  2761. @parm OUT PBYTE | *ppPackedEventInfo| A pointer to the packed event information
  2762. structure for propagation is returned via this parameter.
  2763. @comm The cluster service propagates events contained in this structure
  2764. and deletes the memory after it has done so. Once the cluster service has
  2765. registered with the eventlog service, the eventlog service passes up
  2766. logged events to the cluster service for propagation.
  2767. @rdesc Returns a result code. ERROR_SUCCESS on success.
  2768. @xref <f ElfRegisterClusterSvc> <f ElfrDeregisterClusterSvc>
  2769. ****/
  2770. NTSTATUS
  2771. ElfrRegisterClusterSvc(
  2772. IN EVENTLOG_HANDLE_W UNCServerName,
  2773. OUT PULONG pulSize,
  2774. OUT PBYTE *ppPackedEventInfo)
  2775. {
  2776. ULONG ulTotalSize = 0;
  2777. ULONG ulTotalEventsSize = 0;
  2778. ULONG ulNumLogFiles = 0;
  2779. PPROPLOGFILEINFO pPropLogFileInfo = NULL;
  2780. NTSTATUS Status;
  2781. PPACKEDEVENTINFO pPackedEventInfo = NULL;
  2782. UINT i;
  2783. PEVENTSFORLOGFILE pEventsForLogFile;
  2784. WCHAR *pBinding = NULL;
  2785. HANDLE hClusSvcNode = NULL;
  2786. UNICODE_STRING RootRegistryNode;
  2787. OBJECT_ATTRIBUTES ObjectAttributes;
  2788. BOOL bAcquired = FALSE;
  2789. BOOL bInitedCritSec = FALSE;
  2790. ELF_LOG0(CLUSTER,
  2791. "ElfRegisterClusterSvc: Entry\n");
  2792. //
  2793. // Check if access can be allowed. Return on failure.
  2794. //
  2795. Status = ElfpClusterRpcAccessCheck ();
  2796. if ( !NT_SUCCESS( Status ) )
  2797. {
  2798. ELF_LOG1(ERROR, "ElfRegisterClusterSvc: Access check failed with status %#x\n", Status);
  2799. return ( Status );
  2800. }
  2801. //
  2802. // Initialize the OUT parameters
  2803. //
  2804. *pulSize = 0;
  2805. *ppPackedEventInfo = NULL;
  2806. //
  2807. // Check to see if the cluster service is installed.
  2808. //
  2809. RtlInitUnicodeString(&RootRegistryNode, REG_CLUSSVC_NODE_PATH);
  2810. InitializeObjectAttributes(&ObjectAttributes,
  2811. &RootRegistryNode,
  2812. OBJ_CASE_INSENSITIVE,
  2813. NULL,
  2814. NULL);
  2815. Status = NtOpenKey(&hClusSvcNode, KEY_READ | KEY_NOTIFY, &ObjectAttributes);
  2816. if (!NT_SUCCESS(Status))
  2817. {
  2818. ELF_LOG2(ERROR,
  2819. "ElfRegisterClusterSvc: NtOpenKey of %ws failed %#x\n",
  2820. REG_CLUSSVC_NODE_PATH,
  2821. Status);
  2822. goto FnExit;
  2823. }
  2824. NtClose(hClusSvcNode);
  2825. Status = STATUS_SUCCESS;
  2826. //
  2827. // If the cluster service dies and restarts again in the same session
  2828. // then it will try to register again.
  2829. // We dont reinitialize these globals again to prevent leaks
  2830. //
  2831. RtlEnterCriticalSection(&gClPropCritSec);
  2832. if (!gbClustering)
  2833. {
  2834. ELF_LOG0(CLUSTER,
  2835. "ElfRegisterClusterSvc: gbClustering is FALSE\n");
  2836. //
  2837. // Load the cluster support dll
  2838. //
  2839. ghClusDll = LoadLibraryW(L"CLUSSPRT.DLL");
  2840. if (!ghClusDll)
  2841. {
  2842. RtlLeaveCriticalSection(&gClPropCritSec);
  2843. Status = STATUS_DLL_NOT_FOUND;
  2844. goto FnExit;
  2845. }
  2846. }
  2847. //
  2848. // Get the function entry points
  2849. //
  2850. gpfnPropagateEvents = (PROPAGATEEVENTSPROC) GetProcAddress(ghClusDll,
  2851. "PropagateEvents");
  2852. gpfnBindToCluster = (BINDTOCLUSTERPROC) GetProcAddress(ghClusDll,
  2853. "BindToClusterSvc");
  2854. gpfnUnbindFromCluster = (UNBINDFROMCLUSTERPROC) GetProcAddress(ghClusDll,
  2855. "UnbindFromClusterSvc");
  2856. if (!gpfnPropagateEvents || !gpfnBindToCluster || !gpfnUnbindFromCluster)
  2857. {
  2858. ELF_LOG1(ERROR,
  2859. "ElfRegisterClusterSvc: GetProcAddress for %ws in clussprt.dll failed\n",
  2860. (!gpfnPropagateEvents ? L"PropagateEvents" :
  2861. (!gpfnBindToCluster ? L"BindToClusterSvc" :
  2862. L"UnbindFromClusterSvc")));
  2863. RtlLeaveCriticalSection(&gClPropCritSec);
  2864. Status = STATUS_PROCEDURE_NOT_FOUND;
  2865. goto FnExit;
  2866. }
  2867. //
  2868. // If we had bound to the cluster service previously, unbind and then rebind
  2869. //
  2870. if (ghCluster)
  2871. {
  2872. (*gpfnUnbindFromCluster)(ghCluster);
  2873. }
  2874. //
  2875. // Bind to the cluster service
  2876. //
  2877. ghCluster = (*gpfnBindToCluster)(NULL);
  2878. if (!ghCluster)
  2879. {
  2880. ELF_LOG1(ERROR,
  2881. "ElfRegisterClusterSvc: BindToCluster failed %d\n",
  2882. GetLastError());
  2883. RtlLeaveCriticalSection(&gClPropCritSec);
  2884. Status = STATUS_UNSUCCESSFUL;
  2885. goto FnExit;
  2886. }
  2887. RtlLeaveCriticalSection(&gClPropCritSec);
  2888. //
  2889. // Since we are going to read the logs, make sure the service is running
  2890. //
  2891. while((GetElState() == RUNNING) && (!bAcquired))
  2892. {
  2893. bAcquired = RtlAcquireResourceShared(&GlobalElfResource,
  2894. FALSE); // Don't wait
  2895. if (!bAcquired)
  2896. {
  2897. ELF_LOG0(CLUSTER,
  2898. "ElfRegisterClusterSvc: Sleep waiting for global resource\n");
  2899. Sleep(ELF_GLOBAL_RESOURCE_WAIT);
  2900. }
  2901. }
  2902. //
  2903. // If the resource was not available and the status of the service
  2904. // changed to one of the "non-working" states, then we just return
  2905. // unsuccesful. Rpc should not allow this to happen.
  2906. //
  2907. if (!bAcquired)
  2908. {
  2909. ELF_LOG0(ERROR,
  2910. "ElfRegisterClusterSvc: Global resource not acquired\n");
  2911. Status = STATUS_UNSUCCESSFUL;
  2912. goto FnExit;
  2913. }
  2914. //
  2915. // Determine the size of and acquire read locks on all files.
  2916. // FindSizeofEventsSinceStart acquires the per-log locks if
  2917. // there are events in that log to propagate.
  2918. //
  2919. Status = FindSizeofEventsSinceStart(&ulTotalEventsSize,
  2920. &ulNumLogFiles,
  2921. &pPropLogFileInfo);
  2922. if (!NT_SUCCESS(Status))
  2923. {
  2924. ELF_LOG1(ERROR,
  2925. "ElfRegisterClusterSvc: FindSizeofEventsSinceStart failed %#x\n",
  2926. Status);
  2927. goto FnExit;
  2928. }
  2929. //
  2930. // If there are any events to propagate
  2931. //
  2932. if (ulNumLogFiles && ulTotalEventsSize && pPropLogFileInfo)
  2933. {
  2934. ulTotalSize = sizeof(PACKEDEVENTINFO) // header
  2935. + (sizeof(ULONG) * ulNumLogFiles) // offsets
  2936. + (sizeof(EVENTSFORLOGFILE) * ulNumLogFiles) // info per log
  2937. + ulTotalEventsSize;
  2938. //
  2939. // Allocate memory
  2940. //
  2941. *ppPackedEventInfo = (PBYTE) ElfpAllocateBuffer(ulTotalSize);
  2942. if (!(*ppPackedEventInfo))
  2943. {
  2944. ELF_LOG1(ERROR,
  2945. "ElfRegisterClusterSvc: Unable to allocate %d bytes for pPackedEventInfo\n",
  2946. ulTotalSize);
  2947. //
  2948. // Free the read locks acquired in FindSizeofEventsSinceStart
  2949. //
  2950. for (i=0;i<ulNumLogFiles;i++)
  2951. {
  2952. RtlReleaseResource(&(pPropLogFileInfo[i].pLogFile->Resource));
  2953. }
  2954. Status = STATUS_NO_MEMORY;
  2955. goto FnExit;
  2956. }
  2957. pPackedEventInfo = (PPACKEDEVENTINFO)(*ppPackedEventInfo);
  2958. ELF_LOG2(CLUSTER,
  2959. "ElfRegisterClusterSvc: Allocated %d bytes, pPackedEventInfo is %#x\n",
  2960. ulTotalSize,
  2961. pPackedEventInfo);
  2962. pPackedEventInfo->ulNumEventsForLogFile = ulNumLogFiles;
  2963. for (i = 0;i < ulNumLogFiles; i++)
  2964. {
  2965. //
  2966. // Set the offsets to the EVENTSFORLOGFILE structures
  2967. //
  2968. pPackedEventInfo->ulOffsets[i] =
  2969. ((i == 0) ? (sizeof(PACKEDEVENTINFO) + ulNumLogFiles * sizeof(ULONG)) :
  2970. (pPackedEventInfo->ulOffsets[i - 1]
  2971. + (pPropLogFileInfo[i - 1].ulTotalEventSize
  2972. + sizeof(EVENTSFORLOGFILE))));
  2973. ELF_LOG2(CLUSTER,
  2974. "ElfRegisterClusterSvc: pPackedEventInfo->ulOffsets[%d] = %d\n",
  2975. i,
  2976. pPackedEventInfo->ulOffsets[i]);
  2977. pEventsForLogFile = (PEVENTSFORLOGFILE) ((PBYTE) pPackedEventInfo
  2978. + pPackedEventInfo->ulOffsets[i]);
  2979. //
  2980. // Set the size of the ith EVENTSFORLOGFILE structure
  2981. //
  2982. pEventsForLogFile->ulSize = sizeof(EVENTSFORLOGFILE)
  2983. + pPropLogFileInfo[i].ulTotalEventSize;
  2984. //
  2985. // Copy the file name (or should we get the module name?). StringCchCopy will NULL
  2986. // terminate the destination buffer in all cases.
  2987. //
  2988. StringCchCopy( pEventsForLogFile->szLogicalLogFile,
  2989. MAXLOGICALLOGNAMESIZE,
  2990. pPropLogFileInfo[i].pLogFile->LogModuleName->Buffer );
  2991. //
  2992. // Set the number of events
  2993. //
  2994. pEventsForLogFile->ulNumRecords = pPropLogFileInfo[i].ulNumRecords;
  2995. ELF_LOG3(CLUSTER,
  2996. "ElfRegisterClusterSvc: pEventsForLogFile struct -- ulSize = %d, "
  2997. "Logical file = %ws, ulNumRecords = %d\n",
  2998. pEventsForLogFile->ulSize,
  2999. pEventsForLogFile->szLogicalLogFile,
  3000. pEventsForLogFile->ulNumRecords);
  3001. //
  3002. // Get the events
  3003. //
  3004. Status = GetEventsToProp((PEVENTLOGRECORD) ((PBYTE) pEventsForLogFile
  3005. + sizeof(EVENTSFORLOGFILE)),
  3006. pPropLogFileInfo + i);
  3007. //
  3008. // If that fails, set the ulNumRecords to 0 so tha
  3009. // on a write this data is discarded.
  3010. //
  3011. if (!NT_SUCCESS(Status))
  3012. {
  3013. ELF_LOG2(ERROR,
  3014. "ElfRegisterClusterSvc: GetEventsToProp for %ws log failed %#x\n",
  3015. pPropLogFileInfo[i].pLogFile->LogModuleName->Buffer,
  3016. Status);
  3017. pEventsForLogFile->ulNumRecords=0;
  3018. //
  3019. // Reset the error -- we will go to the next file
  3020. //
  3021. Status = STATUS_SUCCESS;
  3022. }
  3023. //
  3024. // Advance the startpointer for all the files so if the cluster service
  3025. // dies and is restarted, these events won't be propagated again
  3026. //
  3027. pPropLogFileInfo[i].pLogFile->SessionStartRecordNumber =
  3028. pPropLogFileInfo[i].pLogFile->CurrentRecordNumber;
  3029. ELF_LOG1(CLUSTER,
  3030. "ElfRegisterClusterSvc: Done processing %ws log\n",
  3031. pPropLogFileInfo[i].pLogFile->LogModuleName->Buffer);
  3032. RtlReleaseResource (&(pPropLogFileInfo[i].pLogFile->Resource));
  3033. }
  3034. //
  3035. // Set the total size
  3036. //
  3037. pPackedEventInfo->ulSize = pPackedEventInfo->ulOffsets[ulNumLogFiles - 1]
  3038. + pPropLogFileInfo[ulNumLogFiles - 1].ulTotalEventSize
  3039. + sizeof(EVENTSFORLOGFILE);
  3040. *pulSize = pPackedEventInfo->ulSize;
  3041. }
  3042. RtlEnterCriticalSection (&gClPropCritSec);
  3043. //
  3044. // Set the flag to true so that propagation is now on.
  3045. //
  3046. gbClustering = TRUE;
  3047. //
  3048. // Initialize the support for batching events and propagating them to clussvc.
  3049. //
  3050. Status = ElfpInitializeBatchingSupport();
  3051. RtlLeaveCriticalSection (&gClPropCritSec);
  3052. FnExit:
  3053. if (!NT_SUCCESS(Status))
  3054. {
  3055. //
  3056. // Something went wrong
  3057. //
  3058. ELF_LOG1(ERROR,
  3059. "ElfRegisterClusterSvc: Exiting with error %#x\n",
  3060. Status);
  3061. RtlEnterCriticalSection(&gClPropCritSec);
  3062. gbClustering = FALSE;
  3063. if (ghCluster && gpfnUnbindFromCluster)
  3064. {
  3065. (*gpfnUnbindFromCluster)(ghCluster);
  3066. ghCluster = NULL;
  3067. }
  3068. if (ghClusDll)
  3069. {
  3070. FreeLibrary(ghClusDll);
  3071. ghClusDll = NULL;
  3072. }
  3073. RtlLeaveCriticalSection(&gClPropCritSec);
  3074. }
  3075. //
  3076. // Free the pPropLogFileInfo stucture
  3077. //
  3078. ElfpFreeBuffer(pPropLogFileInfo);
  3079. if (bAcquired)
  3080. {
  3081. ReleaseGlobalResource();
  3082. }
  3083. ELF_LOG1(CLUSTER,
  3084. "ElfRegisterClusterSvc: Returning status %#x\n",
  3085. Status);
  3086. ELF_LOG2(CLUSTER,
  3087. "ElfRegisterClusterSvc: *pulSize = %d, *ppPackedEventInfo = %#x\n",
  3088. *pulSize,
  3089. *ppPackedEventInfo);
  3090. return Status;
  3091. }
  3092. /****
  3093. @func NTSTATUS | ElfrDeregisterClusterSvc| This is the server entry point
  3094. for ElfDeregisterClusterSvc(). Before shutdown the cluster
  3095. service deregisters itself for propagation of events from the
  3096. eventlog service.
  3097. @comm Note that events logged after the cluster service goes down
  3098. are not propagated. Binding handle is freed.
  3099. @rdesc Returns a result code. ERROR_SUCCESS on success.
  3100. @xref <f ElfrRegisterClusterSvc>
  3101. ****/
  3102. NTSTATUS
  3103. ElfrDeregisterClusterSvc(
  3104. IN EVENTLOG_HANDLE_W UNCServerName
  3105. )
  3106. {
  3107. NTSTATUS Status;
  3108. ELF_LOG0(CLUSTER,
  3109. "ElfDeregisterClusterSvc: ElfrDeregisterClusterSvc: Entry\n");
  3110. //
  3111. // Check if access can be allowed. Return on failure.
  3112. //
  3113. Status = ElfpClusterRpcAccessCheck ();
  3114. if ( !NT_SUCCESS( Status ) )
  3115. {
  3116. ELF_LOG1(ERROR, "ElfDeregisterClusterSvc: Access check failed with status %#x\n", Status);
  3117. return ( Status );
  3118. }
  3119. RtlEnterCriticalSection (&gClPropCritSec);
  3120. if (gbClustering)
  3121. {
  3122. gbClustering = FALSE;
  3123. //
  3124. // Unload the cluster support dll
  3125. //
  3126. if (ghCluster && gpfnUnbindFromCluster)
  3127. {
  3128. (*gpfnUnbindFromCluster)(ghCluster);
  3129. ghCluster = NULL;
  3130. }
  3131. if (ghClusDll)
  3132. {
  3133. FreeLibrary(ghClusDll);
  3134. ghClusDll = NULL;
  3135. }
  3136. }
  3137. RtlLeaveCriticalSection (&gClPropCritSec);
  3138. ELF_LOG0(CLUSTER,
  3139. "ElfDeregisterClusterSvc: Exit\n");
  3140. return STATUS_SUCCESS;
  3141. }
  3142. /****
  3143. @func NTSTATUS | ElfrWriteClusterEvents| The cluster service calls this
  3144. api to log events reported at other nodes of the cluster in the event log files.
  3145. @parm IN EVENTLOG_HANDLE_W | UNCServerName | Not used.
  3146. @parm IN ULONG | ulSize | The size of the packed event information structure.
  3147. @parm IN PBYTE | pPackedEventInfo| A pointer to the packed event information
  3148. structure for propagation.
  3149. @comm The pPackedEventInfo is delinearized into eventlogbuffers for different event
  3150. log files and the events are recorded in the appropriate eventlog file. Multiple
  3151. events per log file are supported.
  3152. @rdesc Returns a result code. ERROR_SUCCESS on success.
  3153. @xref
  3154. ****/
  3155. NTSTATUS
  3156. ElfrWriteClusterEvents(
  3157. IN EVENTLOG_HANDLE_W UNCServerName,
  3158. IN ULONG ulSize,
  3159. IN BYTE *pBuffer
  3160. )
  3161. {
  3162. UINT i,j;
  3163. PEVENTSFORLOGFILE pEventsForLogFile;
  3164. UNICODE_STRING ModuleName;
  3165. PLOGMODULE pLogModule;
  3166. PEVENTLOGRECORD pEventLogRecord;
  3167. ELF_REQUEST_RECORD Request;
  3168. PPACKEDEVENTINFO pPackedEventInfo;
  3169. NTSTATUS Status = STATUS_SUCCESS;
  3170. WRITE_PKT WritePkt;
  3171. //
  3172. // Check if access can be allowed. Return on failure.
  3173. //
  3174. Status = ElfpClusterRpcAccessCheck ();
  3175. if ( !NT_SUCCESS( Status ) )
  3176. {
  3177. ELF_LOG1(ERROR, "ElfrWriteClusterEvents: Access check failed with status %#x\n", Status);
  3178. return ( Status );
  3179. }
  3180. //
  3181. // We want to put this in a try/except block because we're
  3182. // probing potentially bad user-supplied data.
  3183. //
  3184. try
  3185. {
  3186. pPackedEventInfo = (PPACKEDEVENTINFO)pBuffer;
  3187. //
  3188. // Validate input parameters and check that clustering is on
  3189. //
  3190. if (!pPackedEventInfo
  3191. ||
  3192. !ulSize
  3193. ||
  3194. (((PBYTE)pPackedEventInfo + sizeof(PACKEDEVENTINFO)) > (PBYTE)(pBuffer + ulSize))
  3195. ||
  3196. ((PBYTE)pPackedEventInfo + ulSize <= pBuffer) //if ulSize is large to cause overflow
  3197. ||
  3198. (pPackedEventInfo->ulSize != ulSize)
  3199. ||
  3200. (!gbClustering))
  3201. {
  3202. ELF_LOG1(ERROR,
  3203. "ElfrWriteClusterEvents: Invalid parameter passed in -- %ws\n",
  3204. (!pPackedEventInfo ?
  3205. L"pPackedEventInfo is NULL" :
  3206. (!ulSize ?
  3207. L"ulSize is 0" :
  3208. (!gbClustering ?
  3209. L"gbClustering is FALSE" :
  3210. (pPackedEventInfo->ulSize != ulSize ?
  3211. L"ulSize mismatch" :
  3212. L"pBuffer too small or ulSize too large")))));
  3213. Status = STATUS_INVALID_PARAMETER;
  3214. goto FnExit;
  3215. }
  3216. ELF_LOG2(CLUSTER,
  3217. "ElfrWriteClusterEvents: ulSize = %d, ulNumEventsForLogFile = %d\n",
  3218. ulSize,
  3219. pPackedEventInfo->ulNumEventsForLogFile);
  3220. if ((((PBYTE)pPackedEventInfo + sizeof(PACKEDEVENTINFO) +
  3221. (sizeof(DWORD) * (pPackedEventInfo->ulNumEventsForLogFile))) <
  3222. (PBYTE)(pBuffer)) ||
  3223. (((PBYTE)pPackedEventInfo + sizeof(PACKEDEVENTINFO) +
  3224. (sizeof(DWORD) * (pPackedEventInfo->ulNumEventsForLogFile))) <
  3225. (PBYTE)(pBuffer + sizeof(PACKEDEVENTINFO))))
  3226. {
  3227. ELF_LOG0(ERROR,
  3228. "ElfrWriteClusterEvents: Buffer/values passed in caused overflow\n");
  3229. Status = STATUS_INVALID_PARAMETER;
  3230. goto FnExit;
  3231. }
  3232. //check to see whether we have valid offsets for each eventlog file in the buffer
  3233. //first check to see the buffer passed in is big enough to contain the offsets
  3234. if (((PBYTE)pPackedEventInfo + sizeof(PACKEDEVENTINFO) +
  3235. (sizeof(DWORD) * (pPackedEventInfo->ulNumEventsForLogFile))) >
  3236. (PBYTE)(pBuffer + ulSize))
  3237. {
  3238. ELF_LOG0(ERROR,
  3239. "ElfrWriteClusterEvents: Buffer passed in doesnt contain offsets for all the eventlogfiles\n");
  3240. Status = STATUS_INVALID_PARAMETER;
  3241. goto FnExit;
  3242. }
  3243. //
  3244. // Setup the request packet
  3245. //
  3246. Request.Pkt.WritePkt = &WritePkt; // Set up write packet in request packet
  3247. Request.Flags = 0;
  3248. //
  3249. // For each log
  3250. //
  3251. for (i = 0; i < pPackedEventInfo->ulNumEventsForLogFile; i++)
  3252. {
  3253. pEventsForLogFile = (PEVENTSFORLOGFILE) ((PBYTE)pPackedEventInfo +
  3254. pPackedEventInfo->ulOffsets[i]);
  3255. //
  3256. // Check for overflow or pointer past end of buffer
  3257. //
  3258. if (((PBYTE) pEventsForLogFile < pBuffer)
  3259. ||
  3260. (((PBYTE) pEventsForLogFile + sizeof(EVENTSFORLOGFILE)) >
  3261. (PBYTE) (pBuffer + ulSize)))
  3262. {
  3263. ELF_LOG2(ERROR,
  3264. "ElfrWriteClusterEvents: Bad offset for log %d -- %ws\n",
  3265. i,
  3266. ((PBYTE) pEventsForLogFile < pBuffer ? L"offset caused overflow" :
  3267. L"offset past end of buffer"));
  3268. Status = STATUS_INVALID_PARAMETER;
  3269. goto FnExit;
  3270. }
  3271. ELF_LOG2(CLUSTER,
  3272. "ElfrWriteClusterEvents: szLogicalFile = %ws, ulNumRecords = %d\n",
  3273. pEventsForLogFile->szLogicalLogFile,
  3274. pEventsForLogFile->ulNumRecords);
  3275. //
  3276. // Find the module -- since we dont trust this string, force null termination
  3277. //
  3278. pEventsForLogFile->szLogicalLogFile[MAXLOGICALLOGNAMESIZE - 1] = L'\0';
  3279. RtlInitUnicodeString(&ModuleName, pEventsForLogFile->szLogicalLogFile);
  3280. pLogModule = GetModuleStruc(&ModuleName);
  3281. if (!pLogModule)
  3282. {
  3283. ELF_LOG1(ERROR,
  3284. "ElfrWriteClusterEvents: Bogus ModuleName %ws passed in\n",
  3285. pEventsForLogFile->szLogicalLogFile);
  3286. //skip this log file and go to the next one
  3287. continue;
  3288. }
  3289. //
  3290. // GetModuleStruc always returns something non-NULL -- if the
  3291. // given module name is bogus, we'll use the Application log.
  3292. //
  3293. ELF_LOG2(CLUSTER,
  3294. "ElfrWriteClusterEvents: Processing records for %ws module (%ws log)\n",
  3295. pLogModule->ModuleName,
  3296. pLogModule->LogFile->LogModuleName->Buffer);
  3297. Request.Module = pLogModule;
  3298. Request.LogFile = Request.Module->LogFile;
  3299. Request.Command = ELF_COMMAND_WRITE;
  3300. pEventLogRecord = (PEVENTLOGRECORD) (pEventsForLogFile->pEventLogRecords);
  3301. for (j = 0;
  3302. j < pEventsForLogFile->ulNumRecords &&
  3303. pEventLogRecord->Reserved == ELF_LOG_FILE_SIGNATURE;
  3304. j++)
  3305. {
  3306. //
  3307. // Check for pointer past end of buffer
  3308. //
  3309. if (((PBYTE) pEventLogRecord + pEventLogRecord->Length) >
  3310. (PBYTE) (pBuffer + ulSize))
  3311. {
  3312. ELF_LOG3(ERROR,
  3313. "ElfrWriteClusterEvents: Record %d for %ws module "
  3314. "(%ws log) too long\n",
  3315. j,
  3316. pLogModule->ModuleName,
  3317. pLogModule->LogFile->LogModuleName->Buffer);
  3318. Status = STATUS_INVALID_PARAMETER;
  3319. goto FnExit;
  3320. }
  3321. //
  3322. // Fill in a request packet for the current record
  3323. //
  3324. Request.Pkt.WritePkt->Buffer = pEventLogRecord;
  3325. Request.Pkt.WritePkt->Datasize = pEventLogRecord->Length;
  3326. //
  3327. // SS: Should we get exclusive access to the log so that
  3328. // the current record number is not incremented
  3329. // for an event that needs to be propagated
  3330. // before the session start record number is set here?
  3331. //
  3332. ElfPerformRequest(&Request);
  3333. //
  3334. // Advance the session start record number, so that
  3335. // we don't propagate an event propagated to us
  3336. //
  3337. pLogModule->LogFile->SessionStartRecordNumber =
  3338. pLogModule->LogFile->CurrentRecordNumber;
  3339. //
  3340. // Extract status of operation from the request packet
  3341. //
  3342. Status = Request.Status;
  3343. if (!NT_SUCCESS(Status))
  3344. {
  3345. ELF_LOG3(ERROR,
  3346. "ElfrWriteClusterEvents: Failed to write record %d to "
  3347. "%ws log %#x\n",
  3348. j,
  3349. pLogModule->LogFile->LogModuleName->Buffer,
  3350. Status);
  3351. }
  3352. pEventLogRecord = (PEVENTLOGRECORD) ((PBYTE) pEventLogRecord +
  3353. pEventLogRecord->Length);
  3354. }
  3355. }
  3356. }
  3357. except (EXCEPTION_EXECUTE_HANDLER)
  3358. {
  3359. ELF_LOG1(ERROR,
  3360. "ElfrWriteClusterEvents: Exception %#x caught probing passed-in buffer\n",
  3361. GetExceptionCode());
  3362. Status = STATUS_INVALID_PARAMETER;
  3363. }
  3364. FnExit:
  3365. return Status;
  3366. }
  3367. /****
  3368. @func NTSTATUS | ElfpInitializeBatchingSupport | Initialize the batching support structures.
  3369. @comm This initializes the global structures and threads necessary for batching support.
  3370. @parm None.
  3371. @rdesc STATUS_SUCCESS on success, an NT status error otherwise.
  3372. @xref
  3373. ****/
  3374. NTSTATUS
  3375. ElfpInitializeBatchingSupport(
  3376. VOID
  3377. )
  3378. {
  3379. NTSTATUS ntStatus = STATUS_SUCCESS;
  3380. BOOL fCritSecInitialized = TRUE;
  3381. if ( g_fBatchingSupportInitialized ) goto FnExit;
  3382. //
  3383. // Initialize a CritSec for clustering support
  3384. //
  3385. ntStatus = ElfpInitCriticalSection( &g_CSBatchQueue );
  3386. if ( !NT_SUCCESS( ntStatus ) )
  3387. {
  3388. ELF_LOG1(ERROR,
  3389. "ElfpInitializeBatchingSupport: Unable to init g_CSBatchQueue, status %#x\n",
  3390. ntStatus);
  3391. fCritSecInitialized = FALSE;
  3392. goto FnExit;
  3393. }
  3394. //
  3395. // Initialize the timer that supports batched event propagation into cluster service
  3396. //
  3397. g_hBatchingSupportTimerQueue = CreateTimerQueue();
  3398. if ( g_hBatchingSupportTimerQueue == NULL )
  3399. {
  3400. ntStatus = STATUS_UNSUCCESSFUL;
  3401. ELF_LOG1(ERROR, "ElfpInitializeBatchingSupport: Unable to create timer queue, Status=%d\n",
  3402. GetLastError());
  3403. goto FnExit;
  3404. }
  3405. //
  3406. // Allocate memory for all structures here. Memory for these structures is not freed and it is
  3407. // a one-time only allocation.
  3408. //
  3409. g_pBatchQueueElement = ElfpAllocateBuffer ( sizeof ( BATCH_QUEUE_ELEMENT ) * MAX_BATCH_QUEUE_ELEMENTS );
  3410. if ( g_pBatchQueueElement == NULL )
  3411. {
  3412. ntStatus = STATUS_NO_MEMORY;
  3413. ELF_LOG1(ERROR, "ElfpInitializeBatchingSupport: Memalloc for batch queue elements failed, Status=%d\n",
  3414. GetLastError());
  3415. goto FnExit;
  3416. }
  3417. g_pcbRecordsOfSameType = ElfpAllocateBuffer ( sizeof ( DWORD ) * MAX_BATCH_QUEUE_ELEMENTS );
  3418. if ( g_pcbRecordsOfSameType == NULL )
  3419. {
  3420. ntStatus = STATUS_NO_MEMORY;
  3421. ELF_LOG1(ERROR, "ElfpInitializeBatchingSupport: Memalloc for records of same type array failed, Status=%d\n",
  3422. GetLastError());
  3423. goto FnExit;
  3424. }
  3425. g_pdwRecordType = ElfpAllocateBuffer ( sizeof ( DWORD ) * MAX_BATCH_QUEUE_ELEMENTS );
  3426. if ( g_pdwRecordType == NULL )
  3427. {
  3428. ntStatus = STATUS_NO_MEMORY;
  3429. ELF_LOG1(ERROR, "ElfpInitializeBatchingSupport: Memalloc for records type array failed, Status=%d\n",
  3430. GetLastError());
  3431. goto FnExit;
  3432. }
  3433. g_pPropagatedInfo = ElfpAllocateBuffer ( sizeof ( PROPINFO ) * MAX_BATCH_QUEUE_ELEMENTS );
  3434. if ( g_pPropagatedInfo == NULL )
  3435. {
  3436. ntStatus = STATUS_NO_MEMORY;
  3437. ELF_LOG1(ERROR, "ElfpInitializeBatchingSupport: Memalloc for propinfo array failed, Status=%d\n",
  3438. GetLastError());
  3439. goto FnExit;
  3440. }
  3441. g_fBatchingSupportInitialized = TRUE;
  3442. FnExit:
  3443. if ( ntStatus != STATUS_SUCCESS )
  3444. {
  3445. //
  3446. // Free allocated resources on failure
  3447. //
  3448. if ( fCritSecInitialized )
  3449. {
  3450. DeleteCriticalSection ( &g_CSBatchQueue );
  3451. }
  3452. if ( g_hBatchingSupportTimerQueue )
  3453. {
  3454. DeleteTimerQueueEx ( g_hBatchingSupportTimerQueue, NULL );
  3455. g_hBatchingSupportTimerQueue = NULL;
  3456. }
  3457. ElfpFreeBuffer ( g_pdwRecordType );
  3458. g_pdwRecordType = NULL;
  3459. ElfpFreeBuffer ( g_pPropagatedInfo );
  3460. g_pPropagatedInfo = NULL;
  3461. ElfpFreeBuffer ( g_pBatchQueueElement );
  3462. g_pBatchQueueElement = NULL;
  3463. ElfpFreeBuffer ( g_pcbRecordsOfSameType );
  3464. g_pcbRecordsOfSameType = NULL;
  3465. }
  3466. return ( ntStatus );
  3467. }// ElfpInitializeBatchingSupport
  3468. /****
  3469. @func NTSTATUS | ElfpSaveEventBuffer | Save the module name and a pointer to the event buffer.
  3470. @parm IN PLOGMODULE | pModule | A pointer to a module for the eventlog file.
  3471. @parm IN PVOID | pEventBuffer | A pointer to the event buffer.
  3472. @parm IN DWORD | dwRecordLength | The length of the event buffer in bytes.
  3473. @comm This saves a pointer to the supplied eventlog buffer so that it can be batch sent to the cluster service
  3474. for replication.
  3475. @rdesc Returns a result code. STATUS_SUCCESS on success.
  3476. @xref
  3477. ****/
  3478. NTSTATUS
  3479. ElfpSaveEventBuffer(
  3480. IN PLOGMODULE pModule,
  3481. IN PVOID pEventBuffer,
  3482. IN DWORD dwRecordLength
  3483. )
  3484. {
  3485. NTSTATUS ntStatus = STATUS_SUCCESS;
  3486. LPWSTR lpszLogFileName = NULL;
  3487. LPWSTR lpszLogicalLogFile = NULL;
  3488. DWORD cchLogFileName, cchLogicalLogFile;
  3489. //
  3490. // If the batching support system is not initialized or if you don't detect cluster service as having
  3491. // registered with the eventlog service, just return. Note that you cannot afford to get the
  3492. // gClPropCritSec here since that could hang the ElfReportEvent API if we are hung in the propagate to the
  3493. // cluster service.
  3494. //
  3495. if ( ( g_fBatchingSupportInitialized == FALSE ) ||
  3496. ( gbClustering == FALSE ) )
  3497. {
  3498. ElfpFreeBuffer( pEventBuffer );
  3499. return ( ntStatus );
  3500. }
  3501. //
  3502. // To conserve resources, let us limit the max size of records we accept.
  3503. //
  3504. if ( dwRecordLength >= MAXSIZE_OF_EVENTSTOPROP )
  3505. {
  3506. ntStatus = STATUS_BUFFER_OVERFLOW;
  3507. ELF_LOG1(ERROR, "ElfpSaveEventBuffer: Eventlog record size %d is bigger than supported size\n",
  3508. dwRecordLength);
  3509. ElfpFreeBuffer( pEventBuffer );
  3510. return( ntStatus );
  3511. }
  3512. //
  3513. // This is a hack to prevent replication of the time blob delta events generated by the
  3514. // cluster service.
  3515. //
  3516. if ( ( ( ( PEVENTLOGRECORD ) pEventBuffer )->EventID == CLUSSPRT_EVENT_TIME_DELTA_INFORMATION ) &&
  3517. ( !lstrcmpW( ( LPWSTR ) ( ( PBYTE ) pEventBuffer + sizeof( EVENTLOGRECORD ) ), L"ClusSvc" ) ) )
  3518. {
  3519. ElfpFreeBuffer( pEventBuffer );
  3520. return( ntStatus );
  3521. }
  3522. RtlEnterCriticalSection ( &g_CSBatchQueue );
  3523. //
  3524. // If the batch queue is full, you would just drop stuff on the floor.
  3525. //
  3526. if ( g_dwFirstFreeIndex == MAX_BATCH_QUEUE_ELEMENTS )
  3527. {
  3528. ELF_LOG2(ERROR, "ElfpSaveEventBuffer: Batch queue full, dropped event of length %d in log file %ws\n",
  3529. dwRecordLength,
  3530. pModule->LogFile->LogModuleName->Buffer);
  3531. ntStatus = STATUS_BUFFER_OVERFLOW;
  3532. goto FnExit;
  3533. }
  3534. //
  3535. // Save the log file name, event buffer pointer and record length. Memory for this will be freed
  3536. // at batching time by ElfpBatchEventsAndPropagate.
  3537. //
  3538. cchLogicalLogFile = lstrlen ( pModule->LogFile->LogModuleName->Buffer ) + 1;
  3539. lpszLogicalLogFile = ElfpAllocateBuffer ( cchLogicalLogFile * sizeof ( WCHAR ) );
  3540. if ( lpszLogicalLogFile == NULL )
  3541. {
  3542. ntStatus = STATUS_NO_MEMORY;
  3543. ELF_LOG0(ERROR, "ElfpSaveEventBuffer: Unable to alloc memory for logical log file name\n");
  3544. goto FnExit;
  3545. }
  3546. //
  3547. // Save the log file name and the current record number. This information will be used
  3548. // to update the session start record number in the log file after the event is
  3549. // is successfully sent to the cluster service. Memory for this will be freed at batching
  3550. // time by ElfpBatchEventsAndPropagate..
  3551. //
  3552. cchLogFileName = lstrlen ( pModule->LogFile->LogFileName->Buffer ) + 1;
  3553. lpszLogFileName = ElfpAllocateBuffer ( cchLogFileName * sizeof ( WCHAR ) );
  3554. if ( lpszLogFileName == NULL )
  3555. {
  3556. ntStatus = STATUS_NO_MEMORY;
  3557. ELF_LOG0(ERROR, "ElfpSaveEventBuffer: Unable to alloc memory for log file name\n");
  3558. goto FnExit;
  3559. }
  3560. g_pBatchQueueElement[g_dwFirstFreeIndex].lpszLogicalLogFile = lpszLogicalLogFile;
  3561. //
  3562. // StringCchCopy will NULL terminate the string in the destination buffer. Save the log module
  3563. // name.
  3564. //
  3565. StringCchCopy ( g_pBatchQueueElement[g_dwFirstFreeIndex].lpszLogicalLogFile,
  3566. cchLogicalLogFile,
  3567. pModule->LogFile->LogModuleName->Buffer );
  3568. //
  3569. // Just save the pointer to the event buffer. Memory will be freed at batching time by
  3570. // ElfpBatchEventsAndPropagate.
  3571. //
  3572. g_pBatchQueueElement[g_dwFirstFreeIndex].pEventBuffer = pEventBuffer;
  3573. g_pBatchQueueElement[g_dwFirstFreeIndex].dwRecordLength = dwRecordLength;
  3574. //
  3575. // StringCchCopy will NULL terminate the string in the destination buffer. Save the log file name.
  3576. //
  3577. StringCchCopy ( lpszLogFileName, cchLogFileName, pModule->LogFile->LogFileName->Buffer );
  3578. RtlInitUnicodeString ( &g_pBatchQueueElement[g_dwFirstFreeIndex].PropagatedInfo.LogFileName, lpszLogFileName );
  3579. g_pBatchQueueElement[g_dwFirstFreeIndex].PropagatedInfo.dwCurrentRecordNum = pModule->LogFile->CurrentRecordNumber;
  3580. if ( g_hBatchingSupportTimer == NULL )
  3581. {
  3582. //
  3583. // Insert a timer action into the timer queue.
  3584. //
  3585. if ( !CreateTimerQueueTimer( &g_hBatchingSupportTimer, // Timer handle
  3586. g_hBatchingSupportTimerQueue, // Timer queue handle
  3587. ElfpBatchEventsAndPropagate, // Callback
  3588. NULL, // Context
  3589. BATCHING_SUPPORT_TIMER_DUE_TIME, // Due time in msec
  3590. 0, // Period (fire once)
  3591. WT_EXECUTELONGFUNCTION ) ) // Long func exec
  3592. {
  3593. ELF_LOG1(ERROR, "ElfpInitializeBatchingSupport: Unable to create timer, Status=%d\n",
  3594. GetLastError());
  3595. ntStatus = STATUS_UNSUCCESSFUL;
  3596. goto FnExit;
  3597. }
  3598. }
  3599. g_dwFirstFreeIndex ++;
  3600. FnExit:
  3601. RtlLeaveCriticalSection ( &g_CSBatchQueue );
  3602. if ( ntStatus != STATUS_SUCCESS )
  3603. {
  3604. ElfpFreeBuffer( pEventBuffer );
  3605. ElfpFreeBuffer ( lpszLogFileName );
  3606. ElfpFreeBuffer ( lpszLogicalLogFile );
  3607. }
  3608. return ( ntStatus );
  3609. }// ElfpSaveEventBuffer
  3610. /****
  3611. @func NTSTATUS | ElfpBatchEventsAndPropagate | Read eventlog records, batch them and ship them.
  3612. @comm This reads the eventlog records saved in the batch queue, packs them in one structure and ships
  3613. them off to the cluster service.
  3614. @parm None used.
  3615. @rdesc None.
  3616. @xref
  3617. ****/
  3618. VOID CALLBACK
  3619. ElfpBatchEventsAndPropagate(
  3620. IN PVOID pContext,
  3621. IN BOOLEAN fTimerFired
  3622. )
  3623. {
  3624. DWORD i, j, k, dwRecordIndex, dwTypeNumber = 1;
  3625. ULONG ulTotalSize = 0, ulTotalLogFiles = 0;
  3626. PPACKEDEVENTINFO pPackedEventInfo = NULL;
  3627. PEVENTSFORLOGFILE pEventsForLogFile = NULL;
  3628. DWORD cbMostRecentTotalRecordLength = 0;
  3629. LPBYTE pDest;
  3630. DWORD dwStatus = ERROR_INVALID_PARAMETER;
  3631. DWORD dwFirstFreeIndex = 0;
  3632. UNREFERENCED_PARAMETER( pContext );
  3633. UNREFERENCED_PARAMETER( fTimerFired );
  3634. RtlEnterCriticalSection ( &g_CSBatchQueue );
  3635. //
  3636. // You should never have 0 elements in the batch queue
  3637. //
  3638. ASSERT ( g_dwFirstFreeIndex != 0 );
  3639. dwFirstFreeIndex = g_dwFirstFreeIndex;
  3640. //
  3641. // g_pcbRecordsOfSameType[i] - Total count of bytes of eventlog records of the same type. Only the first element
  3642. // of each type has this field set, for subsequent ones of the same type, this field will be 0
  3643. //
  3644. // g_pdwRecordType[i] - Type number for record i. Type number explained below. All elements will have this
  3645. // field set correctly.
  3646. //
  3647. ZeroMemory( g_pcbRecordsOfSameType, sizeof ( *g_pcbRecordsOfSameType ) * MAX_BATCH_QUEUE_ELEMENTS );
  3648. ZeroMemory( g_pdwRecordType, sizeof ( *g_pdwRecordType ) * MAX_BATCH_QUEUE_ELEMENTS );
  3649. //
  3650. // Estimate how much contiguous memory is needed. In the process, mark a type number for each record. The type
  3651. // number will be same for records of the same type.
  3652. //
  3653. for ( i=0; i<g_dwFirstFreeIndex; i++ )
  3654. {
  3655. //
  3656. // Check if this event record has been parsed already.
  3657. //
  3658. if ( g_pdwRecordType[i] != 0 ) continue;
  3659. //
  3660. // This record has not been categorized yet. So, compare this record with other records
  3661. // downstream and categorize all like ones into the same type.
  3662. //
  3663. for ( j=i; j<g_dwFirstFreeIndex; j++ )
  3664. {
  3665. if ( ( g_pdwRecordType[j] == 0 ) &&
  3666. ( ( j == i ) ||
  3667. ( lstrcmp( g_pBatchQueueElement[i].lpszLogicalLogFile,
  3668. g_pBatchQueueElement[j].lpszLogicalLogFile ) == 0 ) ) )
  3669. {
  3670. g_pcbRecordsOfSameType[i] += g_pBatchQueueElement[j].dwRecordLength;
  3671. g_pdwRecordType[j] = dwTypeNumber;
  3672. }
  3673. } // for
  3674. //
  3675. // Bump up the type number
  3676. //
  3677. dwTypeNumber += 1;
  3678. } // for
  3679. //
  3680. // Calculate the total size needed for the packed eventlog info. Total size = Size of all eventlog
  3681. // records + size of headers prepended to each record + size of header for the overall package
  3682. //
  3683. for ( i=0; i<g_dwFirstFreeIndex; i++ )
  3684. {
  3685. if ( g_pcbRecordsOfSameType[i] != 0 )
  3686. {
  3687. ulTotalSize += sizeof( EVENTSFORLOGFILE ) + g_pcbRecordsOfSameType[i];
  3688. ulTotalLogFiles += 1;
  3689. }
  3690. //
  3691. // Initialize the propagation information
  3692. //
  3693. g_pPropagatedInfo[i].dwCurrentRecordNum = 0;
  3694. RtlInitUnicodeString ( &g_pPropagatedInfo[i].LogFileName, NULL );
  3695. } // for
  3696. ulTotalSize += sizeof( PACKEDEVENTINFO ) + ulTotalLogFiles * sizeof ( ULONG );
  3697. //
  3698. // Allocate the packed info struct. Packed event info consists of:
  3699. //
  3700. // 1. PACKEDEVENTINFO structure
  3701. // 2. Offsets into the start of EVENTSFORLOGFILE (total number of offsets equals ulTotalLogFiles)
  3702. // from the beginning of the packed info structure.
  3703. // 3. A series of 4 and 5, one set for each log file.
  3704. // 4. EVENTSFORLOGFILE structure
  3705. // 5. A series of eventlog records
  3706. //
  3707. pPackedEventInfo = ( PPACKEDEVENTINFO ) ElfpAllocateBuffer( ulTotalSize );
  3708. if ( !pPackedEventInfo )
  3709. {
  3710. ELF_LOG1(ERROR, "ElfpBatchEventsAndPropagate: Unable to allocate %d bytes for PackedEventInfo\n",
  3711. ulTotalSize);
  3712. goto CleanupTimerAndExit;
  3713. }
  3714. //
  3715. // First of, initialize the header and in a loop initialize the offset fields in the
  3716. // header
  3717. //
  3718. pPackedEventInfo->ulNumEventsForLogFile = ulTotalLogFiles;
  3719. pPackedEventInfo->ulSize = ulTotalSize;
  3720. j = 0;
  3721. for ( i=0; i<g_dwFirstFreeIndex; i++ )
  3722. {
  3723. if ( g_pcbRecordsOfSameType[i] != 0 )
  3724. {
  3725. //
  3726. // You are now looking at the first element of one type. Calculate the offset at which
  3727. // you need to start copying the eventlog info.
  3728. //
  3729. pPackedEventInfo->ulOffsets[j] = ( j== 0 ) ?
  3730. ( sizeof ( PACKEDEVENTINFO ) + ulTotalLogFiles * sizeof ( ULONG ) ) :
  3731. ( pPackedEventInfo->ulOffsets[j-1] + sizeof ( EVENTSFORLOGFILE ) +
  3732. cbMostRecentTotalRecordLength );
  3733. pEventsForLogFile = ( PEVENTSFORLOGFILE ) ( ( LPBYTE ) pPackedEventInfo + pPackedEventInfo->ulOffsets[j] );
  3734. pEventsForLogFile->ulSize = g_pcbRecordsOfSameType[i] + sizeof ( EVENTSFORLOGFILE );
  3735. //
  3736. // StringCchCopy will NULL terminate the buffer.
  3737. //
  3738. StringCchCopy ( pEventsForLogFile->szLogicalLogFile,
  3739. MAXLOGICALLOGNAMESIZE,
  3740. g_pBatchQueueElement[i].lpszLogicalLogFile );
  3741. ElfpFreeBuffer ( g_pBatchQueueElement[i].lpszLogicalLogFile );
  3742. g_pBatchQueueElement[i].lpszLogicalLogFile = NULL;
  3743. pEventsForLogFile->ulNumRecords = 0;
  3744. pDest = ( LPBYTE ) pEventsForLogFile->pEventLogRecords;
  3745. for ( k=i; k<g_dwFirstFreeIndex; k++ )
  3746. {
  3747. if ( g_pdwRecordType[k] == g_pdwRecordType[i] )
  3748. {
  3749. //
  3750. // We are looking at two records of the same type. Copy the eventlog record into the
  3751. // buffer. Increment the number of log records.
  3752. //
  3753. CopyMemory( pDest,
  3754. g_pBatchQueueElement[k].pEventBuffer,
  3755. g_pBatchQueueElement[k].dwRecordLength );
  3756. pEventsForLogFile->ulNumRecords ++;
  3757. pDest += g_pBatchQueueElement[k].dwRecordLength;
  3758. ElfpFreeBuffer ( g_pBatchQueueElement[k].pEventBuffer );
  3759. ElfpFreeBuffer ( g_pBatchQueueElement[k].lpszLogicalLogFile );
  3760. }
  3761. } // for
  3762. cbMostRecentTotalRecordLength = g_pcbRecordsOfSameType[i];
  3763. j++;
  3764. }// if
  3765. //
  3766. // Save the propagation info right here so it can be used after the events are
  3767. // propagated. Note that we cannot rely on the g_pBatchQueueElement after the batch
  3768. // queue lock is released.
  3769. //
  3770. g_pPropagatedInfo[i].dwCurrentRecordNum = g_pBatchQueueElement[i].PropagatedInfo.dwCurrentRecordNum;
  3771. g_pPropagatedInfo[i].LogFileName = g_pBatchQueueElement[i].PropagatedInfo.LogFileName;
  3772. } // for
  3773. CleanupTimerAndExit:
  3774. //
  3775. // Mark that the batch queue is empty. But, save the value first for later use.
  3776. //
  3777. g_dwFirstFreeIndex = 0;
  3778. //
  3779. // Delete the timer. Don't NULL out the handle until you got a chance to propagate the event.
  3780. //
  3781. if ( !DeleteTimerQueueTimer( g_hBatchingSupportTimerQueue, // Timer queue handle
  3782. g_hBatchingSupportTimer, // Timer handle
  3783. NULL ) ) // No blocking
  3784. {
  3785. //
  3786. // ERROR_IO_PENDING is legitimate since we delete the timer from within a callback and
  3787. // that callback is not finished yet.
  3788. //
  3789. if ( GetLastError() != ERROR_IO_PENDING )
  3790. {
  3791. ELF_LOG1(ERROR, "ElfpBatchEventsAndPropagate: Delete timer returns status=%d...\n",
  3792. GetLastError());
  3793. }
  3794. }
  3795. RtlLeaveCriticalSection ( &g_CSBatchQueue );
  3796. //
  3797. // Acquire the critical section for this global propagation area. The assumption is that this call
  3798. // may take a long time. E.g., cluster service is in the debugger.
  3799. //
  3800. RtlEnterCriticalSection ( &gClPropCritSec );
  3801. if ( gbClustering && pPackedEventInfo )
  3802. {
  3803. dwStatus = ( *gpfnPropagateEvents )( ghCluster,
  3804. pPackedEventInfo->ulSize,
  3805. ( PUCHAR ) pPackedEventInfo );
  3806. if ( dwStatus != ERROR_SUCCESS )
  3807. {
  3808. ELF_LOG1( ERROR, "ElfpBatchEventsAndPropagate: Propagate events failed with error %d\n",
  3809. dwStatus );
  3810. }
  3811. }
  3812. RtlLeaveCriticalSection ( &gClPropCritSec );
  3813. //
  3814. // If the events were successfully propagated, then make sure the session start record
  3815. // number information in the log file structure is advanced so a new ElfrRegisterClusterSvc
  3816. // will not pick up events already propagated. If the events were not successfully propagated,
  3817. // then not advancing the session number will force ElfrRegisterClusterSvc to batch
  3818. // all events not propagated into one shot as an output parameter.
  3819. //
  3820. for ( i=0; i<dwFirstFreeIndex; i++ )
  3821. {
  3822. if ( dwStatus == ERROR_SUCCESS )
  3823. {
  3824. PLOGFILE pLogFile;
  3825. pLogFile = FindLogFileFromName ( &g_pPropagatedInfo[i].LogFileName );
  3826. if ( pLogFile )
  3827. {
  3828. pLogFile->SessionStartRecordNumber = g_pPropagatedInfo[i].dwCurrentRecordNum;
  3829. }
  3830. }
  3831. ElfpFreeBuffer ( g_pPropagatedInfo[i].LogFileName.Buffer );
  3832. } // for
  3833. //
  3834. // Free the blob
  3835. //
  3836. ElfpFreeBuffer ( pPackedEventInfo );
  3837. //
  3838. // NULL out the global timer handle. This will trigger the producer of events (ElfpSaveEventBuffer) to
  3839. // create a new timer.
  3840. //
  3841. RtlEnterCriticalSection ( &g_CSBatchQueue );
  3842. g_hBatchingSupportTimer = NULL;
  3843. RtlLeaveCriticalSection ( &g_CSBatchQueue );
  3844. }// ElfpBatchEventsAndPropagate
  3845. //SS:end of changes made to enable cluster wide event logging
  3846. NTSTATUS
  3847. ElfrFlushEL (
  3848. IN IELF_HANDLE LogHandle
  3849. )
  3850. /*++
  3851. Routine Description:
  3852. This is the RPC server entry point for the ElfrFlushEL API.
  3853. Arguments:
  3854. Return Value:
  3855. Returns an NTSTATUS code.
  3856. --*/
  3857. {
  3858. NTSTATUS Status;
  3859. // Only LSASS should be able to do this!
  3860. if(gElfSecurityHandle != LogHandle)
  3861. return STATUS_ACCESS_DENIED;
  3862. //
  3863. // Check the handle before proceeding.
  3864. //
  3865. if (LogHandle == NULL)
  3866. {
  3867. ELF_LOG0(ERROR,
  3868. "ElfrFlushEL: LogHandle is NULL\n");
  3869. return STATUS_INVALID_PARAMETER;
  3870. }
  3871. Status = VerifyElfHandle(LogHandle);
  3872. if (!NT_SUCCESS(Status))
  3873. {
  3874. ELF_LOG1(ERROR,
  3875. "ElfrFlushEL: VerifyElfHandle failed %#x\n",
  3876. Status);
  3877. return Status;
  3878. }
  3879. //
  3880. // Ensure the caller has write access.
  3881. //
  3882. if (!(LogHandle->GrantedAccess & ELF_LOGFILE_WRITE))
  3883. {
  3884. ELF_LOG0(ERROR,
  3885. "ElfrFlushEL: LogHandle does not have write access\n");
  3886. return STATUS_ACCESS_DENIED;
  3887. }
  3888. ElfpFlushFiles(FALSE);
  3889. return STATUS_SUCCESS;
  3890. }
  3891. /****
  3892. @func NTSTATUS | ElfpClusterAccessCheck | Check whether the caller has rights to invoke RPCs for cluster support.
  3893. @parm None.
  3894. @comm Check if the caller is in the admin group, allow access if so.
  3895. @rdesc Returns a result code. STATUS_SUCCESS on success.
  3896. @xref
  3897. ****/
  3898. NTSTATUS
  3899. ElfpClusterRpcAccessCheck(
  3900. VOID
  3901. )
  3902. {
  3903. NTSTATUS Status = STATUS_SUCCESS, revertStatus;
  3904. HANDLE hClientToken = NULL;
  3905. BOOL fCheckMember;
  3906. //
  3907. // Impersonate to figure if the caller is in the admin group. The cluster service must run
  3908. // in an account that has local admin privileges.
  3909. //
  3910. Status = I_RpcMapWin32Status( RpcImpersonateClient( NULL ) );
  3911. if ( !NT_SUCCESS( Status ) )
  3912. {
  3913. ELF_LOG1(ERROR, "ElfpClusterAccessCheck: RpcImpersonateClient failed %#x\n", Status);
  3914. return ( Status );
  3915. }
  3916. if ( !OpenThreadToken( GetCurrentThread(), TOKEN_READ, TRUE, &hClientToken ) )
  3917. {
  3918. ELF_LOG1(ERROR, "ElfpClusterAccessCheck: OpenThreadToken failed %d\n", GetLastError());
  3919. Status = STATUS_ACCESS_DENIED;
  3920. goto FnExit;
  3921. }
  3922. if ( !CheckTokenMembership( hClientToken,
  3923. ElfGlobalData->AliasAdminsSid,
  3924. &fCheckMember ) )
  3925. {
  3926. ELF_LOG1(ERROR, "ElfpClusterAccessCheck: CheckTokenMembership failed %d\n", GetLastError());
  3927. Status = STATUS_ACCESS_DENIED;
  3928. goto FnExit;
  3929. }
  3930. if ( !fCheckMember )
  3931. {
  3932. ELF_LOG0(ERROR, "ElfpClusterAccessCheck: Caller is not an Admin\n");
  3933. Status = STATUS_ACCESS_DENIED;
  3934. goto FnExit;
  3935. }
  3936. FnExit:
  3937. //
  3938. // Stop impersonating
  3939. //
  3940. revertStatus = I_RpcMapWin32Status( RpcRevertToSelf() );
  3941. if ( !NT_SUCCESS( revertStatus ) )
  3942. {
  3943. ELF_LOG1(ERROR, "ElfpClusterAccessCheck: RpcRevertToSelf failed %#x\n", revertStatus);
  3944. if ( NT_SUCCESS ( Status ) ) Status = revertStatus;
  3945. }
  3946. if ( hClientToken )
  3947. {
  3948. CloseHandle( hClientToken );
  3949. }
  3950. return ( Status );
  3951. }// ElfpClusterAccessCheck