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.

1576 lines
35 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. EVENTAPI.C
  5. Abstract:
  6. This module contains the client ends of the EventLog APIs.
  7. Author:
  8. Rajen Shah (rajens) 24-Aug-1991
  9. Revision History:
  10. --*/
  11. #include "advapi.h"
  12. static WCHAR wszDosDevices[] = L"\\DosDevices\\";
  13. ULONG
  14. BaseSetLastNTError(
  15. IN NTSTATUS Status
  16. )
  17. /*++
  18. Routine Description:
  19. This API sets the "last error value" and the "last error string"
  20. based on the value of Status. For status codes that don't have
  21. a corresponding error string, the string is set to null.
  22. Arguments:
  23. Status - Supplies the status value to store as the last error value.
  24. Return Value:
  25. The corresponding Win32 error code that was stored in the
  26. "last error value" thread variable.
  27. --*/
  28. {
  29. ULONG dwErrorCode;
  30. dwErrorCode = RtlNtStatusToDosError( Status );
  31. SetLastError( dwErrorCode );
  32. return( dwErrorCode );
  33. }
  34. BOOL
  35. InitAnsiString(
  36. OUT PANSI_STRING DestinationString,
  37. IN PCSZ SourceString OPTIONAL
  38. )
  39. /*++
  40. Routine Description:
  41. The RtlInitAnsiString function initializes an NT counted string.
  42. The DestinationString is initialized to point to the SourceString
  43. and the Length and MaximumLength fields of DestinationString are
  44. initialized to the length of the SourceString, which is zero if
  45. SourceString is not specified.
  46. This is RtlInitAnsiString with a return status that rejects strings
  47. that are greater than 64K bytes.
  48. Arguments:
  49. DestinationString - Pointer to the counted string to initialize
  50. SourceString - Optional pointer to a null terminated string that
  51. the counted string is to point to.
  52. Return Value:
  53. None.
  54. --*/
  55. {
  56. ULONG Length = 0;
  57. DestinationString->Length = 0;
  58. DestinationString->Buffer = (PCHAR)SourceString;
  59. if (ARGUMENT_PRESENT( SourceString )) {
  60. while (*SourceString++) {
  61. Length++;
  62. }
  63. //
  64. // Make sure the length won't overflow a USHORT when converted to
  65. // UNICODE characters
  66. //
  67. if (Length * sizeof(WCHAR) > 0xFFFF) {
  68. return(FALSE);
  69. }
  70. DestinationString->Length = (USHORT) Length;
  71. DestinationString->MaximumLength = (USHORT) (Length + 1);
  72. }
  73. else {
  74. DestinationString->MaximumLength = 0;
  75. DestinationString->Length = 0;
  76. }
  77. return(TRUE);
  78. }
  79. BOOL
  80. InitUnicodeString(
  81. OUT PUNICODE_STRING DestinationString,
  82. IN PCWSTR SourceString OPTIONAL
  83. )
  84. /*++
  85. Routine Description:
  86. The InitUnicodeString function initializes an NT counted
  87. unicode string. The DestinationString is initialized to point to
  88. the SourceString and the Length and MaximumLength fields of
  89. DestinationString are initialized to the length of the SourceString,
  90. which is zero if SourceString is not specified.
  91. This is RtlInitUnicodeString with a return status that rejects strings
  92. that are greater than 64K bytes.
  93. Arguments:
  94. DestinationString - Pointer to the counted string to initialize
  95. SourceString - Optional pointer to a null terminated unicode string that
  96. the counted string is to point to.
  97. Return Value:
  98. None.
  99. --*/
  100. {
  101. ULONG Length = 0;
  102. DestinationString->Length = 0;
  103. DestinationString->Buffer = (PWSTR)SourceString;
  104. if (ARGUMENT_PRESENT( SourceString )) {
  105. while (*SourceString++) {
  106. Length += sizeof(*SourceString);
  107. }
  108. //
  109. // Make sure the length won't overflow a USHORT
  110. //
  111. if (Length > 0xFFFF) {
  112. return(FALSE);
  113. }
  114. DestinationString->Length = (USHORT) Length;
  115. DestinationString->MaximumLength =
  116. (USHORT) Length + (USHORT) sizeof(UNICODE_NULL);
  117. }
  118. else {
  119. DestinationString->MaximumLength = 0;
  120. DestinationString->Length = 0;
  121. }
  122. return(TRUE);
  123. }
  124. //
  125. // Single version API's (no strings)
  126. //
  127. BOOL
  128. CloseEventLog (
  129. HANDLE hEventLog
  130. )
  131. /*++
  132. Routine Description:
  133. This is the client DLL entry point for the WinCloseEventLog API.
  134. It closes the RPC binding, and frees any memory allocated for the
  135. handle.
  136. NOTE that there is no equivalent call for ANSI.
  137. Arguments:
  138. LogHandle - Handle returned from a previous "Open" call.
  139. Return Value:
  140. Returns TRUE if success, FALSE otherwise.
  141. --*/
  142. {
  143. NTSTATUS Status;
  144. BOOL ReturnValue;
  145. Status = ElfCloseEventLog (hEventLog);
  146. if ( !NT_SUCCESS(Status) ) {
  147. BaseSetLastNTError(Status);
  148. ReturnValue = FALSE;
  149. } else {
  150. ReturnValue = TRUE;
  151. }
  152. return ReturnValue;
  153. }
  154. BOOL
  155. DeregisterEventSource (
  156. HANDLE hEventLog
  157. )
  158. /*++
  159. Routine Description:
  160. This is the client DLL entry point for the DeregisterEventSource API.
  161. It closes the RPC binding, and frees any memory allocated for the
  162. handle.
  163. NOTE that there is no equivalent call for ANSI.
  164. Arguments:
  165. LogHandle - Handle returned from a previous "Open" call.
  166. Return Value:
  167. Returns TRUE if success, FALSE otherwise.
  168. --*/
  169. {
  170. NTSTATUS Status;
  171. BOOL ReturnValue;
  172. Status = ElfDeregisterEventSource (hEventLog);
  173. if ( !NT_SUCCESS(Status) ) {
  174. BaseSetLastNTError(Status);
  175. ReturnValue = FALSE;
  176. } else {
  177. ReturnValue = TRUE;
  178. }
  179. return ReturnValue;
  180. }
  181. BOOL
  182. NotifyChangeEventLog(
  183. HANDLE hEventLog,
  184. HANDLE hEvent
  185. )
  186. /*++
  187. Routine Description:
  188. Arguments:
  189. Return Value:
  190. --*/
  191. {
  192. NTSTATUS Status;
  193. Status = ElfChangeNotify(hEventLog,hEvent);
  194. if ( !NT_SUCCESS(Status) ) {
  195. BaseSetLastNTError(Status);
  196. return(FALSE);
  197. } else {
  198. return(TRUE);
  199. }
  200. }
  201. BOOL
  202. GetNumberOfEventLogRecords (
  203. HANDLE hEventLog,
  204. PDWORD NumberOfRecords
  205. )
  206. /*++
  207. Routine Description:
  208. This is the client DLL entry point that returns the number of records in
  209. the eventlog specified by hEventLog.
  210. NOTE that there is no equivalent call for ANSI.
  211. Arguments:
  212. LogHandle - Handle returned from a previous "Open" call.
  213. NumberOfRecords - Pointer to a DWORD to place the number of records.
  214. Return Value:
  215. Returns TRUE if success, FALSE otherwise.
  216. --*/
  217. {
  218. NTSTATUS Status;
  219. BOOL ReturnValue;
  220. Status = ElfNumberOfRecords (hEventLog, NumberOfRecords);
  221. if ( !NT_SUCCESS(Status) ) {
  222. BaseSetLastNTError(Status);
  223. ReturnValue = FALSE;
  224. } else {
  225. ReturnValue = TRUE;
  226. }
  227. return ReturnValue;
  228. }
  229. BOOL
  230. GetOldestEventLogRecord (
  231. HANDLE hEventLog,
  232. PDWORD OldestRecord
  233. )
  234. /*++
  235. Routine Description:
  236. This is the client DLL entry point that returns the record number of the
  237. oldest record in the eventlog specified by hEventLog.
  238. NOTE that there is no equivalent call for ANSI.
  239. Arguments:
  240. LogHandle - Handle returned from a previous "Open" call.
  241. OldestRecord - Pointer to a DWORD to place the record number of the
  242. oldest record in the eventlog specified by hEventLog
  243. Return Value:
  244. Returns TRUE if success, FALSE otherwise.
  245. --*/
  246. {
  247. NTSTATUS Status;
  248. BOOL ReturnValue;
  249. Status = ElfOldestRecord (hEventLog, OldestRecord);
  250. if ( !NT_SUCCESS(Status) ) {
  251. BaseSetLastNTError(Status);
  252. ReturnValue = FALSE;
  253. } else {
  254. ReturnValue = TRUE;
  255. }
  256. return ReturnValue;
  257. }
  258. BOOL
  259. GetEventLogInformation (
  260. HANDLE hEventLog,
  261. DWORD dwInfoLevel,
  262. PVOID lpBuffer,
  263. DWORD cbBufSize,
  264. LPDWORD pcbBytesNeeded
  265. )
  266. /*++
  267. Routine Description:
  268. This is the client DLL entry point that returns information about
  269. the eventlog specified by hEventLog.
  270. Arguments:
  271. LogHandle - Handle returned from a previous "Open" call.
  272. dwInfoLevel - Which information to return
  273. lpBuffer - Pointer to buffer to hold information
  274. cbBufSize - Size of buffer, in bytes
  275. pcbBytesNeeded - Number of bytes needed
  276. Return Value:
  277. Returns TRUE if success, FALSE otherwise.
  278. --*/
  279. {
  280. NTSTATUS ntStatus;
  281. ntStatus = ElfGetLogInformation(hEventLog,
  282. dwInfoLevel,
  283. lpBuffer,
  284. cbBufSize,
  285. pcbBytesNeeded);
  286. if (!NT_SUCCESS(ntStatus)) {
  287. BaseSetLastNTError(ntStatus);
  288. return FALSE;
  289. }
  290. return TRUE;
  291. }
  292. //
  293. // UNICODE APIs
  294. //
  295. BOOL
  296. ClearEventLogW (
  297. HANDLE hEventLog,
  298. LPCWSTR BackupFileName
  299. )
  300. /*++
  301. Routine Description:
  302. This is the client DLL entry point for the ClearEventLogFile API.
  303. The call is passed to the eventlog service on the appropriate server
  304. identified by LogHandle.
  305. Arguments:
  306. LogHandle - Handle returned from a previous "Open" call. This is
  307. used to identify the module and the server.
  308. BackupFileName - Name of the file to back up the current log file.
  309. NULL implies not to back up the file.
  310. Return Value:
  311. TRUE if success, FALSE otherwise.
  312. --*/
  313. {
  314. UNICODE_STRING Unicode;
  315. UNICODE_STRING DLUnicode; // Downlevel NT filename.
  316. NTSTATUS Status;
  317. BOOL ReturnValue;
  318. //
  319. // Turn the Dos filename into an NT filename
  320. //
  321. if (BackupFileName) {
  322. ReturnValue = RtlDosPathNameToNtPathName_U(BackupFileName, &Unicode, NULL, NULL);
  323. if (!BackupFileName || !ReturnValue) {
  324. SetLastError(ERROR_INVALID_PARAMETER);
  325. return(FALSE);
  326. }
  327. }
  328. else {
  329. Unicode.Length = 0;
  330. Unicode.MaximumLength = 0;
  331. Unicode.Buffer = NULL;
  332. }
  333. Status = ElfClearEventLogFileW (hEventLog, &Unicode);
  334. //
  335. // With NT 4.0, NT filenames are preceeded with \?? vs. \DosDevices
  336. // in 3.51. This retry logic exists for 3.51 machines which don't
  337. // recognize NT 4.0 filenames. The API should have passed Windows
  338. // filenames vs NT.
  339. //
  340. if (Status == STATUS_OBJECT_PATH_NOT_FOUND && BackupFileName != NULL) {
  341. DLUnicode.MaximumLength = (wcslen(BackupFileName) * sizeof(WCHAR)) +
  342. sizeof(wszDosDevices);
  343. DLUnicode.Buffer = RtlAllocateHeap(
  344. RtlProcessHeap(), 0,
  345. DLUnicode.MaximumLength);
  346. if (DLUnicode.Buffer != NULL) {
  347. wcscpy(DLUnicode.Buffer, wszDosDevices);
  348. wcscat(DLUnicode.Buffer, BackupFileName);
  349. DLUnicode.Length = DLUnicode.MaximumLength - sizeof(UNICODE_NULL);
  350. Status = ElfClearEventLogFileW (hEventLog, &DLUnicode);
  351. RtlFreeHeap(RtlProcessHeap(), 0, DLUnicode.Buffer);
  352. }
  353. else {
  354. Status = STATUS_NO_MEMORY;
  355. }
  356. }
  357. if ( !NT_SUCCESS(Status) ) {
  358. BaseSetLastNTError(Status);
  359. ReturnValue = FALSE;
  360. } else {
  361. ReturnValue = TRUE;
  362. }
  363. if (Unicode.MaximumLength) {
  364. RtlFreeHeap(RtlProcessHeap(), 0, Unicode.Buffer);
  365. }
  366. return ReturnValue;
  367. }
  368. BOOL
  369. BackupEventLogW (
  370. HANDLE hEventLog,
  371. LPCWSTR BackupFileName
  372. )
  373. /*++
  374. Routine Description:
  375. This is the client DLL entry point for the BackupEventLogFile API.
  376. The call is passed to the eventlog service on the appropriate server
  377. identified by LogHandle.
  378. Arguments:
  379. LogHandle - Handle returned from a previous "Open" call. This is
  380. used to identify the module and the server.
  381. BackupFileName - Name of the file to back up the current log file.
  382. Return Value:
  383. TRUE if success, FALSE otherwise.
  384. --*/
  385. {
  386. UNICODE_STRING Unicode;
  387. UNICODE_STRING DLUnicode; // Downlevel NT filename.
  388. NTSTATUS Status;
  389. BOOL ReturnValue = TRUE;
  390. //
  391. // Turn the Dos filename into an NT filename
  392. //
  393. if (BackupFileName) {
  394. ReturnValue = RtlDosPathNameToNtPathName_U(BackupFileName, &Unicode,
  395. NULL, NULL);
  396. }
  397. if (!BackupFileName || !ReturnValue) {
  398. SetLastError(ERROR_INVALID_PARAMETER);
  399. return(FALSE);
  400. }
  401. Status = ElfBackupEventLogFileW (hEventLog, &Unicode);
  402. //
  403. // With NT 4.0, NT filenames are preceeded with \?? vs. \DosDevices
  404. // in 3.51. This retry logic exists for 3.51 machines which don't
  405. // recognize NT 4.0 filenames. The API should have passed Windows
  406. // filenames vs NT.
  407. //
  408. if (Status == STATUS_OBJECT_PATH_NOT_FOUND && BackupFileName != NULL) {
  409. DLUnicode.MaximumLength = (wcslen(BackupFileName) * sizeof(WCHAR)) +
  410. sizeof(wszDosDevices);
  411. DLUnicode.Buffer = RtlAllocateHeap(
  412. RtlProcessHeap(), 0,
  413. DLUnicode.MaximumLength);
  414. if (DLUnicode.Buffer != NULL) {
  415. wcscpy(DLUnicode.Buffer, wszDosDevices);
  416. wcscat(DLUnicode.Buffer, BackupFileName);
  417. DLUnicode.Length = DLUnicode.MaximumLength - sizeof(UNICODE_NULL);
  418. Status = ElfBackupEventLogFileW (hEventLog, &DLUnicode);
  419. RtlFreeHeap(RtlProcessHeap(), 0, DLUnicode.Buffer);
  420. }
  421. else {
  422. Status = STATUS_NO_MEMORY;
  423. }
  424. }
  425. if ( !NT_SUCCESS(Status) ) {
  426. BaseSetLastNTError(Status);
  427. ReturnValue = FALSE;
  428. } else {
  429. ReturnValue = TRUE;
  430. }
  431. if (Unicode.MaximumLength) {
  432. RtlFreeHeap(RtlProcessHeap(), 0, Unicode.Buffer);
  433. }
  434. return ReturnValue;
  435. }
  436. HANDLE
  437. OpenEventLogW (
  438. LPCWSTR UNCServerName,
  439. LPCWSTR ModuleName
  440. )
  441. /*++
  442. Routine Description:
  443. This is the client DLL entry point for the WinOpenEventLog API.
  444. It creates an RPC binding for the server specified, and stores that
  445. and additional data away. It returns a handle to the caller that can
  446. be used to later on access the handle-specific information.
  447. Arguments:
  448. UNCServerName - Server with which to bind for subsequent operations.
  449. ModuleName - Supplies the name of the module to associate with
  450. this handle.
  451. Return Value:
  452. Returns a handle that can be used for subsequent Win API calls. If
  453. the handle is NULL, then an error occurred.
  454. --*/
  455. {
  456. UNICODE_STRING Unicode;
  457. UNICODE_STRING UnicodeModuleName;
  458. HANDLE LogHandle;
  459. NTSTATUS Status;
  460. HANDLE ReturnHandle;
  461. RtlInitUnicodeString(&UnicodeModuleName,ModuleName);
  462. RtlInitUnicodeString(&Unicode, UNCServerName);
  463. Status = ElfOpenEventLogW (
  464. &Unicode,
  465. &UnicodeModuleName,
  466. &LogHandle
  467. );
  468. if ( !NT_SUCCESS(Status) ) {
  469. BaseSetLastNTError(Status);
  470. ReturnHandle = (HANDLE)NULL;
  471. } else {
  472. ReturnHandle = (HANDLE)LogHandle;
  473. }
  474. return ReturnHandle;
  475. }
  476. HANDLE
  477. RegisterEventSourceW (
  478. LPCWSTR UNCServerName,
  479. LPCWSTR ModuleName
  480. )
  481. /*++
  482. Routine Description:
  483. This is the client DLL entry point for the RegisterEventSource API.
  484. It creates an RPC binding for the server specified, and stores that
  485. and additional data away. It returns a handle to the caller that can
  486. be used to later on access the handle-specific information.
  487. Arguments:
  488. UNCServerName - Server with which to bind for subsequent operations.
  489. ModuleName - Supplies the name of the module to associate with
  490. this handle.
  491. Return Value:
  492. Returns a handle that can be used for subsequent Win API calls. If
  493. the handle is NULL, then an error occurred.
  494. --*/
  495. {
  496. UNICODE_STRING Unicode;
  497. UNICODE_STRING UnicodeModuleName;
  498. HANDLE LogHandle;
  499. NTSTATUS Status;
  500. HANDLE ReturnHandle;
  501. RtlInitUnicodeString(&UnicodeModuleName,ModuleName);
  502. RtlInitUnicodeString(&Unicode, UNCServerName);
  503. Status = ElfRegisterEventSourceW (
  504. &Unicode,
  505. &UnicodeModuleName,
  506. &LogHandle
  507. );
  508. if ( !NT_SUCCESS(Status) ) {
  509. BaseSetLastNTError(Status);
  510. ReturnHandle = (HANDLE)NULL;
  511. } else {
  512. ReturnHandle = (HANDLE)LogHandle;
  513. }
  514. return ReturnHandle;
  515. }
  516. HANDLE
  517. OpenBackupEventLogW (
  518. LPCWSTR UNCServerName,
  519. LPCWSTR FileName
  520. )
  521. /*++
  522. Routine Description:
  523. This is the client DLL entry point for the OpenBackupEventLog API.
  524. It creates an RPC binding for the server specified, and stores that
  525. and additional data away. It returns a handle to the caller that can
  526. be used to later on access the handle-specific information.
  527. Arguments:
  528. UNCServerName - Server with which to bind for subsequent operations.
  529. FileName - Supplies the filename of the logfile to associate with
  530. this handle.
  531. Return Value:
  532. Returns a handle that can be used for subsequent Win API calls. If
  533. the handle is NULL, then an error occurred.
  534. --*/
  535. {
  536. UNICODE_STRING Unicode;
  537. UNICODE_STRING UnicodeFileName;
  538. UNICODE_STRING DLUnicode; // Downlevel NT filename.
  539. HANDLE LogHandle;
  540. NTSTATUS Status = STATUS_SUCCESS;
  541. HANDLE ReturnHandle;
  542. RtlInitUnicodeString(&Unicode, UNCServerName);
  543. RtlInitUnicodeString(&UnicodeFileName, NULL);
  544. //
  545. // Turn the Dos filename into an NT filename if it was given
  546. //
  547. if (FileName)
  548. {
  549. if (!RtlDosPathNameToNtPathName_U(FileName, &UnicodeFileName, NULL, NULL))
  550. {
  551. Status = STATUS_OBJECT_NAME_INVALID;
  552. }
  553. }
  554. if (NT_SUCCESS(Status))
  555. {
  556. Status = ElfOpenBackupEventLogW (
  557. &Unicode,
  558. &UnicodeFileName,
  559. &LogHandle
  560. );
  561. //
  562. // With NT 4.0, NT filenames are preceeded with \?? vs. \DosDevices
  563. // in 3.51. This retry logic exists for 3.51 machines which don't
  564. // recognize NT 4.0 filenames. The API should have passed Windows
  565. // filenames vs NT.
  566. //
  567. if (Status == STATUS_OBJECT_PATH_NOT_FOUND && FileName != NULL)
  568. {
  569. DLUnicode.MaximumLength = (wcslen(FileName) * sizeof(WCHAR)) +
  570. sizeof(wszDosDevices);
  571. DLUnicode.Buffer = RtlAllocateHeap(
  572. RtlProcessHeap(), 0,
  573. DLUnicode.MaximumLength);
  574. if (DLUnicode.Buffer != NULL)
  575. {
  576. wcscpy(DLUnicode.Buffer, wszDosDevices);
  577. wcscat(DLUnicode.Buffer, FileName);
  578. DLUnicode.Length = DLUnicode.MaximumLength - sizeof(UNICODE_NULL);
  579. Status = ElfOpenBackupEventLogW (
  580. &Unicode,
  581. &DLUnicode,
  582. &LogHandle
  583. );
  584. RtlFreeHeap(RtlProcessHeap(), 0, DLUnicode.Buffer);
  585. }
  586. else
  587. {
  588. Status = STATUS_NO_MEMORY;
  589. }
  590. }
  591. }
  592. if (!NT_SUCCESS(Status))
  593. {
  594. BaseSetLastNTError(Status);
  595. ReturnHandle = NULL;
  596. }
  597. else
  598. {
  599. ReturnHandle = LogHandle;
  600. }
  601. if (UnicodeFileName.MaximumLength)
  602. {
  603. RtlFreeHeap(RtlProcessHeap(), 0, UnicodeFileName.Buffer);
  604. }
  605. return ReturnHandle;
  606. }
  607. BOOL
  608. ReadEventLogW (
  609. HANDLE hEventLog,
  610. DWORD dwReadFlags,
  611. DWORD dwRecordOffset,
  612. LPVOID lpBuffer,
  613. DWORD nNumberOfBytesToRead,
  614. DWORD *pnBytesRead,
  615. DWORD *pnMinNumberOfBytesNeeded
  616. )
  617. /*++
  618. Routine Description:
  619. This is the client DLL entry point for the WinreadEventLog API.
  620. Arguments:
  621. Return Value:
  622. Returns count of bytes read. Zero of none read.
  623. --*/
  624. {
  625. NTSTATUS Status;
  626. BOOL ReturnValue;
  627. Status = ElfReadEventLogW (
  628. hEventLog,
  629. dwReadFlags,
  630. dwRecordOffset,
  631. lpBuffer,
  632. nNumberOfBytesToRead,
  633. pnBytesRead,
  634. pnMinNumberOfBytesNeeded
  635. );
  636. if ( !NT_SUCCESS(Status) ) {
  637. BaseSetLastNTError(Status);
  638. ReturnValue = FALSE;
  639. } else {
  640. ReturnValue = TRUE;
  641. }
  642. return ReturnValue;
  643. }
  644. BOOL
  645. ReportEventW (
  646. HANDLE hEventLog,
  647. WORD wType,
  648. WORD wCategory OPTIONAL,
  649. DWORD dwEventID,
  650. PSID lpUserSid OPTIONAL,
  651. WORD wNumStrings,
  652. DWORD dwDataSize,
  653. LPCWSTR *lpStrings OPTIONAL,
  654. LPVOID lpRawData OPTIONAL
  655. )
  656. /*++
  657. Routine Description:
  658. This is the client DLL entry point for the ReportEvent API.
  659. Arguments:
  660. Return Value:
  661. Returns TRUE if success, FALSE otherwise.
  662. --*/
  663. {
  664. NTSTATUS Status = STATUS_SUCCESS;
  665. BOOL ReturnValue;
  666. PUNICODE_STRING *pUStrings;
  667. ULONG i;
  668. ULONG AllocatedStrings;
  669. //
  670. // Convert the array of strings to an array of PUNICODE_STRINGs
  671. // before calling ElfReportEventW.
  672. //
  673. pUStrings = RtlAllocateHeap(
  674. RtlProcessHeap(), 0,
  675. wNumStrings * sizeof(PUNICODE_STRING)
  676. );
  677. if (pUStrings) {
  678. //
  679. // Guard the memory allocation above while we peruse the user's
  680. // buffer. If not, we'd leak it on an exception.
  681. //
  682. try {
  683. //
  684. // For each string passed in, allocate a UNICODE_STRING structure
  685. // and set it to the matching string.
  686. //
  687. for (AllocatedStrings = 0; AllocatedStrings < wNumStrings;
  688. AllocatedStrings++) {
  689. pUStrings[AllocatedStrings] = RtlAllocateHeap(
  690. RtlProcessHeap(), 0,
  691. sizeof(UNICODE_STRING)
  692. );
  693. if (pUStrings[AllocatedStrings]) {
  694. if (!InitUnicodeString(
  695. pUStrings[AllocatedStrings],
  696. lpStrings[AllocatedStrings]
  697. )) {
  698. //
  699. // This string was invalid (> 64K bytes) give up
  700. // and make sure we only free the ones we've already
  701. // allocated (including this last one)
  702. //
  703. AllocatedStrings++;
  704. Status = STATUS_INVALID_PARAMETER;
  705. break;
  706. }
  707. }
  708. }
  709. }
  710. except (EXCEPTION_EXECUTE_HANDLER) {
  711. Status = STATUS_INVALID_PARAMETER;
  712. }
  713. if (Status == STATUS_SUCCESS) {
  714. Status = ElfReportEventW (
  715. hEventLog,
  716. wType,
  717. wCategory,
  718. dwEventID,
  719. lpUserSid,
  720. wNumStrings,
  721. dwDataSize,
  722. pUStrings,
  723. lpRawData,
  724. 0, // Flags - Paired event
  725. NULL, // RecordNumber | support. Not
  726. NULL // TimeWritten - in P1
  727. );
  728. }
  729. //
  730. // Free the space allocated for the UNICODE strings
  731. // and then free the space for the array.
  732. //
  733. for (i = 0; i < AllocatedStrings; i++) {
  734. if (pUStrings[i])
  735. RtlFreeHeap (RtlProcessHeap(), 0, pUStrings[i]);
  736. }
  737. RtlFreeHeap (RtlProcessHeap(), 0, pUStrings);
  738. } else {
  739. Status = STATUS_NO_MEMORY;
  740. }
  741. if ( !NT_SUCCESS(Status) ) {
  742. BaseSetLastNTError(Status);
  743. ReturnValue = FALSE;
  744. } else {
  745. ReturnValue = TRUE;
  746. }
  747. return ReturnValue;
  748. }
  749. //
  750. // ANSI APIs
  751. //
  752. BOOL
  753. ClearEventLogA (
  754. HANDLE hEventLog,
  755. LPCSTR BackupFileName
  756. )
  757. /*++
  758. Routine Description:
  759. This is the client DLL entry point for the ClearEventLogFile API.
  760. The call is passed to the eventlog service on the appropriate server
  761. identified by LogHandle.
  762. Arguments:
  763. LogHandle - Handle returned from a previous "Open" call. This is
  764. used to identify the module and the server.
  765. BackupFileName - Name of the file to back up the current log file.
  766. NULL implies not to back up the file.
  767. Return Value:
  768. TRUE if success, FALSE otherwise.
  769. --*/
  770. {
  771. ANSI_STRING AnsiString;
  772. UNICODE_STRING UnicodeString;
  773. NTSTATUS Status;
  774. BOOL ReturnValue;
  775. //
  776. // Turn the backup filename into UNICODE
  777. //
  778. if (BackupFileName) {
  779. RtlInitAnsiString(&AnsiString, BackupFileName);
  780. Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString,
  781. TRUE);
  782. if ( !NT_SUCCESS(Status) ) {
  783. BaseSetLastNTError(Status);
  784. return(FALSE);
  785. }
  786. }
  787. else {
  788. RtlInitUnicodeString(&UnicodeString, NULL);
  789. }
  790. ReturnValue = ClearEventLogW (hEventLog, (LPCWSTR)UnicodeString.Buffer);
  791. RtlFreeUnicodeString(&UnicodeString);
  792. return(ReturnValue);
  793. }
  794. BOOL
  795. BackupEventLogA (
  796. HANDLE hEventLog,
  797. LPCSTR BackupFileName
  798. )
  799. /*++
  800. Routine Description:
  801. This is the client DLL entry point for the BackupEventLogFile API.
  802. The call is passed to the eventlog service on the appropriate server
  803. identified by LogHandle.
  804. Arguments:
  805. LogHandle - Handle returned from a previous "Open" call. This is
  806. used to identify the module and the server.
  807. BackupFileName - Name of the file to back up the current log file.
  808. Return Value:
  809. TRUE if success, FALSE otherwise.
  810. --*/
  811. {
  812. ANSI_STRING AnsiString;
  813. UNICODE_STRING UnicodeString;
  814. NTSTATUS Status;
  815. BOOL ReturnValue;
  816. //
  817. // Turn the backup filename into UNICODE
  818. //
  819. if (BackupFileName) {
  820. RtlInitAnsiString(&AnsiString, BackupFileName);
  821. Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString,
  822. TRUE);
  823. if ( !NT_SUCCESS(Status) ) {
  824. BaseSetLastNTError(Status);
  825. return(FALSE);
  826. }
  827. }
  828. else {
  829. RtlInitUnicodeString(&UnicodeString, NULL);
  830. }
  831. ReturnValue = BackupEventLogW (hEventLog, (LPCWSTR)UnicodeString.Buffer);
  832. RtlFreeUnicodeString(&UnicodeString);
  833. return(ReturnValue);
  834. }
  835. HANDLE
  836. OpenEventLogA (
  837. LPCSTR UNCServerName,
  838. LPCSTR ModuleName
  839. )
  840. /*++
  841. Routine Description:
  842. This is the client DLL entry point for the WinOpenEventLog API.
  843. It creates an RPC binding for the server specified, and stores that
  844. and additional data away. It returns a handle to the caller that can
  845. be used to later on access the handle-specific information.
  846. Arguments:
  847. UNCServerName - Server with which to bind for subsequent operations.
  848. ModuleName - Supplies the name of the module to associate with
  849. this handle.
  850. Return Value:
  851. Returns a handle that can be used for subsequent Win API calls. If
  852. the handle is NULL, then an error occurred.
  853. --*/
  854. {
  855. ANSI_STRING AnsiString;
  856. ANSI_STRING AnsiModuleName;
  857. NTSTATUS Status;
  858. HANDLE LogHandle;
  859. HANDLE ReturnHandle;
  860. RtlInitAnsiString(&AnsiModuleName,ModuleName);
  861. RtlInitAnsiString(&AnsiString, UNCServerName);
  862. Status = ElfOpenEventLogA (
  863. &AnsiString,
  864. &AnsiModuleName,
  865. &LogHandle
  866. );
  867. if ( !NT_SUCCESS(Status) ) {
  868. BaseSetLastNTError(Status);
  869. ReturnHandle = (HANDLE)NULL;
  870. } else {
  871. ReturnHandle = (HANDLE)LogHandle;
  872. }
  873. return ReturnHandle;
  874. }
  875. HANDLE
  876. RegisterEventSourceA (
  877. LPCSTR UNCServerName,
  878. LPCSTR ModuleName
  879. )
  880. /*++
  881. Routine Description:
  882. This is the client DLL entry point for the RegisterEventSource API.
  883. It creates an RPC binding for the server specified, and stores that
  884. and additional data away. It returns a handle to the caller that can
  885. be used to later on access the handle-specific information.
  886. Arguments:
  887. UNCServerName - Server with which to bind for subsequent operations.
  888. ModuleName - Supplies the name of the module to associate with
  889. this handle.
  890. Return Value:
  891. Returns a handle that can be used for subsequent Win API calls. If
  892. the handle is NULL, then an error occurred.
  893. --*/
  894. {
  895. ANSI_STRING AnsiString;
  896. ANSI_STRING AnsiModuleName;
  897. NTSTATUS Status;
  898. HANDLE LogHandle;
  899. HANDLE ReturnHandle;
  900. RtlInitAnsiString(&AnsiModuleName,ModuleName);
  901. RtlInitAnsiString(&AnsiString, UNCServerName);
  902. Status = ElfRegisterEventSourceA (
  903. &AnsiString,
  904. &AnsiModuleName,
  905. &LogHandle
  906. );
  907. if ( !NT_SUCCESS(Status) ) {
  908. BaseSetLastNTError(Status);
  909. ReturnHandle = (HANDLE)NULL;
  910. } else {
  911. ReturnHandle = (HANDLE)LogHandle;
  912. }
  913. return ReturnHandle;
  914. }
  915. HANDLE
  916. OpenBackupEventLogA (
  917. LPCSTR UNCServerName,
  918. LPCSTR FileName
  919. )
  920. /*++
  921. Routine Description:
  922. This is the client DLL entry point for the OpenBackupEventLog API.
  923. It creates an RPC binding for the server specified, and stores that
  924. and additional data away. It returns a handle to the caller that can
  925. be used to later on access the handle-specific information.
  926. Arguments:
  927. UNCServerName - Server with which to bind for subsequent operations.
  928. FileName - Supplies the filename of the logfile to associate with
  929. this handle.
  930. Return Value:
  931. Returns a handle that can be used for subsequent Win API calls. If
  932. the handle is NULL, then an error occurred.
  933. --*/
  934. {
  935. ANSI_STRING AnsiString;
  936. UNICODE_STRING UnicodeServerName;
  937. UNICODE_STRING UnicodeFileName;
  938. NTSTATUS Status;
  939. HANDLE ReturnHandle;
  940. //
  941. // Turn the servername into UNICODE
  942. //
  943. if (UNCServerName) {
  944. RtlInitAnsiString(&AnsiString, UNCServerName);
  945. Status = RtlAnsiStringToUnicodeString(&UnicodeServerName, &AnsiString,
  946. TRUE);
  947. if ( !NT_SUCCESS(Status) ) {
  948. BaseSetLastNTError(Status);
  949. return(NULL);
  950. }
  951. }
  952. else {
  953. RtlInitUnicodeString(&UnicodeServerName, NULL);
  954. }
  955. //
  956. // Turn the filename into UNICODE
  957. //
  958. if (FileName) {
  959. RtlInitAnsiString(&AnsiString, FileName);
  960. Status = RtlAnsiStringToUnicodeString(&UnicodeFileName, &AnsiString,
  961. TRUE);
  962. if ( !NT_SUCCESS(Status) ) {
  963. RtlFreeUnicodeString(&UnicodeServerName);
  964. BaseSetLastNTError(Status);
  965. return(NULL);
  966. }
  967. }
  968. else {
  969. RtlInitUnicodeString(&UnicodeFileName, NULL);
  970. }
  971. ReturnHandle = OpenBackupEventLogW ((LPCWSTR)UnicodeServerName.Buffer,
  972. (LPCWSTR)UnicodeFileName.Buffer);
  973. RtlFreeUnicodeString(&UnicodeServerName);
  974. RtlFreeUnicodeString(&UnicodeFileName);
  975. return(ReturnHandle);
  976. }
  977. BOOL
  978. ReadEventLogA (
  979. HANDLE hEventLog,
  980. DWORD dwReadFlags,
  981. DWORD dwRecordOffset,
  982. LPVOID lpBuffer,
  983. DWORD nNumberOfBytesToRead,
  984. DWORD *pnBytesRead,
  985. DWORD *pnMinNumberOfBytesNeeded
  986. )
  987. /*++
  988. Routine Description:
  989. This is the client DLL entry point for the WinreadEventLog API.
  990. Arguments:
  991. Return Value:
  992. Returns count of bytes read. Zero of none read.
  993. --*/
  994. {
  995. NTSTATUS Status;
  996. BOOL ReturnValue;
  997. Status = ElfReadEventLogA (
  998. hEventLog,
  999. dwReadFlags,
  1000. dwRecordOffset,
  1001. lpBuffer,
  1002. nNumberOfBytesToRead,
  1003. pnBytesRead,
  1004. pnMinNumberOfBytesNeeded
  1005. );
  1006. if ( !NT_SUCCESS(Status) ) {
  1007. BaseSetLastNTError(Status);
  1008. ReturnValue = FALSE;
  1009. } else {
  1010. ReturnValue = TRUE;
  1011. }
  1012. return ReturnValue;
  1013. }
  1014. BOOL
  1015. ReportEventA (
  1016. HANDLE hEventLog,
  1017. WORD wType,
  1018. WORD wCategory OPTIONAL,
  1019. DWORD dwEventID,
  1020. PSID lpUserSid OPTIONAL,
  1021. WORD wNumStrings,
  1022. DWORD dwDataSize,
  1023. LPCSTR *lpStrings OPTIONAL,
  1024. LPVOID lpRawData OPTIONAL
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. This is the client DLL entry point for the ReportEvent API.
  1029. Arguments:
  1030. Return Value:
  1031. Returns TRUE if success, FALSE otherwise.
  1032. --*/
  1033. {
  1034. NTSTATUS Status = STATUS_SUCCESS;
  1035. BOOL ReturnValue;
  1036. PANSI_STRING *pAStrings;
  1037. ULONG i;
  1038. ULONG AllocatedStrings;
  1039. //
  1040. // Convert the array of strings to an array of PANSI_STRINGs
  1041. // before calling ElfReportEventW.
  1042. //
  1043. pAStrings = RtlAllocateHeap(
  1044. RtlProcessHeap(), 0,
  1045. wNumStrings * sizeof(PANSI_STRING)
  1046. );
  1047. if (pAStrings) {
  1048. //
  1049. // Guard the memory allocation above while we peruse the user's
  1050. // buffer. If not, we'd leak it on an exception.
  1051. //
  1052. try {
  1053. //
  1054. // For each string passed in, allocate an ANSI_STRING structure
  1055. // and fill it in with the string.
  1056. //
  1057. for (AllocatedStrings = 0; AllocatedStrings < wNumStrings;
  1058. AllocatedStrings++) {
  1059. pAStrings[AllocatedStrings] = RtlAllocateHeap(
  1060. RtlProcessHeap(), 0,
  1061. sizeof(ANSI_STRING)
  1062. );
  1063. if (pAStrings[AllocatedStrings]) {
  1064. if (!InitAnsiString(
  1065. pAStrings[AllocatedStrings],
  1066. lpStrings[AllocatedStrings]
  1067. )) {
  1068. //
  1069. // This string was invalid (> 32K chars) give up
  1070. // and make sure we only free the ones we've already
  1071. // allocated (including this last one)
  1072. //
  1073. AllocatedStrings++;
  1074. Status = STATUS_INVALID_PARAMETER;
  1075. break;
  1076. }
  1077. }
  1078. }
  1079. }
  1080. except (EXCEPTION_EXECUTE_HANDLER) {
  1081. Status = STATUS_INVALID_PARAMETER;
  1082. }
  1083. if (Status == STATUS_SUCCESS) {
  1084. Status = ElfReportEventA (
  1085. hEventLog,
  1086. wType,
  1087. wCategory,
  1088. dwEventID,
  1089. lpUserSid,
  1090. wNumStrings,
  1091. dwDataSize,
  1092. pAStrings,
  1093. lpRawData,
  1094. 0, // Flags - Paired event
  1095. NULL, // RecordNumber | support. Not
  1096. NULL // TimeWritten - in P1
  1097. );
  1098. }
  1099. //
  1100. // Free all the memory that was allocated
  1101. //
  1102. for (i = 0; i < AllocatedStrings; i++) {
  1103. if (pAStrings[i])
  1104. RtlFreeHeap (RtlProcessHeap(), 0, pAStrings[i]);
  1105. }
  1106. RtlFreeHeap (RtlProcessHeap(), 0, pAStrings);
  1107. } else {
  1108. Status = STATUS_NO_MEMORY;
  1109. }
  1110. if ( !NT_SUCCESS(Status) ) {
  1111. BaseSetLastNTError(Status);
  1112. ReturnValue = FALSE;
  1113. } else {
  1114. ReturnValue = TRUE;
  1115. }
  1116. return ReturnValue;
  1117. }