Patch for the afore mentioned bug fixes and enhancements.

------------------------ Cut Here ------------------------
diff -u -N orig/CategorizedMessage.java new/CategorizedMessage.java
--- orig/CategorizedMessage.java        Wed Dec 31 18:00:00 1969
+++ new/CategorizedMessage.java Mon Oct  7 13:27:29 2002
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) The Apache Software Foundation. All rights reserved.
+ *
+ * This software is published under the terms of the Apache Software
+ * License version 1.1, a copy of which has been included with this
+ * distribution in the LICENSE.txt file.  
+ */
+
+package org.apache.log4j.nt;
+
+import java.beans.*;
+
+/**
+ * Class that allows you to assign a category number to a message to be
+ * logged to the NTEventLogAppender. This category number will show up in
+ * the Category column of the Windows Event Log. If you have text assigned
+ * to those numbers in a resource DLL, you will see the text instead of the
+ * number.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]";>Brian Lind</a> 
+ */
+public class CategorizedMessage extends Object implements java.io.Serializable {
+
+    private PropertyChangeSupport propertySupport;
+
+    /** Holds value of property message. */
+    private Object message;
+    
+    /** Holds value of property eventCategory. */
+    private int eventCategory;
+    
+    /** Creates new CategorizedMessage */
+    public CategorizedMessage() {
+        propertySupport = new PropertyChangeSupport ( this );
+    }
+
+    /** Creates new CategorizedMessage */
+    public CategorizedMessage(int eventCategory, Object message) {
+        this();
+        this.eventCategory = eventCategory;
+        this.message = message;
+    }
+
+
+    public void addPropertyChangeListener (PropertyChangeListener listener) {
+        propertySupport.addPropertyChangeListener (listener);
+    }
+
+    public void removePropertyChangeListener (PropertyChangeListener listener) {
+        propertySupport.removePropertyChangeListener (listener);
+    }
+
+    /** Getter for property message.
+     * @return Value of property message.
+     */
+    public Object getMessage() {
+        return message;
+    }
+    
+    /** Setter for property message.
+     * @param message New value of property message.
+     */
+    public void setMessage(Object message) {
+        this.message = message;
+    }
+    
+    /** Getter for property eventCategory.
+     * @return Value of property eventCategory.
+     */
+    public int getEventCategory() {
+        return eventCategory;
+    }
+    
+    /** Setter for property eventCategory.
+     * @param eventCategory New value of property eventCategory.
+     */
+    public void setEventCategory(int eventCategory) {
+        this.eventCategory = eventCategory;
+    }
+    
+    public java.lang.String toString() {
+        if( message != null )
+            return message.toString();
+        else
+            return "null";
+    }
+    
+}
diff -u -N orig/EventLogCategories.mc new/EventLogCategories.mc
--- orig/EventLogCategories.mc  Mon Oct  7 13:14:05 2002
+++ new/EventLogCategories.mc   Mon Oct  7 13:27:29 2002
@@ -1,20 +1,20 @@
-MessageId=0xC350
+MessageId=1
 Language=English
 Fatal
 .
-MessageId=0x9C40
+MessageId=2
 Language=English
 Error
 .
-MessageId=0x7530
+MessageId=3
 Language=English
 Warn
 .
-MessageId=0x4E20
+MessageId=4
 Language=English
 Info
 .
-MessageId=0x2710
+MessageId=5
 Language=English
 Debug
 .
diff -u -N orig/ExampleCategories.mc new/ExampleCategories.mc
--- orig/ExampleCategories.mc   Wed Dec 31 18:00:00 1969
+++ new/ExampleCategories.mc    Mon Oct  7 13:27:29 2002
@@ -0,0 +1,44 @@
+MessageId=1
+Language=English
+Fatal
+.
+MessageId=2
+Language=English
+Error
+.
+MessageId=3
+Language=English
+Warn
+.
+MessageId=4
+Language=English
+Info
+.
+MessageId=5
+Language=English
+Debug
+.
+MessageId=6
+Language=English
+Started
+.
+MessageId=7
+Language=English
+Stopped
+.
+MessageId=8
+Language=English
+Success
+.
+MessageId=9
+Language=English
+Failure
+.
+MessageId=10
+Language=English
+Open
+.
+MessageId=11
+Language=English
+Close
+.
diff -u -N orig/ExampleEvents.mc new/ExampleEvents.mc
--- orig/ExampleEvents.mc       Wed Dec 31 18:00:00 1969
+++ new/ExampleEvents.mc        Mon Oct  7 13:27:29 2002
@@ -0,0 +1,4 @@
+MessageId=0x1000
+Language=English
+Message = (%1)
+.
diff -u -N orig/NTEventLogAppender.java new/NTEventLogAppender.java
--- orig/NTEventLogAppender.java        Mon Oct  7 13:14:05 2002
+++ new/NTEventLogAppender.java Mon Oct  7 13:27:29 2002
@@ -26,7 +26,9 @@
    will get a java.lang.UnsatisfiedLinkError.
 
    @author <a href="mailto:[EMAIL PROTECTED]";>Chris Taylor</a>
-   @author <a href="mailto:[EMAIL PROTECTED]";>Jim Cakalic</a> */
+   @author <a href="mailto:[EMAIL PROTECTED]";>Jim Cakalic</a> 
+   @author <a href="mailto:[EMAIL PROTECTED]";>Brian Lind</a> 
+ */
 public class NTEventLogAppender extends AppenderSkeleton {
   private int _handle = 0;
 
@@ -58,8 +60,18 @@
   public NTEventLogAppender(String source, Layout layout) {
     this(null, source, layout);
   }
-
+  
   public NTEventLogAppender(String server, String source, Layout layout) {
+    this(server, source, layout, null, null);
+  }
+
+  public NTEventLogAppender(String server, String source, Layout layout,
+    String categoryMessageFile) {
+    this(server, source, layout, categoryMessageFile, null);
+  }
+
+  public NTEventLogAppender(String server, String source, Layout layout,
+    String categoryMessageFile, String eventMessageFile) {
     if (source == null) {
       source = "Log4j";
     }
@@ -70,6 +82,10 @@
     }
 
     try {
+      if( categoryMessageFile != null )
+          setCategoryMessageFile(categoryMessageFile);
+      if( eventMessageFile != null )
+          setEventMessageFile(eventMessageFile);
       _handle = registerEventSource(server, source);
     } catch (Exception e) {
       e.printStackTrace();
@@ -109,14 +125,20 @@
        }
       }
     }
-    // Normalize the log message level into the supported categories
-    int nt_category = event.level.toInt();
+    // Normalize the log message level into the supported NT event types
+    int priority = event.level.toInt();
 
     // Anything above FATAL or below DEBUG is labeled as INFO.
-    //if (nt_category > FATAL || nt_category < DEBUG) {
-    //  nt_category = INFO;
+    //if (priority > FATAL || priority < DEBUG) {
+    //  priority = INFO;
     //}
-    reportEvent(_handle, sbuf.toString(), nt_category);
+    if( event.getMessage() instanceof CategorizedMessage ) {
+      CategorizedMessage extendedMsg = (CategorizedMessage)(event.getMessage());
+      reportEventAndCategory(_handle, sbuf.toString(), priority, 
+extendedMsg.getEventCategory());
+    }
+    else {
+      reportEvent(_handle, sbuf.toString(), priority);
+    }
   }
 
 
@@ -149,9 +171,16 @@
   }
 
   native private int registerEventSource(String server, String source);
-  native private void reportEvent(int handle, String message, int level);
+  native private void reportEvent(int handle, String message, int priority);
   native private void deregisterEventSource(int handle);
 
+  native private void setEventMessageFile(String dllName);
+  native private void setCategoryMessageFile(String dllName);
+  native private void reportEventAndCategory(int handle, String message, int 
+priority, int category);
+
+  native public boolean isUserDisplayed();
+  native public void setUserDisplayed(boolean on);
+  
   static {
     System.loadLibrary("NTEventLogAppender");
   }
diff -u -N orig/Notes.txt new/Notes.txt
--- orig/Notes.txt      Wed Dec 31 18:00:00 1969
+++ new/Notes.txt       Mon Oct  7 13:27:29 2002
@@ -0,0 +1,36 @@
+Notes:
+
+The NTEventLogAppender.dll DLL still needs to be found in your PATH, even if
+you use custom resource only DLL's. Your resource DLL's, of course, need to
+be found in the PATH somewhere too.
+
+
+When creating your own resource only DLL for your custom categories, you should
+still include the standard log4j ones for compatability purposes. You can copy
+and paste the standard ones (number 1 thru 5) from the EventLogCategories.mc file.
+Be sure to start numbering yours at 6 on up or they will not show up in the Event Log.
+If you leave gaps in the numbers, only the numbers show up in the Event Log instead
+of the text. At least that's what I've experienced when I decided to try and start
+numbering my categories at 100. Didn't work for me.
+
+To use custom categories you need to tell the NTEventLogAppender about you custom
+resource only DLL and use the CategorizedMessage class to associate a category
+number with you log message.
+Example:
+
+    Category log = Category.getInstance(appName);
+    NTEventLogAppender appender = 
+        new NTEventLogAppender(null, appName, null, "MyCategories.dll");
+    log.addAppender(appender);
+    log.info(new CategorizedMessage(6, "Hi there."));
+    
+
+If you would like to use a custom event, not very useful at this point, you
+can create a resource only DLL message file (.mc file), with one message
+in it with MessageId=0x1000 and whatever you want for the text of the event. 
+If you don't include a %1 somewhere in the text, you'll never see the message you 
+passed in from Java. You specify your event message DLL in a NTEventLogAppender
+contructor.
+Example:
+    NTEventLogAppender appender = 
+        new NTEventLogAppender(null, appName, null, "MyCategories.dll", 
+"MyEvent.dll");
diff -u -N orig/examplemake.bat new/examplemake.bat
--- orig/examplemake.bat        Wed Dec 31 18:00:00 1969
+++ new/examplemake.bat Mon Oct  7 13:27:29 2002
@@ -0,0 +1,12 @@
+@echo off
+
+REM Example for creating custom Event Categories and Event ID's and descriptions
+
+MC ExampleCategories.mc
+RC -r -fo ExampleCategories.res ExampleCategories.rc
+LINK /subsystem:windows /INCREMENTAL:NO /dll /noentry /out:"ExampleCategories.dll" 
+ExampleCategories.res
+
+MC ExampleEvents.mc
+RC -r -fo ExampleEvents.res ExampleEvents.rc
+LINK /subsystem:windows /INCREMENTAL:NO /dll /noentry /out:"ExampleEvents.dll" 
+ExampleEvents.res
+
diff -u -N orig/nteventlog.cpp new/nteventlog.cpp
--- orig/nteventlog.cpp Mon Oct  7 13:14:06 2002
+++ new/nteventlog.cpp  Mon Oct  7 13:36:11 2002
@@ -12,6 +12,12 @@
 #include "org_apache_log4j_nt_NTEventLogAppender.h"
 #include <windows.h>
 
+const DWORD defaultMessageID = 0x1000;
+DWORD messageID = defaultMessageID;
+char *EventMessageFile = "NTEventLogAppender.dll";
+char *CategoryMessageFile = "NTEventLogAppender.dll";
+BOOL displayUser = FALSE;
+
 // Borrowed unabashedly from the JNI Programmer's Guide
 void JNU_ThrowByName(JNIEnv *env, const char *name, const char *msg) {
 
@@ -83,8 +89,27 @@
  * be displayed in the NT Event Viewer.
  */
 WORD getCategory(jint priority) {
-  // Priority values map directly to EventLog category values
-  return (WORD)(priority + 1);
+  WORD ret_val = 0;
+
+  // Map priority to a resonable category name code from EvengLogCategories.mc
+  switch (priority) {
+  case org_apache_log4j_Priority_FATAL_INT:
+    ret_val = 1;
+    break;
+  case org_apache_log4j_Priority_ERROR_INT:
+    ret_val = 2;
+    break;
+  case org_apache_log4j_Priority_WARN_INT:
+    ret_val = 3;
+    break;
+  case org_apache_log4j_Priority_INFO_INT:
+    ret_val = 4;
+    break;
+  case org_apache_log4j_Priority_DEBUG_INT:
+    ret_val = 5;
+    break;
+  }
+  return ret_val;
 }
 
 /*
@@ -112,12 +137,13 @@
   return ret_val;
 }
 
-HKEY regGetKey(TCHAR *subkey, DWORD *disposition) {
-  HKEY hkey = 0;
-  RegCreateKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, NULL, 
-                REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, 
-                &hkey, disposition);
-  return hkey;
+DWORD regGetKey(TCHAR *subkey, HKEY *hkey) {
+  DWORD result;
+  DWORD disposition;
+  result = RegCreateKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, NULL, 
+                         REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, 
+                         hkey, &disposition);
+  return result;
 }
 
 void regSetString(HKEY hkey, TCHAR *name, TCHAR *value) {
@@ -133,28 +159,51 @@
  */
 void addRegistryInfo(char *source) {
   const TCHAR *prefix = 
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\";
-  DWORD disposition;
+  DWORD result;
   HKEY hkey = 0;
   TCHAR subkey[256];
   
   lstrcpy(subkey, prefix);
   lstrcat(subkey, source);
-  hkey = regGetKey(subkey, &disposition);
-  if (disposition == REG_CREATED_NEW_KEY) {
-    regSetString(hkey, "EventMessageFile", "NTEventLogAppender.dll");
-    regSetString(hkey, "CategoryMessageFile", "NTEventLogAppender.dll");
+  result = regGetKey(subkey, &hkey);
+  if (result == ERROR_SUCCESS) {
+    regSetString(hkey, "EventMessageFile", EventMessageFile);
+    regSetString(hkey, "CategoryMessageFile", CategoryMessageFile);
     regSetDword(hkey, "TypesSupported", (DWORD)7);
-    regSetDword(hkey, "CategoryCount", (DWORD)8);
+    regSetDword(hkey, "CategoryCount", (DWORD)1000);
   }
-       //RegSetValueEx(hkey, "EventMessageFile", 0, REG_SZ, (LPBYTE)dllname, 
lstrlen(dllname));
-       //RegSetValueEx(hkey, "CategoryMessageFile", 0, REG_SZ, (LPBYTE)dllname, 
lstrlen(dllname));
-       //RegSetValueEx(hkey, "TypesSupported", 0, REG_DWORD, (LPBYTE)&whichTypes, 
sizeof(DWORD));
-       //RegSetValueEx(hkey, "CategoryCount", 0, REG_DWORD, (LPBYTE)&numCategories, 
sizeof(DWORD));
   RegCloseKey(hkey);
   return;
 }
 
 /*
+ * Lookup the current user's SID and return a pointer to it
+ */
+PSID getCurrentUserId()
+{
+  char user[256];
+  DWORD userLen = 256;
+  PSID userSidPtr = NULL;
+  DWORD sidLen = 0;
+  char domain[256];
+  DWORD domainLen = sizeof(domain);
+  SID_NAME_USE accountType;
+  if( GetUserName(user, &userLen) )
+  {
+    LookupAccountName(NULL, user, userSidPtr, &sidLen, 
+                      domain, &domainLen, &accountType);
+    userSidPtr = (SID *)malloc(sidLen);
+    if( ! LookupAccountName(NULL, user, userSidPtr, &sidLen, 
+                            domain, &domainLen, &accountType) )
+    {
+      free(userSidPtr);
+      userSidPtr = NULL;
+    }
+  }
+  return userSidPtr;
+}
+
+/*
  * Class:     org.apache.log4j.nt.NTEventLogAppender
  * Method:    registerEventSource
  * Signature: (Ljava/lang/String;Ljava/lang/String;)I
@@ -184,8 +233,40 @@
  * Signature: (ILjava/lang/String;I)V
  */
 JNIEXPORT void JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_reportEvent(
-   JNIEnv *env, jobject java_this, jint handle, jstring jstr, jint priority) {
-  
+   JNIEnv *env, jobject java_this, jint handle, jstring jstr, jint priority) 
+{
+  Java_org_apache_log4j_nt_NTEventLogAppender_reportEventAndCategory(
+    env, java_this, handle, jstr, priority, getCategory(priority));
+  return;
+}
+
+/*
+ * Class:     org_apache_log4j_nt_NTEventLogAppender
+ * Method:    deregisterEventSource
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL 
+Java_org_apache_log4j_nt_NTEventLogAppender_deregisterEventSource(
+JNIEnv *env, 
+jobject java_this, 
+jint handle)
+{
+  DeregisterEventSource((HANDLE)handle);
+}
+
+
+/*
+ * Class:     org_apache_log4j_nt_NTEventLogAppender
+ * Method:    reportEvent
+ * Signature: (ILjava/lang/String;II)V
+ */
+JNIEXPORT void JNICALL 
+Java_org_apache_log4j_nt_NTEventLogAppender_reportEventAndCategory
+  (JNIEnv *env, 
+   jobject java_this, 
+   jint handle, 
+   jstring jstr, 
+   jint priority, 
+   jint category)
+{
   jboolean localHandle = JNI_FALSE;
   if (handle == 0) {
     // Client didn't give us a handle so make a local one.
@@ -199,15 +280,24 @@
   char *nstr = JNU_GetStringNativeChars(env, jstr);
   array[0] = nstr;
   
+  // lookup user
+  PSID userSidPtr = NULL;
+  if( displayUser )
+    userSidPtr = getCurrentUserId();
+
   // This is the only message supported by the package. It is backed by
   // a message resource which consists of just '%1' which is replaced
   // by the string we just created.
-  const DWORD messageID = 0x1000;
-  ReportEvent((HANDLE)handle, getType(priority), 
-             getCategory(priority), 
-             messageID, NULL, 1, 0, array, NULL);
+  ReportEvent((HANDLE)handle, getType(priority), (WORD)category, 
+             defaultMessageID, userSidPtr, 1, 0, array, NULL);
   
   free((void *)nstr);
+
+  if( userSidPtr != NULL )
+  {
+    free(userSidPtr);
+  }
+
   if (localHandle == JNI_TRUE) {
     // Created the handle here so free it here too.
     DeregisterEventSource((HANDLE)handle);
@@ -217,16 +307,66 @@
 
 /*
  * Class:     org_apache_log4j_nt_NTEventLogAppender
- * Method:    deregisterEventSource
- * Signature: (I)V
+ * Method:    isUserDisplayed
+ * Signature: ()Z
  */
-JNIEXPORT void JNICALL 
Java_org_apache_log4j_nt_NTEventLogAppender_deregisterEventSource(
-JNIEnv *env, 
-jobject java_this, 
-jint handle)
+JNIEXPORT jboolean JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_isUserDisplayed
+  (JNIEnv *env, 
+   jobject java_this)
 {
-  DeregisterEventSource((HANDLE)handle);
+    if( displayUser )
+        return JNI_TRUE;
+    return JNI_FALSE;
 }
 
+/*
+ * Class:     org_apache_log4j_nt_NTEventLogAppender
+ * Method:    setUserDisplayed
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_setUserDisplayed
+  (JNIEnv *env, 
+   jobject java_this, 
+   jboolean on)
+{
+    if( on == JNI_TRUE )
+        displayUser = TRUE;
+    else
+        displayUser = FALSE;
+}
+
+/*
+ * Class:     org_apache_log4j_nt_NTEventLogAppender
+ * Method:    setEventMessageFile
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_org_apache_log4j_nt_NTEventLogAppender_setEventMessageFile
+  (JNIEnv *env, 
+   jobject java_this, 
+   jstring dllName)
+{
+    char *nstr = JNU_GetStringNativeChars(env, dllName);
+    if( nstr != NULL && strlen(nstr) > 0 )
+    {
+        EventMessageFile = (char *)strdup(nstr);
+    }
+}
+
+/*
+ * Class:     org_apache_log4j_nt_NTEventLogAppender
+ * Method:    setCategoryMessageFile
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL 
+Java_org_apache_log4j_nt_NTEventLogAppender_setCategoryMessageFile
+  (JNIEnv *env, 
+   jobject java_this, 
+   jstring dllName)
+{
+    char *nstr = JNU_GetStringNativeChars(env, dllName);
+    if( nstr != NULL && strlen(nstr) > 0 )
+    {
+        CategoryMessageFile = (char *)strdup(nstr);
+    }
+}
 
 #endif

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to