Article View: comp.os.ms-windows.programmer.win32
Article #2176Re: Reading Event Logs?
From: R�gis Corbel
Date: Thu, 25 Jun 1998 00:00
Date: Thu, 25 Jun 1998 00:00
285 lines
13512 bytes
13512 bytes
--------------C74624BE9C24094D26031064
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hi Niklas,
Well if you look at VC++ documentation for EVENTLOGRECORD structure,
you'll find this :
typedef struct _EVENTLOGRECORD { // evlr
DWORD Length;
DWORD Reserved;
DWORD RecordNumber;
DWORD TimeGenerated;
DWORD TimeWritten;
DWORD EventID;
WORD EventType;
WORD NumStrings;
WORD EventCategory;
WORD ReservedFlags;
DWORD ClosingRecordNumber;
DWORD StringOffset;
DWORD UserSidLength;
DWORD UserSidOffset;
DWORD DataLength;
DWORD DataOffset;
//
// Then follow:
//
// TCHAR SourceName[]
// TCHAR Computername[]
// SID UserSid
// TCHAR Strings[]
// BYTE Data[]
// CHAR Pad[]
// DWORD Length;
//
} EVENTLOGRECORD;
You can see that the infos you're looking for are at the end of the
record. It is because these fields are length-variable. Sofar, the
StringOffset field gives you the address of the first byte of the first
string contained in that record, i.e. SourceName.
Hope it helps.
RC
(regis.corbel@cnet.francetelecom.fr)
Niklas Nihlen wrote:
>
>
> I'm writing a little application that needs to read the Windows NT 4.0
> Event Logs. I am using the OpenEventLog and ReadEventLog functions (se
> code below). But my problem is I don't manage to extract all the
> information that you can get if you inspect a event in Windows NT
> event wiever. Using code similar to the one below, I esaly get the
> date, time and source (who reported the event) but I don't manage to
> get the category, User, Computer and description.
> I would greatly appreciate any help on this problem!
>
>
> EVENTLOGRECORD *pevlr;
> BYTE bBuffer[BUFFER_SIZE];
> DWORD dwRead, dwNeeded, cRecords, dwThisRecord = 0;
>
> /* Open the Application event log. */
>
> h = OpenEventLog(NULL, "Application"); /* source */
> if (h == NULL)
> ErrorExit("could not open Application event log");
>
> pevlr = (EVENTLOGRECORD *) &bBuffer;
>
> /*
> * Opening the event log positions the file pointer
> * for this handle at the beginning of the log.
> *
> * Read records sequentially until there
> * are no more.
> */
>
> while (ReadEventLog(h, /* event log handle */
> EVENTLOG_FORWARDS_READ | /* reads forward */
> EVENTLOG_SEQUENTIAL_READ, /* sequential read */
> 0, /* ignored for sequential reads */
> pevlr, /* address of buffer */
> BUFFER_SIZE, /* size of buffer */
> &dwRead, /* count of bytes read */
> &dwNeeded)) { /* bytes in next record */
>
> while (dwRead > 0) {
>
> /*
> * Print the event ID, type, and source name.
> * The source name is just past the end of the
> * formal structure.
> */
>
> printf("%02d Event ID: 0x%08X ",
> dwThisRecord++, pevlr->EventID);
> printf("EventType: %d Source: %s\n",
> pevlr->EventType, (LPSTR) ((LPBYTE) pevlr +
> sizeof(EVENTLOGRECORD)));
>
> dwRead -= pevlr->Length;
> pevlr = (EVENTLOGRECORD *)
> ((LPBYTE) pevlr + pevlr->Length);
> }
>
> pevlr = (EVENTLOGRECORD *) &bBuffer;
> }
>
> CloseEventLog(h);
>
> Regards,
>
> Niklas Nihlen
> niklas@medcom.se
>
--------------C74624BE9C24094D26031064
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
<HTML>
Hi Niklas,
<P>Well if you look at VC++ documentation for EVENTLOGRECORD structure,
you'll find this :
<BR>typedef struct _EVENTLOGRECORD { // evlr
<BR> DWORD Length;
<BR> DWORD Reserved;
<BR> DWORD RecordNumber;
<BR> DWORD TimeGenerated;
<BR> DWORD TimeWritten;
<BR> DWORD EventID;
<BR> WORD EventType;
<BR> WORD NumStrings;
<BR> WORD EventCategory;
<BR> WORD ReservedFlags;
<BR> DWORD ClosingRecordNumber;
<BR> DWORD StringOffset;
<BR> DWORD UserSidLength;
<BR> DWORD UserSidOffset;
<BR> DWORD DataLength;
<BR> DWORD DataOffset;
<BR> //
<BR> // Then follow:
<BR> //
<BR> // TCHAR SourceName[]
<BR> // TCHAR Computername[]
<BR> // SID UserSid
<BR> // TCHAR Strings[]
<BR> // BYTE Data[]
<BR> // CHAR Pad[]
<BR> // DWORD Length;
<BR> //
<BR>} EVENTLOGRECORD;
<P>You can see that the infos you're looking for are at the end of the
record. It is because these fields are length-variable. Sofar, the StringOffset
field gives you the address of the first byte of the first string contained
in that record, i.e. SourceName.
<P>Hope it helps.
<P>RC
<BR>(regis.corbel@cnet.francetelecom.fr)
<P>Niklas Nihlen wrote:
<BLOCKQUOTE TYPE=CITE>
<P>I'm writing a little application that needs to read the Windows NT 4.0
Event Logs. I am using the OpenEventLog and ReadEventLog functions (se
code below). But my problem is I don't manage to extract all the information
that you can get if you inspect a event in Windows NT event wiever. Using
code similar to the one below, I esaly get the date, time and source (who
reported the event) but I don't manage to get the category, User, Computer
and description.
<BR>I would greatly appreciate any help on this problem!
<BR>
<DL><FONT FACE="Courier New,Courier">EVENTLOGRECORD *pevlr;</FONT>
<BR><FONT FACE="Courier New,Courier">BYTE bBuffer[BUFFER_SIZE];</FONT>
<BR><FONT FACE="Courier New,Courier">DWORD dwRead, dwNeeded, cRecords,
dwThisRecord = 0;</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier"> /* Open the Application
event log. */</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier"> h = OpenEventLog(NULL,
"Application"); /* source */</FONT>
<BR><FONT FACE="Courier New,Courier">
if (h == NULL)</FONT>
<BR><FONT FACE="Courier New,Courier">
ErrorExit("could not open Application event log");</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier"> pevlr = (EVENTLOGRECORD
*) &bBuffer;</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier"> /*</FONT>
<BR><FONT FACE="Courier New,Courier"> * Opening
the event log positions the file pointer</FONT>
<BR><FONT FACE="Courier New,Courier"> * for this
handle at the beginning of the log.</FONT>
<BR><FONT FACE="Courier New,Courier"> *</FONT>
<BR><FONT FACE="Courier New,Courier"> * Read records
sequentially until there</FONT>
<BR><FONT FACE="Courier New,Courier"> * are no
more.</FONT>
<BR><FONT FACE="Courier New,Courier"> */</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier"> while (ReadEventLog(h,
/* event log handle */</FONT>
<BR><FONT FACE="Courier New,Courier">
EVENTLOG_FORWARDS_READ | /* reads forward */</FONT>
<BR><FONT FACE="Courier New,Courier">
EVENTLOG_SEQUENTIAL_READ, /* sequential read */</FONT>
<BR><FONT FACE="Courier New,Courier">
0, /*
ignored for sequential reads */</FONT>
<BR><FONT FACE="Courier New,Courier">
pevlr, /* address of buffer
*/</FONT>
<BR><FONT FACE="Courier New,Courier">
BUFFER_SIZE, /* size of buffer
*/</FONT>
<BR><FONT FACE="Courier New,Courier">
&dwRead, /* count of bytes read
*/</FONT>
<BR><FONT FACE="Courier New,Courier">
&dwNeeded)) { /* bytes in next record
*/</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier">
while (dwRead > 0) {</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier">
/*</FONT>
<BR><FONT FACE="Courier New,Courier">
* Print the event ID, type, and source name.</FONT>
<BR><FONT FACE="Courier New,Courier">
* The source name is just past the end of the</FONT>
<BR><FONT FACE="Courier New,Courier">
* formal structure.</FONT>
<BR><FONT FACE="Courier New,Courier">
*/</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier">
printf("%02d Event ID: 0x%08X ",</FONT>
<BR><FONT FACE="Courier New,Courier">
dwThisRecord++, pevlr->EventID);</FONT>
<BR><FONT FACE="Courier New,Courier">
printf("EventType: %d Source: %s\n",</FONT>
<BR><FONT FACE="Courier New,Courier">
pevlr->EventType, (LPSTR) ((LPBYTE) pevlr +</FONT>
<BR><FONT FACE="Courier New,Courier">
sizeof(EVENTLOGRECORD)));</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier">
dwRead -= pevlr->Length;</FONT>
<BR><FONT FACE="Courier New,Courier">
pevlr = (EVENTLOGRECORD *)</FONT>
<BR><FONT FACE="Courier New,Courier">
((LPBYTE) pevlr + pevlr->Length);</FONT>
<BR><FONT FACE="Courier New,Courier">
}</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier">
pevlr = (EVENTLOGRECORD *) &bBuffer;</FONT>
<BR><FONT FACE="Courier New,Courier"> }</FONT>
<BR><FONT FACE="Courier New,Courier"> </FONT>
<BR><FONT FACE="Courier New,Courier"> CloseEventLog(h);</FONT>
<P>Regards,
<P>Niklas Nihlen
<BR>niklas@medcom.se</DL>
</BLOCKQUOTE>
</HTML>
--------------C74624BE9C24094D26031064--
Technical Details
Message-ID:
<35926D8F.EB117F26@cnet.francetelecom.fr>Path:
arc1-ca.pugleaf.net!unknown!not-for-mailReferences:
<3580F5F7.33A7B8E9@medcom.se>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 113dfb,b34767644b8788b7 X-Google-Attributes: gid113dfb,public X-Google-Thread: 105df1,b34767644b8788b7 X-Google-Attributes: gid105df1,public X-Google-Thread: f5ca7,b34767644b8788b7 X-Google-Attributes: gidf5ca7,public From: "R�gis Corbel" <regis.corbel@cnet.francetelecom.fr> Subject: Re: Reading Event Logs? Date: 1998/06/25 Message-ID: <35926D8F.EB117F26@cnet.francetelecom.fr> X-Deja-AN: 366004554 References: <3580F5F7.33A7B8E9@medcom.se> Content-Type: multipart/alternative; boundary="------------C74624BE9C24094D26031064" Organization: CNET Mime-Version: 1.0 Newsgroups: comp.os.ms-windows.programmer.win32,comp.os.ms-windows.programmer.misc,borland.public.cppbuilder.winapi