Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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