123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- """Event Log Utilities - helper for win32evtlog.pyd
- """
-
- import win32api
- import win32con
- import win32evtlog
- import winerror
-
- error = win32api.error # The error the evtlog module raises.
-
- langid = win32api.MAKELANGID(win32con.LANG_NEUTRAL, win32con.SUBLANG_NEUTRAL)
-
-
- def AddSourceToRegistry(
- appName,
- msgDLL=None,
- eventLogType="Application",
- eventLogFlags=None,
- categoryDLL=None,
- categoryCount=0,
- ):
- """Add a source of messages to the event log.
-
- Allows Python program to register a custom source of messages in the
- registry. You must also provide the DLL name that has the message table, so the
- full message text appears in the event log.
-
- Note that the win32evtlog.pyd file has a number of string entries with just "%1"
- built in, so many Python programs can simply use this DLL. Disadvantages are that
- you do not get language translation, and the full text is stored in the event log,
- blowing the size of the log up.
- """
-
- # When an application uses the RegisterEventSource or OpenEventLog
- # function to get a handle of an event log, the event logging service
- # searches for the specified source name in the registry. You can add a
- # new source name to the registry by opening a new registry subkey
- # under the Application key and adding registry values to the new
- # subkey.
-
- if msgDLL is None:
- msgDLL = win32evtlog.__file__
- # Create a new key for our application
- hkey = win32api.RegCreateKey(
- win32con.HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s"
- % (eventLogType, appName),
- )
-
- # Add the Event-ID message-file name to the subkey.
- win32api.RegSetValueEx(
- hkey,
- "EventMessageFile", # value name \
- 0, # reserved \
- win32con.REG_EXPAND_SZ, # value type \
- msgDLL,
- )
-
- # Set the supported types flags and add it to the subkey.
- if eventLogFlags is None:
- eventLogFlags = (
- win32evtlog.EVENTLOG_ERROR_TYPE
- | win32evtlog.EVENTLOG_WARNING_TYPE
- | win32evtlog.EVENTLOG_INFORMATION_TYPE
- )
- win32api.RegSetValueEx(
- hkey, # subkey handle \
- "TypesSupported", # value name \
- 0, # reserved \
- win32con.REG_DWORD, # value type \
- eventLogFlags,
- )
-
- if categoryCount > 0:
- # Optionally, you can specify a message file that contains the categories
- if categoryDLL is None:
- categoryDLL = win32evtlog.__file__
- win32api.RegSetValueEx(
- hkey, # subkey handle \
- "CategoryMessageFile", # value name \
- 0, # reserved \
- win32con.REG_EXPAND_SZ, # value type \
- categoryDLL,
- )
-
- win32api.RegSetValueEx(
- hkey, # subkey handle \
- "CategoryCount", # value name \
- 0, # reserved \
- win32con.REG_DWORD, # value type \
- categoryCount,
- )
- win32api.RegCloseKey(hkey)
-
-
- def RemoveSourceFromRegistry(appName, eventLogType="Application"):
- """Removes a source of messages from the event log."""
-
- # Delete our key
- try:
- win32api.RegDeleteKey(
- win32con.HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s"
- % (eventLogType, appName),
- )
- except win32api.error as exc:
- if exc.winerror != winerror.ERROR_FILE_NOT_FOUND:
- raise
-
-
- def ReportEvent(
- appName,
- eventID,
- eventCategory=0,
- eventType=win32evtlog.EVENTLOG_ERROR_TYPE,
- strings=None,
- data=None,
- sid=None,
- ):
- """Report an event for a previously added event source."""
- # Get a handle to the Application event log
- hAppLog = win32evtlog.RegisterEventSource(None, appName)
-
- # Now report the event, which will add this event to the event log */
- win32evtlog.ReportEvent(
- hAppLog, # event-log handle \
- eventType,
- eventCategory,
- eventID,
- sid,
- strings,
- data,
- )
-
- win32evtlog.DeregisterEventSource(hAppLog)
-
-
- def FormatMessage(eventLogRecord, logType="Application"):
- """Given a tuple from ReadEventLog, and optionally where the event
- record came from, load the message, and process message inserts.
-
- Note that this function may raise win32api.error. See also the
- function SafeFormatMessage which will return None if the message can
- not be processed.
- """
-
- # From the event log source name, we know the name of the registry
- # key to look under for the name of the message DLL that contains
- # the messages we need to extract with FormatMessage. So first get
- # the event log source name...
- keyName = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\%s\\%s" % (
- logType,
- eventLogRecord.SourceName,
- )
-
- # Now open this key and get the EventMessageFile value, which is
- # the name of the message DLL.
- handle = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, keyName)
- try:
- dllNames = win32api.RegQueryValueEx(handle, "EventMessageFile")[0].split(";")
- # Win2k etc appear to allow multiple DLL names
- data = None
- for dllName in dllNames:
- try:
- # Expand environment variable strings in the message DLL path name,
- # in case any are there.
- dllName = win32api.ExpandEnvironmentStrings(dllName)
-
- dllHandle = win32api.LoadLibraryEx(
- dllName, 0, win32con.LOAD_LIBRARY_AS_DATAFILE
- )
- try:
- data = win32api.FormatMessageW(
- win32con.FORMAT_MESSAGE_FROM_HMODULE,
- dllHandle,
- eventLogRecord.EventID,
- langid,
- eventLogRecord.StringInserts,
- )
- finally:
- win32api.FreeLibrary(dllHandle)
- except win32api.error:
- pass # Not in this DLL - try the next
- if data is not None:
- break
- finally:
- win32api.RegCloseKey(handle)
- return data or "" # Don't want "None" ever being returned.
-
-
- def SafeFormatMessage(eventLogRecord, logType=None):
- """As for FormatMessage, except returns an error message if
- the message can not be processed.
- """
- if logType is None:
- logType = "Application"
- try:
- return FormatMessage(eventLogRecord, logType)
- except win32api.error:
- if eventLogRecord.StringInserts is None:
- desc = ""
- else:
- desc = ", ".join(eventLogRecord.StringInserts)
- return (
- "<The description for Event ID ( %d ) in Source ( %r ) could not be found. It contains the following insertion string(s):%r.>"
- % (
- winerror.HRESULT_CODE(eventLogRecord.EventID),
- eventLogRecord.SourceName,
- desc,
- )
- )
-
-
- def FeedEventLogRecords(
- feeder, machineName=None, logName="Application", readFlags=None
- ):
- if readFlags is None:
- readFlags = (
- win32evtlog.EVENTLOG_BACKWARDS_READ | win32evtlog.EVENTLOG_SEQUENTIAL_READ
- )
- h = win32evtlog.OpenEventLog(machineName, logName)
- try:
- while 1:
- objects = win32evtlog.ReadEventLog(h, readFlags, 0)
- if not objects:
- break
- map(lambda item, feeder=feeder: feeder(*(item,)), objects)
- finally:
- win32evtlog.CloseEventLog(h)
|