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.

1949 lines
46 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. APISTUB.C
  5. Abstract:
  6. This module contains the client ends of the Elf APIs.
  7. Author:
  8. Rajen Shah (rajens) 29-Jul-1991
  9. Revision History:
  10. 29-Jul-1991 RajenS
  11. Created
  12. 13-Jan-1997 Added extensions for clustering to support replicated
  13. eventlogs
  14. --*/
  15. /****
  16. @doc EXTERNAL INTERFACES EVTLOG
  17. ****/
  18. #include <elfclntp.h>
  19. #include <lmerr.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. //
  23. // Global data
  24. //
  25. PUNICODE_STRING pGlobalComputerNameU;
  26. PANSI_STRING pGlobalComputerNameA;
  27. VOID
  28. w_GetComputerName ( )
  29. /*++
  30. Routine Description:
  31. This routine gets the name of the computer. It checks the global
  32. variable to see if the computer name has already been determined.
  33. If not, it updates that variable with the name.
  34. It does this for the UNICODE and the ANSI versions.
  35. Arguments:
  36. NONE
  37. Return Value:
  38. NONE
  39. --*/
  40. {
  41. PUNICODE_STRING pNameU;
  42. PANSI_STRING pNameA;
  43. LPSTR szName;
  44. LPWSTR wszName;
  45. DWORD dwStatus;
  46. //
  47. // If this fails, we're leaking
  48. //
  49. ASSERT(pGlobalComputerNameU == NULL && pGlobalComputerNameA == NULL);
  50. pNameU = MIDL_user_allocate (sizeof (UNICODE_STRING));
  51. pNameA = MIDL_user_allocate (sizeof (ANSI_STRING));
  52. if ((pNameU != NULL) && (pNameA != NULL)) {
  53. dwStatus = ElfpGetComputerName(&szName, &wszName);
  54. if (dwStatus == NO_ERROR) {
  55. //
  56. // ElfpComputerName has allocated a buffer to contain the
  57. // ASCII name of the computer. We use that for the ANSI
  58. // string structure.
  59. //
  60. RtlInitAnsiString ( pNameA, szName );
  61. RtlInitUnicodeString ( pNameU, wszName );
  62. } else {
  63. //
  64. // We could not get the computer name for some reason. Set up
  65. // the golbal pointer to point to the NULL string.
  66. //
  67. RtlInitAnsiString ( pNameA, "\0");
  68. RtlInitUnicodeString ( pNameU, L"\0");
  69. }
  70. pGlobalComputerNameU = pNameU;
  71. pGlobalComputerNameA = pNameA;
  72. }
  73. else {
  74. //
  75. // In case one of the two was allocated.
  76. //
  77. MIDL_user_free (pNameU);
  78. MIDL_user_free (pNameA);
  79. }
  80. }
  81. PUNICODE_STRING
  82. TmpGetComputerNameW ( )
  83. /*++
  84. Routine Description:
  85. This routine gets the UNICODE name of the computer. It checks the global
  86. variable to see if the computer name has already been determined.
  87. If not, it calls the worker routine to do that.
  88. Arguments:
  89. NONE
  90. Return Value:
  91. Returns a pointer to the computer name, or a NULL.
  92. --*/
  93. {
  94. if (pGlobalComputerNameU == NULL) {
  95. w_GetComputerName();
  96. }
  97. return (pGlobalComputerNameU);
  98. }
  99. PANSI_STRING
  100. TmpGetComputerNameA ( )
  101. /*++
  102. Routine Description:
  103. This routine gets the ANSI name of the computer. It checks the global
  104. variable to see if the computer name has already been determined.
  105. If not, it calls the worker routine to do that.
  106. Arguments:
  107. NONE
  108. Return Value:
  109. Returns a pointer to the computer name, or a NULL.
  110. --*/
  111. {
  112. if (pGlobalComputerNameA == NULL) {
  113. w_GetComputerName();
  114. }
  115. return (pGlobalComputerNameA);
  116. }
  117. //
  118. // These APIs only have one interface, since they don't take or return strings
  119. //
  120. NTSTATUS
  121. ElfNumberOfRecords(
  122. IN HANDLE LogHandle,
  123. OUT PULONG NumberOfRecords
  124. )
  125. {
  126. NTSTATUS status;
  127. //
  128. // Make sure the output pointer is valid
  129. //
  130. if (!NumberOfRecords) {
  131. return(STATUS_INVALID_PARAMETER);
  132. }
  133. //
  134. // Do the RPC call with an exception handler since RPC will raise an
  135. // exception if anything fails. It is up to us to figure out what
  136. // to do once the exception is raised.
  137. //
  138. RpcTryExcept {
  139. // Call service entry point
  140. status = ElfrNumberOfRecords (
  141. (IELF_HANDLE) LogHandle,
  142. NumberOfRecords
  143. );
  144. }
  145. RpcExcept (1) {
  146. status = I_RpcMapWin32Status(RpcExceptionCode());
  147. }
  148. RpcEndExcept
  149. return (status);
  150. }
  151. NTSTATUS
  152. ElfOldestRecord(
  153. IN HANDLE LogHandle,
  154. OUT PULONG OldestRecordNumber
  155. )
  156. {
  157. NTSTATUS status;
  158. //
  159. //
  160. // Make sure the output pointer is valid
  161. //
  162. if (!OldestRecordNumber) {
  163. return(STATUS_INVALID_PARAMETER);
  164. }
  165. // Do the RPC call with an exception handler since RPC will raise an
  166. // exception if anything fails. It is up to us to figure out what
  167. // to do once the exception is raised.
  168. //
  169. RpcTryExcept {
  170. // Call service entry point
  171. status = ElfrOldestRecord (
  172. (IELF_HANDLE) LogHandle,
  173. OldestRecordNumber
  174. );
  175. }
  176. RpcExcept (1) {
  177. status = I_RpcMapWin32Status(RpcExceptionCode());
  178. }
  179. RpcEndExcept
  180. return (status);
  181. }
  182. NTSTATUS
  183. ElfChangeNotify(
  184. IN HANDLE LogHandle,
  185. IN HANDLE Event
  186. )
  187. {
  188. NTSTATUS status;
  189. RPC_CLIENT_ID RpcClientId;
  190. CLIENT_ID ClientId;
  191. //
  192. // Map the handles to something that RPC can understand
  193. //
  194. ClientId = NtCurrentTeb()->ClientId;
  195. RpcClientId.UniqueProcess = (ULONG)((ULONG_PTR)ClientId.UniqueProcess);
  196. RpcClientId.UniqueThread = (ULONG)((ULONG_PTR)ClientId.UniqueThread);
  197. //
  198. // Do the RPC call with an exception handler since RPC will raise an
  199. // exception if anything fails. It is up to us to figure out what
  200. // to do once the exception is raised.
  201. //
  202. RpcTryExcept {
  203. // Call service entry point
  204. status = ElfrChangeNotify (
  205. (IELF_HANDLE)((ULONG_PTR)LogHandle),
  206. RpcClientId,
  207. (DWORD)(ULONG_PTR)Event
  208. );
  209. }
  210. RpcExcept (1) {
  211. status = I_RpcMapWin32Status(RpcExceptionCode());
  212. }
  213. RpcEndExcept
  214. return (status);
  215. }
  216. NTSTATUS
  217. ElfGetLogInformation(
  218. IN HANDLE LogHandle,
  219. IN ULONG InfoLevel,
  220. OUT PVOID lpBuffer,
  221. IN ULONG cbBufSize,
  222. OUT PULONG pcbBytesNeeded
  223. )
  224. {
  225. NTSTATUS ntStatus;
  226. //
  227. // Make sure the Infolevel is valid
  228. //
  229. switch (InfoLevel) {
  230. case EVENTLOG_FULL_INFO:
  231. RpcTryExcept {
  232. // Call service entry point
  233. ntStatus = ElfrGetLogInformation(
  234. (IELF_HANDLE) LogHandle,
  235. InfoLevel,
  236. lpBuffer,
  237. cbBufSize,
  238. pcbBytesNeeded);
  239. }
  240. RpcExcept (1) {
  241. ntStatus = I_RpcMapWin32Status(RpcExceptionCode());
  242. }
  243. RpcEndExcept
  244. break;
  245. default:
  246. ntStatus = STATUS_INVALID_LEVEL;
  247. break;
  248. }
  249. return ntStatus;
  250. }
  251. //
  252. // UNICODE APIs
  253. //
  254. NTSTATUS
  255. ElfOpenEventLogW (
  256. IN PUNICODE_STRING UNCServerName,
  257. IN PUNICODE_STRING LogName,
  258. OUT PHANDLE LogHandle
  259. )
  260. /*++
  261. Routine Description:
  262. This is the client DLL entry point for the ElfOpenEventLog API.
  263. It creates an RPC binding for the server specified, and stores that
  264. and additional data away. It returns a handle to the caller that can
  265. be used to later on access the handle-specific information.
  266. Arguments:
  267. UNCServerName - Server with which to bind for subsequent operations.
  268. LogName - Supplies the name of the module for the logfile
  269. to associate with this handle.
  270. LogHandle - Location where log handle is to be returned.
  271. Return Value:
  272. Returns an NTSTATUS code and, if no error, a handle that can be used
  273. for subsequent Elf API calls.
  274. --*/
  275. {
  276. NTSTATUS status = STATUS_SUCCESS;
  277. NTSTATUS ApiStatus;
  278. UNICODE_STRING RegModuleName;
  279. EVENTLOG_HANDLE_W ServerNameString;
  280. BOOLEAN fWasEnabled = FALSE;
  281. BOOL fIsSecurityLog;
  282. //
  283. // Make sure input & output pointers are valid
  284. //
  285. if (!LogHandle || !LogName || LogName->Length == 0) {
  286. return(STATUS_INVALID_PARAMETER);
  287. }
  288. if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
  289. ServerNameString = UNCServerName->Buffer;
  290. } else {
  291. ServerNameString = NULL;
  292. }
  293. RtlInitUnicodeString( &RegModuleName, UNICODE_NULL);
  294. // Call service via RPC. Pass in major and minor version numbers.
  295. *LogHandle = NULL; // Must be NULL so RPC fills it in
  296. fIsSecurityLog = (_wcsicmp(ELF_SECURITY_MODULE_NAME, LogName->Buffer) == 0);
  297. if (fIsSecurityLog) {
  298. //
  299. // Tacitly attempt to enable the SE_SECURITY_PRIVILEGE so we can
  300. // can check it on the server side. We ignore the return value
  301. // because it's possible for this call to fail here but for the
  302. // user to have this privilege if the log is on a remote server.
  303. //
  304. // Note that we make this call on behalf of the client to avoid
  305. // a regression when we check for the privilege on the server
  306. // side -- without this call, 3rd party apps that successfully
  307. // called this API before would fail. Under normal circumstances,
  308. // this is not an encouraged practice.
  309. //
  310. //
  311. // -- This should really be done via ImpersonateSelf()
  312. // and adjusting the thread token
  313. //
  314. ApiStatus = RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
  315. TRUE,
  316. FALSE,
  317. &fWasEnabled);
  318. }
  319. //
  320. // Do the RPC call with an exception handler since RPC will raise an
  321. // exception if anything fails. It is up to us to figure out what
  322. // to do once the exception is raised.
  323. //
  324. RpcTryExcept {
  325. status = ElfrOpenELW(
  326. ServerNameString,
  327. (PRPC_UNICODE_STRING) LogName,
  328. (PRPC_UNICODE_STRING) &RegModuleName,
  329. ELF_VERSION_MAJOR,
  330. ELF_VERSION_MINOR,
  331. (PIELF_HANDLE) LogHandle
  332. );
  333. }
  334. RpcExcept (1) {
  335. status = I_RpcMapWin32Status(RpcExceptionCode());
  336. }
  337. RpcEndExcept
  338. if (fIsSecurityLog && NT_SUCCESS(ApiStatus)) {
  339. //
  340. // Restore the state
  341. //
  342. RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
  343. fWasEnabled,
  344. FALSE,
  345. &fWasEnabled);
  346. }
  347. return (status);
  348. }
  349. NTSTATUS
  350. ElfRegisterEventSourceW (
  351. IN PUNICODE_STRING UNCServerName,
  352. IN PUNICODE_STRING ModuleName,
  353. OUT PHANDLE LogHandle
  354. )
  355. /*++
  356. Routine Description:
  357. This is the client DLL entry point for the ElfRegisterEventSource API.
  358. It creates an RPC binding for the server specified, and stores that
  359. and additional data away. It returns a handle to the caller that can
  360. be used to later on access the handle-specific information.
  361. Arguments:
  362. UNCServerName - Server with which to bind for subsequent operations.
  363. ModuleName - Supplies the name of the module to associate with
  364. this handle.
  365. LogHandle - Location where log handle is to be returned.
  366. Return Value:
  367. Returns an NTSTATUS code and, if no error, a handle that can be used
  368. for subsequent Elf API calls.
  369. --*/
  370. {
  371. NTSTATUS status = STATUS_SUCCESS;
  372. UNICODE_STRING RegModuleName;
  373. EVENTLOG_HANDLE_W ServerNameString;
  374. //
  375. // Make sure input & output pointers are valid
  376. //
  377. if (!LogHandle || !ModuleName || ModuleName->Length == 0) {
  378. return(STATUS_INVALID_PARAMETER);
  379. }
  380. if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
  381. ServerNameString = UNCServerName->Buffer;
  382. } else {
  383. ServerNameString = NULL;
  384. }
  385. RtlInitUnicodeString( &RegModuleName, UNICODE_NULL);
  386. // Call service via RPC. Pass in major and minor version numbers.
  387. *LogHandle = NULL; // Must be NULL so RPC fills it in
  388. //
  389. // Do the RPC call with an exception handler since RPC will raise an
  390. // exception if anything fails. It is up to us to figure out what
  391. // to do once the exception is raised.
  392. //
  393. RpcTryExcept {
  394. status = ElfrRegisterEventSourceW(
  395. ServerNameString,
  396. (PRPC_UNICODE_STRING)ModuleName,
  397. (PRPC_UNICODE_STRING)&RegModuleName,
  398. ELF_VERSION_MAJOR,
  399. ELF_VERSION_MINOR,
  400. (PIELF_HANDLE) LogHandle
  401. );
  402. }
  403. RpcExcept (1) {
  404. status = I_RpcMapWin32Status(RpcExceptionCode());
  405. }
  406. RpcEndExcept
  407. return (status);
  408. }
  409. NTSTATUS
  410. ElfOpenBackupEventLogW (
  411. IN PUNICODE_STRING UNCServerName,
  412. IN PUNICODE_STRING BackupFileName,
  413. OUT PHANDLE LogHandle
  414. )
  415. /*++
  416. Routine Description:
  417. This is the client DLL entry point for the ElfOpenBackupEventLog API.
  418. It creates an RPC binding for the server specified, and stores that
  419. and additional data away. It returns a handle to the caller that can
  420. be used to later on access the handle-specific information.
  421. Arguments:
  422. UNCServerName - Server with which to bind for subsequent operations.
  423. BackupFileName - Supplies the filename of the module to associate with
  424. this handle.
  425. LogHandle - Location where log handle is to be returned.
  426. Return Value:
  427. Returns an NTSTATUS code and, if no error, a handle that can be used
  428. for subsequent Elf API calls.
  429. --*/
  430. {
  431. NTSTATUS status = STATUS_SUCCESS;
  432. EVENTLOG_HANDLE_W ServerNameString;
  433. //
  434. // Make sure input & output pointers are valid
  435. //
  436. if (!LogHandle || !BackupFileName || BackupFileName->Length == 0) {
  437. return(STATUS_INVALID_PARAMETER);
  438. }
  439. if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
  440. ServerNameString = UNCServerName->Buffer;
  441. } else {
  442. ServerNameString = NULL;
  443. }
  444. // Call service via RPC. Pass in major and minor version numbers.
  445. *LogHandle = NULL; // Must be NULL so RPC fills it in
  446. //
  447. // Do the RPC call with an exception handler since RPC will raise an
  448. // exception if anything fails. It is up to us to figure out what
  449. // to do once the exception is raised.
  450. //
  451. RpcTryExcept {
  452. status = ElfrOpenBELW(
  453. ServerNameString,
  454. (PRPC_UNICODE_STRING)BackupFileName,
  455. ELF_VERSION_MAJOR,
  456. ELF_VERSION_MINOR,
  457. (PIELF_HANDLE) LogHandle
  458. );
  459. }
  460. RpcExcept (1) {
  461. status = I_RpcMapWin32Status(RpcExceptionCode());
  462. }
  463. RpcEndExcept
  464. return (status);
  465. }
  466. NTSTATUS
  467. ElfClearEventLogFileW (
  468. IN HANDLE LogHandle,
  469. IN PUNICODE_STRING BackupFileName
  470. )
  471. /*++
  472. Routine Description:
  473. This is the client DLL entry point for the ElfClearEventLogFile API.
  474. The call is passed to the eventlog service on the appropriate server
  475. identified by LogHandle.
  476. Arguments:
  477. LogHandle - Handle returned from a previous "Open" call. This is
  478. used to identify the module and the server.
  479. BackupFileName - Name of the file to back up the current log file.
  480. NULL implies not to back up the file.
  481. Return Value:
  482. Returns an NTSTATUS code.
  483. --*/
  484. {
  485. NTSTATUS status;
  486. //
  487. // Do the RPC call with an exception handler since RPC will raise an
  488. // exception if anything fails. It is up to us to figure out what
  489. // to do once the exception is raised.
  490. //
  491. RpcTryExcept {
  492. // Call service entry point
  493. status = ElfrClearELFW (
  494. (IELF_HANDLE) LogHandle,
  495. (PRPC_UNICODE_STRING)BackupFileName
  496. );
  497. }
  498. RpcExcept (1) {
  499. status = I_RpcMapWin32Status(RpcExceptionCode());
  500. }
  501. RpcEndExcept
  502. return (status);
  503. }
  504. NTSTATUS
  505. ElfBackupEventLogFileW (
  506. IN HANDLE LogHandle,
  507. IN PUNICODE_STRING BackupFileName
  508. )
  509. /*++
  510. Routine Description:
  511. This is the client DLL entry point for the ElfBackupEventLogFile API.
  512. The call is passed to the eventlog service on the appropriate server
  513. identified by LogHandle.
  514. Arguments:
  515. LogHandle - Handle returned from a previous "Open" call. This is
  516. used to identify the module and the server.
  517. BackupFileName - Name of the file to back up the current log file.
  518. Return Value:
  519. Returns an NTSTATUS code.
  520. --*/
  521. {
  522. NTSTATUS status;
  523. NTSTATUS ApiStatus;
  524. BOOLEAN fWasEnabled;
  525. //
  526. // Make sure input pointers are valid
  527. //
  528. if (!BackupFileName || BackupFileName->Length == 0) {
  529. return(STATUS_INVALID_PARAMETER);
  530. }
  531. //
  532. // Tacitly attempt to enable the SE_BACKUP_PRIVILEGE so we can
  533. // can check it on the server side
  534. //
  535. // Note that we make this call on behalf of the client to avoid
  536. // a regression when we check for the privilege on the server
  537. // side -- without this call, 3rd party apps that successfully
  538. // called this API before would fail. Under normal circumstances,
  539. // this is not an encouraged practice.
  540. //
  541. //
  542. // -- This should really be done via ImpersonateSelf()
  543. // and adjusting the thread token
  544. //
  545. ApiStatus = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
  546. TRUE,
  547. FALSE,
  548. &fWasEnabled);
  549. //
  550. // Do the RPC call with an exception handler since RPC will raise an
  551. // exception if anything fails. It is up to us to figure out what
  552. // to do once the exception is raised.
  553. //
  554. RpcTryExcept {
  555. // Call service entry point
  556. status = ElfrBackupELFW (
  557. (IELF_HANDLE) LogHandle,
  558. (PRPC_UNICODE_STRING)BackupFileName);
  559. }
  560. RpcExcept (1) {
  561. status = I_RpcMapWin32Status(RpcExceptionCode());
  562. }
  563. RpcEndExcept
  564. //
  565. // Restore the client's privilege state to what it was before
  566. //
  567. if (NT_SUCCESS(ApiStatus)) {
  568. RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
  569. fWasEnabled,
  570. TRUE,
  571. &fWasEnabled);
  572. }
  573. return (status);
  574. }
  575. NTSTATUS
  576. ElfCloseEventLog (
  577. IN HANDLE LogHandle
  578. )
  579. /*++
  580. Routine Description:
  581. This is the client DLL entry point for the ElfCloseEventLog API.
  582. It closes the RPC binding, and frees any memory allocated for the
  583. handle.
  584. Arguments:
  585. LogHandle - Handle returned from a previous "Open" call.
  586. Return Value:
  587. Returns an NTSTATUS code.
  588. --*/
  589. {
  590. NTSTATUS status;
  591. //
  592. // Do the RPC call with an exception handler since RPC will raise an
  593. // exception if anything fails. It is up to us to figure out what
  594. // to do once the exception is raised.
  595. //
  596. RpcTryExcept {
  597. // Call server
  598. status = ElfrCloseEL (
  599. (PIELF_HANDLE) &LogHandle
  600. );
  601. }
  602. RpcExcept (1) {
  603. status = I_RpcMapWin32Status(RpcExceptionCode());
  604. }
  605. RpcEndExcept
  606. return (status);
  607. }
  608. NTSTATUS
  609. ElfDeregisterEventSource (
  610. IN HANDLE LogHandle
  611. )
  612. /*++
  613. Routine Description:
  614. This is the client DLL entry point for the ElfDeregisterEventSource API.
  615. It closes the RPC binding, and frees any memory allocated for the
  616. handle.
  617. Arguments:
  618. LogHandle - Handle returned from a previous "Open" call.
  619. Return Value:
  620. Returns an NTSTATUS code.
  621. --*/
  622. {
  623. NTSTATUS status;
  624. //
  625. // Do the RPC call with an exception handler since RPC will raise an
  626. // exception if anything fails. It is up to us to figure out what
  627. // to do once the exception is raised.
  628. //
  629. RpcTryExcept {
  630. // Call server
  631. status = ElfrDeregisterEventSource (
  632. (PIELF_HANDLE) &LogHandle
  633. );
  634. }
  635. RpcExcept (1) {
  636. status = I_RpcMapWin32Status(RpcExceptionCode());
  637. }
  638. RpcEndExcept
  639. return (status);
  640. }
  641. NTSTATUS
  642. ElfReadEventLogW (
  643. IN HANDLE LogHandle,
  644. IN ULONG ReadFlags,
  645. IN ULONG RecordNumber,
  646. OUT PVOID Buffer,
  647. IN ULONG NumberOfBytesToRead,
  648. OUT PULONG NumberOfBytesRead,
  649. OUT PULONG MinNumberOfBytesNeeded
  650. )
  651. /*++
  652. Routine Description:
  653. This is the client DLL entry point for the ElfReadEventLog API.
  654. Arguments:
  655. Return Value:
  656. Returns an NTSTATUS code.
  657. --*/
  658. {
  659. NTSTATUS status;
  660. ULONG FlagBits;
  661. //
  662. // Make sure the output pointers are valid
  663. //
  664. if (!Buffer || !NumberOfBytesRead || !MinNumberOfBytesNeeded) {
  665. return(STATUS_INVALID_PARAMETER);
  666. }
  667. //
  668. // Ensure that the ReadFlags we got are valid.
  669. // Make sure that one of each type of bit is set.
  670. //
  671. FlagBits = ReadFlags & (EVENTLOG_SEQUENTIAL_READ | EVENTLOG_SEEK_READ);
  672. if ((FlagBits > 2) || (FlagBits == 0)) {
  673. return(STATUS_INVALID_PARAMETER);
  674. }
  675. FlagBits = ReadFlags & (EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ);
  676. if ((FlagBits > 8) || (FlagBits == 0)) {
  677. return(STATUS_INVALID_PARAMETER);
  678. }
  679. //
  680. // Do the RPC call with an exception handler since RPC will raise an
  681. // exception if anything fails. It is up to us to figure out what
  682. // to do once the exception is raised.
  683. //
  684. RpcTryExcept {
  685. // Call service
  686. status = ElfrReadELW (
  687. (IELF_HANDLE) LogHandle,
  688. ReadFlags,
  689. RecordNumber,
  690. NumberOfBytesToRead,
  691. Buffer,
  692. NumberOfBytesRead,
  693. MinNumberOfBytesNeeded
  694. );
  695. }
  696. RpcExcept (1) {
  697. status = I_RpcMapWin32Status(RpcExceptionCode());
  698. }
  699. RpcEndExcept
  700. // Return status and bytes read/required.
  701. return (status);
  702. }
  703. NTSTATUS
  704. ElfReportEventW (
  705. IN HANDLE LogHandle,
  706. IN USHORT EventType,
  707. IN USHORT EventCategory OPTIONAL,
  708. IN ULONG EventID,
  709. IN PSID UserSid,
  710. IN USHORT NumStrings,
  711. IN ULONG DataSize,
  712. IN PUNICODE_STRING *Strings,
  713. IN PVOID Data,
  714. IN USHORT Flags,
  715. IN OUT PULONG RecordNumber OPTIONAL,
  716. IN OUT PULONG TimeWritten OPTIONAL
  717. )
  718. /*++
  719. Routine Description:
  720. This is the client DLL entry point for the ElfReportEvent API.
  721. Arguments:
  722. Return Value:
  723. Returns an NTSTATUS code.
  724. Note:
  725. The last three parameters (Flags, RecordNumber and TimeWritten) are
  726. designed to be used by Security Auditing for the implementation of
  727. paired events (associating a file open event with the subsequent file
  728. close). This will not be implemented in Product 1, but the API is
  729. defined to allow easier support of this in a later release.
  730. --*/
  731. {
  732. NTSTATUS status;
  733. PUNICODE_STRING pComputerNameU;
  734. LARGE_INTEGER Time;
  735. ULONG EventTime;
  736. //
  737. // Generate the time of the event. This is done on the client side
  738. // since that is where the event occurred.
  739. //
  740. NtQuerySystemTime(&Time);
  741. RtlTimeToSecondsSince1970(&Time,
  742. &EventTime
  743. );
  744. //
  745. // Generate the ComputerName of the client.
  746. // We have to do this in the client side since this call may be
  747. // remoted to another server and we would not necessarily have
  748. // the computer name there.
  749. //
  750. pComputerNameU = TmpGetComputerNameW();
  751. //
  752. // Do the RPC call with an exception handler since RPC will raise an
  753. // exception if anything fails. It is up to us to figure out what
  754. // to do once the exception is raised.
  755. //
  756. RpcTryExcept {
  757. // Call service
  758. status = ElfrReportEventW (
  759. (IELF_HANDLE) LogHandle,
  760. EventTime,
  761. EventType,
  762. EventCategory,
  763. EventID,
  764. NumStrings,
  765. DataSize,
  766. (PRPC_UNICODE_STRING)pComputerNameU,
  767. UserSid,
  768. (PRPC_UNICODE_STRING *)Strings,
  769. Data,
  770. Flags,
  771. RecordNumber,
  772. TimeWritten
  773. );
  774. }
  775. RpcExcept (1) {
  776. status = I_RpcMapWin32Status(RpcExceptionCode());
  777. }
  778. RpcEndExcept
  779. return (status);
  780. }
  781. //
  782. // ANSI APIs
  783. //
  784. NTSTATUS
  785. ElfOpenEventLogA (
  786. IN PANSI_STRING UNCServerName,
  787. IN PANSI_STRING LogName,
  788. OUT PHANDLE LogHandle
  789. )
  790. /*++
  791. Routine Description:
  792. This is the client DLL entry point for the ElfOpenEventLog API.
  793. It creates an RPC binding for the server specified, and stores that
  794. and additional data away. It returns a handle to the caller that can
  795. be used to later on access the handle-specific information.
  796. Arguments:
  797. UNCServerName - Server with which to bind for subsequent operations.
  798. LogName - Supplies the name of the module for the logfile to
  799. associate with this handle.
  800. LogHandle - Location where log handle is to be returned.
  801. Return Value:
  802. Returns an NTSTATUS code and, if no error, a handle that can be used
  803. for subsequent Elf API calls.
  804. --*/
  805. {
  806. NTSTATUS status = STATUS_SUCCESS;
  807. NTSTATUS ApiStatus;
  808. ANSI_STRING RegModuleName;
  809. EVENTLOG_HANDLE_A ServerNameString;
  810. BOOLEAN fWasEnabled = FALSE;
  811. BOOL fIsSecurityLog;
  812. //
  813. // Make sure input & output pointers are valid
  814. //
  815. if (!LogHandle || !LogName || LogName->Length == 0) {
  816. return(STATUS_INVALID_PARAMETER);
  817. }
  818. if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
  819. ServerNameString = UNCServerName->Buffer;
  820. } else {
  821. ServerNameString = NULL;
  822. }
  823. RtlInitAnsiString( &RegModuleName, ELF_APPLICATION_MODULE_NAME_ASCII );
  824. // Call service via RPC. Pass in major and minor version numbers.
  825. *LogHandle = NULL; // Must be NULL so RPC fills it in
  826. fIsSecurityLog = (_stricmp(ELF_SECURITY_MODULE_NAME_ASCII, LogName->Buffer) == 0);
  827. if (fIsSecurityLog) {
  828. //
  829. // Tacitly attempt to enable the SE_SECURITY_PRIVILEGE so we can
  830. // can check it on the server side. We ignore the return value
  831. // because it's possible for this call to fail here but for the
  832. // user to have this privilege if the log is on a remote server
  833. //
  834. // Note that we make this call on behalf of the client to avoid
  835. // a regression when we check for the privilege on the server
  836. // side -- without this call, 3rd party apps that successfully
  837. // called this API before would fail. Under normal circumstances,
  838. // this is not an encouraged practice.
  839. //
  840. //
  841. // -- This should really be done via ImpersonateSelf()
  842. // and adjusting the thread token
  843. //
  844. ApiStatus = RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
  845. TRUE,
  846. FALSE,
  847. &fWasEnabled);
  848. }
  849. //
  850. // Do the RPC call with an exception handler since RPC will raise an
  851. // exception if anything fails. It is up to us to figure out what
  852. // to do once the exception is raised.
  853. //
  854. RpcTryExcept {
  855. status = ElfrOpenELA (
  856. ServerNameString,
  857. (PRPC_STRING) LogName,
  858. (PRPC_STRING) &RegModuleName,
  859. ELF_VERSION_MAJOR,
  860. ELF_VERSION_MINOR,
  861. (PIELF_HANDLE) LogHandle);
  862. }
  863. RpcExcept (1) {
  864. status = I_RpcMapWin32Status(RpcExceptionCode());
  865. }
  866. RpcEndExcept
  867. if (fIsSecurityLog && NT_SUCCESS(ApiStatus)) {
  868. //
  869. // Restore the state
  870. //
  871. RtlAdjustPrivilege(SE_SECURITY_PRIVILEGE,
  872. fWasEnabled,
  873. FALSE,
  874. &fWasEnabled);
  875. }
  876. return (status);
  877. }
  878. NTSTATUS
  879. ElfRegisterEventSourceA (
  880. IN PANSI_STRING UNCServerName,
  881. IN PANSI_STRING ModuleName,
  882. OUT PHANDLE LogHandle
  883. )
  884. /*++
  885. Routine Description:
  886. This is the client DLL entry point for the ElfOpenEventLog API.
  887. It creates an RPC binding for the server specified, and stores that
  888. and additional data away. It returns a handle to the caller that can
  889. be used to later on access the handle-specific information.
  890. Arguments:
  891. UNCServerName - Server with which to bind for subsequent operations.
  892. ModuleName - Supplies the name of the module to associate with
  893. this handle.
  894. LogHandle - Location where log handle is to be returned.
  895. Return Value:
  896. Returns an NTSTATUS code and, if no error, a handle that can be used
  897. for subsequent Elf API calls.
  898. --*/
  899. {
  900. NTSTATUS status = STATUS_SUCCESS;
  901. ANSI_STRING RegModuleName;
  902. EVENTLOG_HANDLE_A ServerNameString;
  903. //
  904. // Make sure input & output pointers are valid
  905. //
  906. if (!LogHandle || !ModuleName || ModuleName->Length == 0) {
  907. return(STATUS_INVALID_PARAMETER);
  908. }
  909. if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
  910. ServerNameString = UNCServerName->Buffer;
  911. } else {
  912. ServerNameString = NULL;
  913. }
  914. RtlInitAnsiString( &RegModuleName, ELF_APPLICATION_MODULE_NAME_ASCII );
  915. if ( NT_SUCCESS (status) ) {
  916. // Call service via RPC. Pass in major and minor version numbers.
  917. *LogHandle = NULL; // Must be NULL so RPC fills it in
  918. //
  919. // Do the RPC call with an exception handler since RPC will raise an
  920. // exception if anything fails. It is up to us to figure out what
  921. // to do once the exception is raised.
  922. //
  923. RpcTryExcept {
  924. status = ElfrRegisterEventSourceA (
  925. ServerNameString,
  926. (PRPC_STRING)ModuleName,
  927. (PRPC_STRING)&RegModuleName,
  928. ELF_VERSION_MAJOR,
  929. ELF_VERSION_MINOR,
  930. (PIELF_HANDLE) LogHandle
  931. );
  932. }
  933. RpcExcept (1) {
  934. status = I_RpcMapWin32Status(RpcExceptionCode());
  935. }
  936. RpcEndExcept
  937. }
  938. return (status);
  939. }
  940. NTSTATUS
  941. ElfOpenBackupEventLogA (
  942. IN PANSI_STRING UNCServerName,
  943. IN PANSI_STRING FileName,
  944. OUT PHANDLE LogHandle
  945. )
  946. /*++
  947. Routine Description:
  948. This is the client DLL entry point for the ElfOpenBackupEventLog API.
  949. It creates an RPC binding for the server specified, and stores that
  950. and additional data away. It returns a handle to the caller that can
  951. be used to later on access the handle-specific information.
  952. Arguments:
  953. UNCServerName - Server with which to bind for subsequent operations.
  954. FileName - Supplies the filename of the logfile to associate with
  955. this handle.
  956. LogHandle - Location where log handle is to be returned.
  957. Return Value:
  958. Returns an NTSTATUS code and, if no error, a handle that can be used
  959. for subsequent Elf API calls.
  960. --*/
  961. {
  962. EVENTLOG_HANDLE_A ServerNameString;
  963. NTSTATUS status;
  964. //
  965. // Make sure input & output pointers are valid
  966. //
  967. if (!LogHandle || !FileName || FileName->Length == 0) {
  968. return(STATUS_INVALID_PARAMETER);
  969. }
  970. if ((UNCServerName != NULL) && (UNCServerName->Length != 0)) {
  971. ServerNameString = UNCServerName->Buffer;
  972. } else {
  973. ServerNameString = NULL;
  974. }
  975. // Call service via RPC. Pass in major and minor version numbers.
  976. *LogHandle = NULL; // Must be NULL so RPC fills it in
  977. //
  978. // Do the RPC call with an exception handler since RPC will raise an
  979. // exception if anything fails. It is up to us to figure out what
  980. // to do once the exception is raised.
  981. //
  982. RpcTryExcept {
  983. status = ElfrOpenBELA (
  984. ServerNameString,
  985. (PRPC_STRING)FileName,
  986. ELF_VERSION_MAJOR,
  987. ELF_VERSION_MINOR,
  988. (PIELF_HANDLE) LogHandle
  989. );
  990. }
  991. RpcExcept (1) {
  992. status = I_RpcMapWin32Status(RpcExceptionCode());
  993. }
  994. RpcEndExcept
  995. return (status);
  996. }
  997. NTSTATUS
  998. ElfClearEventLogFileA (
  999. IN HANDLE LogHandle,
  1000. IN PANSI_STRING BackupFileName
  1001. )
  1002. /*++
  1003. Routine Description:
  1004. This is the client DLL entry point for the ElfClearEventLogFile API.
  1005. The call is passed to the eventlog service on the appropriate server
  1006. identified by LogHandle.
  1007. Arguments:
  1008. LogHandle - Handle returned from a previous "Open" call. This is
  1009. used to identify the module and the server.
  1010. BackupFileName - Name of the file to back up the current log file.
  1011. NULL implies not to back up the file.
  1012. Return Value:
  1013. Returns an NTSTATUS code.
  1014. --*/
  1015. {
  1016. NTSTATUS status;
  1017. //
  1018. // Do the RPC call with an exception handler since RPC will raise an
  1019. // exception if anything fails. It is up to us to figure out what
  1020. // to do once the exception is raised.
  1021. //
  1022. RpcTryExcept {
  1023. // Call service entry point
  1024. status = ElfrClearELFA (
  1025. (IELF_HANDLE) LogHandle,
  1026. (PRPC_STRING)BackupFileName
  1027. );
  1028. }
  1029. RpcExcept (1) {
  1030. status = I_RpcMapWin32Status(RpcExceptionCode());
  1031. }
  1032. RpcEndExcept
  1033. return (status);
  1034. }
  1035. NTSTATUS
  1036. ElfBackupEventLogFileA (
  1037. IN HANDLE LogHandle,
  1038. IN PANSI_STRING BackupFileName
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. This is the client DLL entry point for the ElfBackupEventLogFile API.
  1043. The call is passed to the eventlog service on the appropriate server
  1044. identified by LogHandle.
  1045. Arguments:
  1046. LogHandle - Handle returned from a previous "Open" call. This is
  1047. used to identify the module and the server.
  1048. BackupFileName - Name of the file to back up the current log file.
  1049. Return Value:
  1050. Returns an NTSTATUS code.
  1051. --*/
  1052. {
  1053. NTSTATUS status;
  1054. NTSTATUS ApiStatus;
  1055. BOOLEAN fWasEnabled;
  1056. //
  1057. // Make sure input pointers are valid
  1058. //
  1059. if (!BackupFileName || BackupFileName->Length == 0) {
  1060. return(STATUS_INVALID_PARAMETER);
  1061. }
  1062. //
  1063. // Tacitly attempt to enable the SE_BACKUP_PRIVILEGE so we can
  1064. // can check it on the server side
  1065. //
  1066. // Note that we make this call on behalf of the client to avoid
  1067. // a regression when we check for the privilege on the server
  1068. // side -- without this call, 3rd party apps that successfully
  1069. // called this API before would fail. Under normal circumstances,
  1070. // this is not an encouraged practice.
  1071. //
  1072. //
  1073. // -- This should really be done via ImpersonateSelf()
  1074. // and adjusting the thread token
  1075. //
  1076. ApiStatus = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
  1077. TRUE,
  1078. FALSE,
  1079. &fWasEnabled);
  1080. //
  1081. // Do the RPC call with an exception handler since RPC will raise an
  1082. // exception if anything fails. It is up to us to figure out what
  1083. // to do once the exception is raised.
  1084. //
  1085. RpcTryExcept {
  1086. // Call service entry point
  1087. status = ElfrBackupELFA (
  1088. (IELF_HANDLE) LogHandle,
  1089. (PRPC_STRING)BackupFileName
  1090. );
  1091. }
  1092. RpcExcept (1) {
  1093. status = I_RpcMapWin32Status(RpcExceptionCode());
  1094. }
  1095. RpcEndExcept
  1096. //
  1097. // Restore the client's privilege state to what it was before
  1098. //
  1099. if (NT_SUCCESS(ApiStatus)) {
  1100. RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE,
  1101. fWasEnabled,
  1102. TRUE,
  1103. &fWasEnabled);
  1104. }
  1105. return (status);
  1106. }
  1107. NTSTATUS
  1108. ElfReadEventLogA (
  1109. IN HANDLE LogHandle,
  1110. IN ULONG ReadFlags,
  1111. IN ULONG RecordNumber,
  1112. OUT PVOID Buffer,
  1113. IN ULONG NumberOfBytesToRead,
  1114. OUT PULONG NumberOfBytesRead,
  1115. OUT PULONG MinNumberOfBytesNeeded
  1116. )
  1117. /*++
  1118. Routine Description:
  1119. This is the client DLL entry point for the ElfReadEventLog API.
  1120. Arguments:
  1121. Return Value:
  1122. Returns an NTSTATUS code.
  1123. --*/
  1124. {
  1125. NTSTATUS status;
  1126. ULONG FlagBits;
  1127. //
  1128. // Make sure the output pointers are valid
  1129. //
  1130. if (!Buffer || !NumberOfBytesRead || !MinNumberOfBytesNeeded) {
  1131. return(STATUS_INVALID_PARAMETER);
  1132. }
  1133. //
  1134. // Ensure that the ReadFlags we got are valid.
  1135. // Make sure that one of each type of bit is set.
  1136. //
  1137. FlagBits = ReadFlags & (EVENTLOG_SEQUENTIAL_READ | EVENTLOG_SEEK_READ);
  1138. if ( (FlagBits == (EVENTLOG_SEQUENTIAL_READ | EVENTLOG_SEEK_READ))
  1139. || (FlagBits == 0)) {
  1140. return(STATUS_INVALID_PARAMETER);
  1141. }
  1142. FlagBits = ReadFlags & (EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ);
  1143. if ( (FlagBits == (EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ))
  1144. || (FlagBits == 0)) {
  1145. return(STATUS_INVALID_PARAMETER);
  1146. }
  1147. //
  1148. // Do the RPC call with an exception handler since RPC will raise an
  1149. // exception if anything fails. It is up to us to figure out what
  1150. // to do once the exception is raised.
  1151. //
  1152. RpcTryExcept {
  1153. // Call service
  1154. status = ElfrReadELA (
  1155. (IELF_HANDLE) LogHandle,
  1156. ReadFlags,
  1157. RecordNumber,
  1158. NumberOfBytesToRead,
  1159. Buffer,
  1160. NumberOfBytesRead,
  1161. MinNumberOfBytesNeeded
  1162. );
  1163. }
  1164. RpcExcept (1) {
  1165. status = I_RpcMapWin32Status(RpcExceptionCode());
  1166. }
  1167. RpcEndExcept
  1168. // Return status and bytes read/required.
  1169. return (status);
  1170. }
  1171. NTSTATUS
  1172. ElfReportEventA (
  1173. IN HANDLE LogHandle,
  1174. IN USHORT EventType,
  1175. IN USHORT EventCategory OPTIONAL,
  1176. IN ULONG EventID,
  1177. IN PSID UserSid,
  1178. IN USHORT NumStrings,
  1179. IN ULONG DataSize,
  1180. IN PANSI_STRING *Strings,
  1181. IN PVOID Data,
  1182. IN USHORT Flags,
  1183. IN OUT PULONG RecordNumber OPTIONAL,
  1184. IN OUT PULONG TimeWritten OPTIONAL
  1185. )
  1186. /*++
  1187. Routine Description:
  1188. This is the client DLL entry point for the ElfReportEvent API.
  1189. Arguments:
  1190. Return Value:
  1191. Returns an NTSTATUS code.
  1192. Note:
  1193. The last three parameters (Flags, RecordNumber and TimeWritten) are
  1194. designed to be used by Security Auditing for the implementation of
  1195. paired events (associating a file open event with the subsequent file
  1196. close). This will not be implemented in Product 1, but the API is
  1197. defined to allow easier support of this in a later release.
  1198. --*/
  1199. {
  1200. NTSTATUS status;
  1201. PANSI_STRING pComputerNameA;
  1202. LARGE_INTEGER Time;
  1203. ULONG EventTime;
  1204. //
  1205. // Generate the time of the event. This is done on the client side
  1206. // since that is where the event occurred.
  1207. //
  1208. NtQuerySystemTime(&Time);
  1209. RtlTimeToSecondsSince1970(&Time,
  1210. &EventTime
  1211. );
  1212. //
  1213. // Generate the ComputerName of the client.
  1214. // We have to do this in the client side since this call may be
  1215. // remoted to another server and we would not necessarily have
  1216. // the computer name there.
  1217. //
  1218. pComputerNameA = TmpGetComputerNameA();
  1219. //
  1220. // Do the RPC call with an exception handler since RPC will raise an
  1221. // exception if anything fails. It is up to us to figure out what
  1222. // to do once the exception is raised.
  1223. //
  1224. RpcTryExcept {
  1225. // Call service
  1226. status = ElfrReportEventA (
  1227. (IELF_HANDLE) LogHandle,
  1228. EventTime,
  1229. EventType,
  1230. EventCategory,
  1231. EventID,
  1232. NumStrings,
  1233. DataSize,
  1234. (PRPC_STRING)pComputerNameA,
  1235. UserSid,
  1236. (PRPC_STRING*)Strings,
  1237. Data,
  1238. Flags,
  1239. RecordNumber,
  1240. TimeWritten
  1241. );
  1242. }
  1243. RpcExcept (1) {
  1244. status = I_RpcMapWin32Status(RpcExceptionCode());
  1245. }
  1246. RpcEndExcept
  1247. return (status);
  1248. }
  1249. /****
  1250. @func NTSTATUS | ElfRegisterClusterSvc| The cluster service registers
  1251. itself with the event log service at initialization by calling this api.
  1252. @parm IN PUNICODE_STRING | UNCServerName | Inidicates the server on which the
  1253. cluster service will register with the eventlog service. This must
  1254. be the local node.
  1255. @parm OUT PULONG | pulSize | A pointer to a long that returns the size of the
  1256. packed event information structure that is returned.
  1257. @parm OUT PPACKEDEVENTINFO | *ppPackedEventInfo| A pointer to the packed event information
  1258. structure for propagation is returned via this parameter.
  1259. @comm The elf client validates parameters and called the servier entry point.
  1260. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1261. @xref <f ElfrRegisterClusterSvc>
  1262. ****/
  1263. NTSTATUS
  1264. ElfRegisterClusterSvc (
  1265. IN PUNICODE_STRING UNCServerName,
  1266. OUT PULONG pulSize,
  1267. OUT PPACKEDEVENTINFO *ppPackedEventInfo
  1268. )
  1269. {
  1270. EVENTLOG_HANDLE_W ServerNameString;
  1271. NTSTATUS status;
  1272. if ((UNCServerName != NULL) && (UNCServerName->Length != 0))
  1273. {
  1274. ServerNameString = UNCServerName->Buffer;
  1275. }
  1276. else
  1277. {
  1278. ServerNameString = NULL;
  1279. }
  1280. //
  1281. // Do the RPC call with an exception handler since RPC will raise an
  1282. // exception if anything fails. It is up to us to figure out what
  1283. // to do once the exception is raised.
  1284. //
  1285. RpcTryExcept {
  1286. // Call service
  1287. status = ElfrRegisterClusterSvc (ServerNameString, pulSize,
  1288. (PBYTE *)ppPackedEventInfo);
  1289. }
  1290. RpcExcept (1) {
  1291. status = I_RpcMapWin32Status(RpcExceptionCode());
  1292. }
  1293. RpcEndExcept
  1294. return(status);
  1295. }
  1296. /****
  1297. @func NTSTATUS | ElfDeregisterClusterSvc| Before stopping the cluster
  1298. service deregisters itself for propagation of events from the
  1299. eventlog service.
  1300. @parm IN PUNICODE_STRING | UNCServerName | Inidicates the server on which the
  1301. cluster service will register with the eventlog service. This must
  1302. be on the local node.
  1303. @comm The elf client forwards this to the appropriate eventlog server entry point.
  1304. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1305. @xref <f ElfDeregisterClusterSvc> <f ElfrDeregisterClusterSvc>
  1306. ****/
  1307. NTSTATUS
  1308. ElfDeregisterClusterSvc(
  1309. IN PUNICODE_STRING UNCServerName
  1310. )
  1311. {
  1312. NTSTATUS status;
  1313. EVENTLOG_HANDLE_W ServerNameString;
  1314. if ((UNCServerName != NULL) && (UNCServerName->Length != 0))
  1315. {
  1316. ServerNameString = UNCServerName->Buffer;
  1317. }
  1318. else
  1319. {
  1320. ServerNameString = NULL;
  1321. }
  1322. //
  1323. // Do the RPC call with an exception handler since RPC will raise an
  1324. // exception if anything fails. It is up to us to figure out what
  1325. // to do once the exception is raised.
  1326. //
  1327. RpcTryExcept {
  1328. // Call service
  1329. status = ElfrDeregisterClusterSvc (ServerNameString);
  1330. }
  1331. RpcExcept (1) {
  1332. status = I_RpcMapWin32Status(RpcExceptionCode());
  1333. }
  1334. RpcEndExcept
  1335. return(status);
  1336. }
  1337. /****
  1338. @func NTSTATUS | ElfWriteClusterEvents| The cluster service calls this
  1339. api to log events reported at other nodes of the cluster.
  1340. @parm IN EVENTLOG_HANDLE_W | UNCServerName | Not used.
  1341. @parm IN ULONG | ulSize | The size of the packed event information structure.
  1342. @parm IN PACKEDEVENTINFO | pPackedEventInfo| A pointer to the packed event information
  1343. structure for propagation.
  1344. @comm The elf client validates the parameters and forwards this to the appropriate
  1345. entry point in the eventlog server.
  1346. @rdesc Returns a result code. ERROR_SUCCESS on success.
  1347. @xref
  1348. ****/
  1349. NTSTATUS
  1350. ElfWriteClusterEvents(
  1351. IN PUNICODE_STRING UNCServerName,
  1352. IN ULONG ulSize,
  1353. IN PPACKEDEVENTINFO pPackedEventInfo)
  1354. {
  1355. NTSTATUS status;
  1356. EVENTLOG_HANDLE_W ServerNameString;
  1357. //validate input parameters
  1358. if (!pPackedEventInfo || !ulSize || (pPackedEventInfo->ulSize != ulSize))
  1359. return(STATUS_INVALID_PARAMETER);
  1360. if ((UNCServerName != NULL) && (UNCServerName->Length != 0))
  1361. {
  1362. ServerNameString = UNCServerName->Buffer;
  1363. }
  1364. else
  1365. {
  1366. ServerNameString = NULL;
  1367. }
  1368. //
  1369. // Do the RPC call with an exception handler since RPC will raise an
  1370. // exception if anything fails. It is up to us to figure out what
  1371. // to do once the exception is raised.
  1372. //
  1373. RpcTryExcept {
  1374. // Call service
  1375. status = ElfrWriteClusterEvents (ServerNameString, ulSize,
  1376. (PBYTE)pPackedEventInfo);
  1377. }
  1378. RpcExcept (1) {
  1379. status = I_RpcMapWin32Status(RpcExceptionCode());
  1380. }
  1381. RpcEndExcept
  1382. return(status);
  1383. }