Windows: integrated logon
[openafs.git] / src / WINNT / afsd / afslogon.c
index f8c25ac..0554eed 100644 (file)
 #include "afskfw.h"
 #include "lanahelper.h"
 
+/* Allocated in Windows Driver Kit */
+#ifndef WNNC_NET_OPENAFS
+#define WNNC_NET_OPENAFS     0x00390000
+#endif
+
 #include <WINNT\afsreg.h>
 
 DWORD TraceOption = 0;
 
 HANDLE hDLL;
 
-WSADATA WSAjunk;
 #define AFS_LOGON_EVENT_NAME TEXT("AFS Logon")
 
 void DebugEvent0(char *a) 
@@ -46,9 +50,11 @@ void DebugEvent0(char *a)
         return;
     
     h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
-    ptbuf[0] = a;
-    ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
-    DeregisterEventSource(h);
+    if (h != INVALID_HANDLE_VALUE) {
+        ptbuf[0] = a;
+        ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
+        DeregisterEventSource(h);
+    }
 }
 
 #define MAXBUF_ 512
@@ -61,13 +67,15 @@ void DebugEvent(char *b,...)
         return;
 
     h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
-    va_start(marker,b);
-    StringCbVPrintf(buf, MAXBUF_+1,b,marker);
-    buf[MAXBUF_] = '\0';
-    ptbuf[0] = buf;
-    ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
-    DeregisterEventSource(h);
-    va_end(marker);
+    if (h != INVALID_HANDLE_VALUE) {
+        va_start(marker,b);
+        StringCbVPrintf(buf, MAXBUF_+1,b,marker);
+        buf[MAXBUF_] = '\0';
+        ptbuf[0] = buf;
+        ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 1008, NULL, 1, 0, (const char **)ptbuf, NULL);
+        DeregisterEventSource(h);
+        va_end(marker);
+    }
 }
 
 static HANDLE hInitMutex = NULL;
@@ -75,15 +83,23 @@ static BOOL bInit = FALSE;
 
 BOOLEAN APIENTRY DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
 {
+    WSADATA wsaData;
     hDLL = dll;
+
     switch (reason) {
     case DLL_PROCESS_ATTACH:
-        /* Initialization Mutex */
-        hInitMutex = CreateMutex(NULL, FALSE, NULL);
+       /* Initialization Mutex */
+       if (!hInitMutex)
+           hInitMutex = CreateMutex(NULL, FALSE, NULL);
+
+       WSAStartup( MAKEWORD(2,2), &wsaData );
         break;
 
     case DLL_PROCESS_DETACH:
-        CloseHandle(hInitMutex);
+       WSACleanup();
+       CloseHandle(hInitMutex);
+       hInitMutex = NULL;
+       bInit = FALSE;
         break;
 
     case DLL_THREAD_ATTACH:
@@ -100,14 +116,28 @@ void AfsLogonInit(void)
 {
     if ( bInit == FALSE ) {
         if ( WaitForSingleObject( hInitMutex, INFINITE ) == WAIT_OBJECT_0 ) {
-            if ( bInit == FALSE ) {
-                rx_Init(0);
-                initAFSDirPath();
-                ka_Init(0);
-                bInit = TRUE;
-            }
-            ReleaseMutex(hInitMutex);
-        }
+           /* initAFSDirPath() initializes an array and sets a 
+            * flag so that the initialization can only occur
+            * once.  No cleanup will be done when the DLL is 
+            * unloaded so the initialization will not be 
+            * performed again on a subsequent reload
+            */
+           initAFSDirPath();
+
+           /* ka_Init initializes a number of error tables.
+            * and then calls ka_CellConfig() which grabs 
+            * an afsconf_dir structure via afsconf_Open().
+            * Upon a second attempt to call ka_CellConfig()
+            * the structure will be released with afsconf_Close()
+            * and then re-opened.  Could this corrupt memory?
+            * 
+            * We only need this if we are not using KFW.
+            */
+           if (!KFW_is_available())
+               ka_Init(0);
+           bInit = TRUE;
+       }
+       ReleaseMutex(hInitMutex);
     }
 }
 
@@ -192,7 +222,7 @@ DWORD APIENTRY NPGetCaps(DWORD index)
     switch (index) {
     case WNNC_NET_TYPE:
         /* Don't have our own type; use somebody else's. */
-        return WNNC_NET_SUN_PC_NFS;
+        return WNNC_NET_OPENAFS;
 
     case WNNC_START:
         /* Say we are already started, even though we might wait after we receive NPLogonNotify */
@@ -294,21 +324,24 @@ BOOL IsServiceStartPending (void)
                if(hkDom) { \
                        dwSize = sizeof(v); \
                        rv = RegQueryValueEx(hkDom, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
-                       if(rv == ERROR_SUCCESS) DebugEvent(#v " found in hkDom with type [%d]", dwType); \
+                       if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
+                            DebugEvent(#v " found in hkDom with type [%d]", dwType); \
                } \
-               if(hkDoms && (rv != ERROR_SUCCESS || dwType != t)) { \
+               if(hkDoms && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
                        dwSize = sizeof(v); \
                        rv = RegQueryValueEx(hkDoms, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
-                       if(rv == ERROR_SUCCESS) DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
+                       if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
+                            DebugEvent(#v " found in hkDoms with type [%d]", dwType); \
                } \
-               if(hkNp && (rv != ERROR_SUCCESS || dwType != t)) { \
+               if(hkNp && ((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t)) { \
                        dwSize = sizeof(v); \
                        rv = RegQueryValueEx(hkNp, n, 0, &dwType, (LPBYTE) &(v), &dwSize); \
-                       if(rv == ERROR_SUCCESS) DebugEvent(#v " found in hkNp with type [%d]", dwType); \
+                       if(rv == ERROR_SUCCESS || rv == ERROR_MORE_DATA) \
+                            DebugEvent(#v " found in hkNp with type [%d]", dwType); \
                } \
-               if(rv != ERROR_SUCCESS || dwType != t) { \
+               if((rv != ERROR_SUCCESS && rv != ERROR_MORE_DATA) || dwType != t) { \
                        v = d; \
-                       DebugEvent(#v " being set to default"); \
+                       DebugEvent0(#v " being set to default"); \
                } \
        } while(0)
 
@@ -326,8 +359,8 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     DWORD dwSize;
     DWORD dwType;
     DWORD dwDummy;
-    char computerName[MAX_COMPUTERNAME_LENGTH + 1];
-    char *effDomain;
+    char computerName[MAX_COMPUTERNAME_LENGTH + 1]="";
+    char *effDomain = NULL;
 
     memset(opt, 0, sizeof(LogonOptions_t));
 
@@ -335,17 +368,16 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     /* If the domain is the same as the Netbios computer name, we use the LOCALHOST domain name*/
     opt->flags = LOGON_FLAG_REMOTE;
     if(domain) {
-        dwSize = MAX_COMPUTERNAME_LENGTH;
+        dwSize = MAX_COMPUTERNAME_LENGTH + 1;
         if(GetComputerName(computerName, &dwSize)) {
-            if(!stricmp(computerName, domain)) {
+            if(!cm_stricmp_utf8(computerName, domain)) {
                 effDomain = "LOCALHOST";
                 opt->flags = LOGON_FLAG_LOCAL;
             }
-            else
-                effDomain = domain;
         }
-    } else
-        effDomain = NULL;
+        if (effDomain == NULL)
+            effDomain = domain;
+    }
 
     rv = RegOpenKeyEx( HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0, KEY_READ, &hkParm );
     if(rv != ERROR_SUCCESS) {
@@ -377,7 +409,7 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
             hkDoms = NULL;
         }
     } else
-        DebugEvent("Not opening domain key for [%s]", effDomain);
+        DebugEvent0("Not opening domain key");
 
     /* Each individual can either be specified on the domain key, the domains key or in the
        net provider key.  They fail over in that order.  If none is found, we just use the 
@@ -391,7 +423,7 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     rv = RegQueryValueEx(hkParm, REG_CLIENT_FAIL_SILENTLY_PARM, 0, &dwType, (LPBYTE) &dwDummy, &dwSize);
     if (rv != ERROR_SUCCESS)
         LOOKUPKEYCHAIN(dwDummy, REG_DWORD, DEFAULT_FAIL_SILENTLY, REG_CLIENT_FAIL_SILENTLY_PARM);
-    opt->failSilently = !!dwDummy;
+    opt->failSilently = dwDummy ? 1 :0;
 
     /* Retry interval */
     LOOKUPKEYCHAIN(opt->retryInterval, REG_DWORD, DEFAULT_RETRY_INTERVAL, REG_CLIENT_RETRY_INTERVAL_PARM);
@@ -399,29 +431,38 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
     /* Sleep interval */
     LOOKUPKEYCHAIN(opt->sleepInterval, REG_DWORD, DEFAULT_SLEEP_INTERVAL, REG_CLIENT_SLEEP_INTERVAL_PARM);
 
-    opt->logonScript = NULL;
-    opt->smbName = NULL;
-
     if(!ISLOGONINTEGRATED(opt->LogonOption)) {
+        DebugEvent0("Integrated logon disabled");
         goto cleanup; /* no need to lookup the logon script */
     }
 
     /* come up with SMB username */
     if(ISHIGHSECURITY(opt->LogonOption)) {
+        DebugEvent0("High Security Mode active");
         opt->smbName = malloc( MAXRANDOMNAMELEN );
+        if (opt->smbName == NULL)
+            goto cleanup;
         GenRandomName(opt->smbName);
-    } else {
+    } else if (lpLogonId) {
         /* username and domain for logon session is not necessarily the same as
            username and domain passed into network provider. */
-        PSECURITY_LOGON_SESSION_DATA plsd;
-        char lsaUsername[MAX_USERNAME_LENGTH];
-        char lsaDomain[MAX_DOMAIN_LENGTH];
+        PSECURITY_LOGON_SESSION_DATA plsd=NULL;
+        char lsaUsername[MAX_USERNAME_LENGTH]="";
+        char lsaDomain[MAX_DOMAIN_LENGTH]="";
         size_t len, tlen;
+        NTSTATUS Status;
 
-        LsaGetLogonSessionData(lpLogonId, &plsd);
+        Status = LsaGetLogonSessionData(lpLogonId, &plsd);
+        if ( FAILED(Status) || plsd == NULL ) {
+            DebugEvent("LsaGetLogonSessionData failed [0x%x]", Status);
+            goto bad_strings;
+        }
         
-        UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH);
-        UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH);
+        if (!UnicodeStringToANSI(plsd->UserName, lsaUsername, MAX_USERNAME_LENGTH))
+            goto bad_strings;
+
+        if (!UnicodeStringToANSI(plsd->LogonDomain, lsaDomain, MAX_DOMAIN_LENGTH))
+            goto bad_strings;
 
         DebugEvent("PLSD username[%s] domain[%s]",lsaUsername,lsaDomain);
 
@@ -438,6 +479,8 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         len += 2;
 
         opt->smbName = malloc(len);
+        if (opt->smbName == NULL)
+            goto cleanup;
 
         StringCbCopy(opt->smbName, len, lsaDomain);
         StringCbCat(opt->smbName, len, "\\");
@@ -446,10 +489,29 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         strlwr(opt->smbName);
 
       bad_strings:
-        LsaFreeReturnBuffer(plsd);
+        if (plsd)
+            LsaFreeReturnBuffer(plsd);
     }
+    if (opt->smbName == NULL) {
+        size_t len;
+
+        DebugEvent("Constructing username using [%s] and [%s]",
+                   username, domain);
+        len = strlen(username) + strlen(domain) + 2;
+
+        opt->smbName = malloc(len);
+        if (opt->smbName == NULL)
+            goto cleanup;
 
-    DebugEvent("Looking up logon script");
+        StringCbCopy(opt->smbName, len, domain);
+        StringCbCat(opt->smbName, len, "\\");
+        StringCbCat(opt->smbName, len, username);
+
+        strlwr(opt->smbName);
+    }
+
+    DebugEvent0("Looking up logon script");
     /* Logon script */
     /* First find out where the key is */
     hkTemp = NULL;
@@ -459,20 +521,22 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         rv = RegQueryValueExW(hkDom, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
     if(rv == ERROR_SUCCESS && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
         hkTemp = hkDom;
-        DebugEvent("Located logon script in hkDom");
+        DebugEvent0("Located logon script in hkDom");
     }
-    else if(hkDoms)
+    else if(hkDoms) {
         rv = RegQueryValueExW(hkDoms, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
-    if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
-        hkTemp = hkDoms;
-        DebugEvent("Located logon script in hkDoms");
-    }
-    /* Note that the LogonScript in the NP key is only used if we are doing high security. */
-    else if(hkNp && ISHIGHSECURITY(opt->LogonOption))
-        rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
-    if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
-        hkTemp = hkNp;
-        DebugEvent("Located logon script in hkNp");
+        if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
+            hkTemp = hkDoms;
+            DebugEvent0("Located logon script in hkDoms");
+        }
+        /* Note that the LogonScript in the NP key is only used if we are doing high security. */
+        else if(hkNp && ISHIGHSECURITY(opt->LogonOption)) {
+            rv = RegQueryValueExW(hkNp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, NULL, &dwSize);
+            if(rv == ERROR_SUCCESS && !hkTemp && (dwType == REG_SZ || dwType == REG_EXPAND_SZ)) {
+                hkTemp = hkNp;
+                DebugEvent0("Located logon script in hkNp");
+            }
+        }
     }
 
     if(hkTemp) {
@@ -488,15 +552,19 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         len ++;
 
         wuname = malloc(len * sizeof(WCHAR));
+        if (!wuname)
+            goto doneLogonScript;
         MultiByteToWideChar(CP_ACP,0,opt->smbName,-1,wuname,(int)(len*sizeof(WCHAR)));
 
         DebugEvent("Username is set for [%S]", wuname);
 
         /* dwSize still has the size of the required buffer in bytes. */
         regscript = malloc(dwSize);
+        if (!regscript)
+            goto doneLogonScript;
         rv = RegQueryValueExW(hkTemp, REG_CLIENT_LOGON_SCRIPT_PARMW, 0, &dwType, (LPBYTE) regscript, &dwSize);
         if(rv != ERROR_SUCCESS) {/* what the ..? */
-            DebugEvent("Can't look up logon script [%d]",rv);
+            DebugEvent("Can't look up logon script rv [%d] size [%d] gle %d",rv, dwSize, GetLastError());
             goto doneLogonScript;
         }
 
@@ -507,12 +575,14 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
 
             dwSize += MAX_PATH * sizeof(WCHAR);  /* make room for environment expansion. */
             regexscript = malloc(dwSize);
+            if (!regexscript)
+                goto doneLogonScript;
             dwReq = ExpandEnvironmentStringsW(regscript, regexscript, dwSize / sizeof(WCHAR));
             free(regscript);
             regscript = regexscript;
             regexscript = NULL;
             if(dwReq > (dwSize / sizeof(WCHAR))) {
-                DebugEvent("Overflow while expanding environment strings.");
+                DebugEvent0("Overflow while expanding environment strings.");
                 goto doneLogonScript;
             }
         }
@@ -522,9 +592,13 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         if(wcsstr(regscript, L"%s")) {
             dwSize += (DWORD)(len * sizeof(WCHAR)); /* make room for username expansion */
             regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
+            if (!regexuscript)
+                goto doneLogonScript;
             hr = StringCbPrintfW(regexuscript, dwSize, regscript, wuname);
         } else {
             regexuscript = (WCHAR *) LocalAlloc(LMEM_FIXED, dwSize);
+            if (!regexuscript)
+                goto doneLogonScript;
             hr = StringCbCopyW(regexuscript, dwSize, regscript);
         }
 
@@ -541,44 +615,100 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt
         if(regexscript) free(regexscript);
     }
 
-    DebugEvent("Looking up TheseCells");
-    /* Logon script */
+    DebugEvent0("Looking up TheseCells");
+    /* TheseCells */
     /* First find out where the key is */
     hkTemp = NULL;
     rv = ~ERROR_SUCCESS;
-    dwType = 0;
+    dwSize = 0;
     if (hkDom)
         rv = RegQueryValueEx(hkDom, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
     if (rv == ERROR_SUCCESS && dwType == REG_MULTI_SZ) {
         hkTemp = hkDom;
-        DebugEvent("Located TheseCells in hkDom");
-    } else if (hkDoms)
+        DebugEvent("Located TheseCells in hkDom size %d", dwSize);
+    } else if (hkDoms) {
         rv = RegQueryValueEx(hkDoms, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
-    if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
-        hkTemp = hkDoms;
-        DebugEvent("Located TheseCells in hkDoms");
-    } else if (hkNp)
-        rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
-    if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
-        hkTemp = hkNp;
-        DebugEvent("Located TheseCells in hkNp");
+        if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
+            hkTemp = hkDoms;
+            DebugEvent("Located TheseCells in hkDoms size %d", dwSize);
+        } else if (hkNp) {
+            rv = RegQueryValueEx(hkNp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, NULL, &dwSize);
+            if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_MULTI_SZ) {
+                hkTemp = hkNp;
+                DebugEvent("Located TheseCells in hkNp size %d", dwSize);
+            }
+        }
     }
 
     if (hkTemp) {
-        CHAR * thesecells;
+        CHAR * thesecells = NULL;
 
         /* dwSize still has the size of the required buffer in bytes. */
-        thesecells = malloc(dwSize);
-        rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, &dwType, (LPBYTE) thesecells, &dwSize);
+        thesecells = malloc(dwSize*2);
+        if (!thesecells)
+            goto doneTheseCells;
+        dwSize *= 2;
+        SetLastError(0);
+        rv = RegQueryValueEx(hkTemp, REG_CLIENT_THESE_CELLS_PARM, 0, NULL, (LPBYTE) thesecells, &dwSize);
         if(rv != ERROR_SUCCESS) {/* what the ..? */
-            DebugEvent("Can't look up TheseCells [%d]",rv);
+            DebugEvent("Can't look up TheseCells rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
             goto doneTheseCells;
         }
 
         DebugEvent("Found TheseCells [%s]", thesecells);
         opt->theseCells = thesecells;
+        thesecells = NULL;
+
+      doneTheseCells:
+        if (thesecells) free(thesecells);
+    }
+
+    DebugEvent0("Looking up Realm");
+    /* Realm */
+    /* First find out where the key is */
+    hkTemp = NULL;
+    rv = ~ERROR_SUCCESS;
+    dwSize = 0;
+    if (hkDom)
+        rv = RegQueryValueEx(hkDom, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
+    if (rv == ERROR_SUCCESS && dwType == REG_SZ) {
+        hkTemp = hkDom;
+        DebugEvent("Located Realm in hkDom size %d", dwSize);
+    } else if (hkDoms) {
+        rv = RegQueryValueEx(hkDoms, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
+        if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
+            hkTemp = hkDoms;
+            DebugEvent("Located Realm in hkDoms size %d", dwSize);
+        } else if (hkNp) {
+            rv = RegQueryValueEx(hkNp, REG_CLIENT_REALM_PARM, 0, &dwType, NULL, &dwSize);
+            if (rv == ERROR_SUCCESS && !hkTemp && dwType == REG_SZ) {
+                hkTemp = hkNp;
+                DebugEvent("Located Realm in hkNp size %d", dwSize);
+            }
+        }
+    }
+
+    if (hkTemp) {
+        CHAR * realm = NULL;
 
-      doneTheseCells:;
+        /* dwSize still has the size of the required buffer in bytes. */
+        realm = malloc(dwSize*2);
+        if (!realm)
+            goto doneRealm;
+        dwSize *=2;
+        SetLastError(0);
+        rv = RegQueryValueEx(hkTemp, REG_CLIENT_REALM_PARM, 0, NULL, (LPBYTE) realm, &dwSize);
+        if(rv != ERROR_SUCCESS) {/* what the ..? */
+            DebugEvent("Can't look up Realm rv [%d] size [%d] gle [%d]",rv, dwSize, GetLastError());
+            goto doneRealm;
+        }
+
+        DebugEvent("Found Realm [%s]", realm);
+        opt->realm = realm;
+        realm = NULL;
+
+      doneRealm:
+        if (realm) free(realm);
     }
 
   cleanup:
@@ -633,8 +763,8 @@ UnicodeStringToANSI(UNICODE_STRING uInputString, LPSTR lpszOutputString, int nOu
         lpszOutputString[min(uInputString.Length/2,nOutStringLen-1)] = '\0';
         return TRUE;
     }
-    else
-        lpszOutputString[0] = '\0';
+      
+    lpszOutputString[0] = '\0';
     return FALSE;
 }  // UnicodeStringToANSI
 
@@ -678,6 +808,15 @@ DWORD APIENTRY NPLogonNotify(
     int retryInterval;
     int sleepInterval;
 
+    /* Are we interactive? */
+    interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
+
+#ifdef DISABLE_NON_INTERACTIVE
+    /* Do not do anything if the logon session is not interactive. */
+    if (!interactive)
+       return 0;
+#endif
+
     (void) RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                          0, KEY_QUERY_VALUE, &NPKey);
     LSPsize=sizeof(TraceOption);
@@ -697,8 +836,8 @@ DWORD APIENTRY NPLogonNotify(
     /* MSV1_0_INTERACTIVE_LOGON and KERB_INTERACTIVE_LOGON are equivalent for
      * our purposes */
 
-    if ( wcscmp(lpAuthentInfoType,L"MSV1_0:Interactive") && 
-         wcscmp(lpAuthentInfoType,L"Kerberos:Interactive") )
+    if ( wcsicmp(lpAuthentInfoType,L"MSV1_0:Interactive") && 
+         wcsicmp(lpAuthentInfoType,L"Kerberos:Interactive") )
     {
         DebugEvent("Unsupported Authentication Info Type: %S",
                    lpAuthentInfoType);
@@ -707,15 +846,13 @@ DWORD APIENTRY NPLogonNotify(
 
     IL = (MSV1_0_INTERACTIVE_LOGON *) lpAuthentInfo;
 
-    /* Are we interactive? */
-    interactive = (wcscmp(lpStationName, L"WinSta0") == 0);
-
     /* Convert from Unicode to ANSI */
 
     /*TODO: Use SecureZeroMemory to erase passwords */
-    UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH);
-    UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH);
-    UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH);
+    if (!UnicodeStringToANSI(IL->UserName, uname, MAX_USERNAME_LENGTH) ||
+        !UnicodeStringToANSI(IL->Password, password, MAX_PASSWORD_LENGTH) ||
+        !UnicodeStringToANSI(IL->LogonDomainName, logonDomain, MAX_DOMAIN_LENGTH))
+       return 0;
 
     /* Make sure AD-DOMANS sent from login that is sent to us is striped */
     ctemp = strchr(uname, '@');
@@ -751,11 +888,11 @@ DWORD APIENTRY NPLogonNotify(
     /* Check for zero length password if integrated logon*/
     if ( ISLOGONINTEGRATED(opt.LogonOption) )  {
         if ( password[0] == 0 ) {
-            DebugEvent("Password is the empty string");
+            DebugEvent0("Password is the empty string");
             code = GT_PW_NULL;
             reason = "zero length password is illegal";
             code=0;
-        }       
+        }
 
         /* Get cell name if doing integrated logon.  
            We might overwrite this if we are logging into an AD realm and we find out that
@@ -763,7 +900,7 @@ DWORD APIENTRY NPLogonNotify(
         DebugEvent("About to call cm_GetRootCellName(%s)",cell);
         code = cm_GetRootCellName(cell);
         if (code < 0) { 
-            DebugEvent("Unable to obtain Root Cell");
+            DebugEvent0("Unable to obtain Root Cell");
             code = KTC_NOCELL;
             reason = "unknown cell";
             code=0;
@@ -775,143 +912,185 @@ DWORD APIENTRY NPLogonNotify(
            cell right away because the client service may not have started yet. This call
            also sets the AD_REALM flag in opt.flags if applicable. */
         if (ISREMOTE(opt.flags)) {
-            DebugEvent("Is Remote");
+            DebugEvent0("Is Remote");
             GetAdHomePath(homePath,MAX_PATH,lpLogonId,&opt);
-        }       
+        }
     }
 
     /* loop until AFS is started. */
-    while (IsServiceRunning() || IsServiceStartPending()) {
-        DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
-                    opt.LogonOption,afsWillAutoStart);
-
-        if (ISADREALM(opt.flags)) {
-            code = GetFileCellName(homePath,cell,256);
-            if (!code) {
-                DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
-            }
-            /* Don't bail out if GetFileCellName failed.
-             * The home dir may not be in AFS after all. 
-             */
-        } else
-            code=0;
+    if (afsWillAutoStart) {
+       while (IsServiceRunning() || IsServiceStartPending()) {
+           DebugEvent("while(autostart) LogonOption[%x], Service AutoStart[%d]",
+                       opt.LogonOption,afsWillAutoStart);
+
+           if (ISADREALM(opt.flags)) {
+               code = GetFileCellName(homePath,cell,256);
+               if (!code) {
+                   DebugEvent("profile path [%s] is in cell [%s]",homePath,cell);
+               }
+               /* Don't bail out if GetFileCellName failed.
+                * The home dir may not be in AFS after all. 
+                */
+           } else
+               code=0;
                
-        /* if Integrated Logon  */
-        if (ISLOGONINTEGRATED(opt.LogonOption))
-        {                      
-            if ( KFW_is_available() ) {
-                code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
-                DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
-                           uname,opt.smbName,cell,code);
-                if (code == 0 && opt.theseCells) { 
-                    char * principal, *p;
-
-                    principal = (char *)malloc(strlen(uname) + strlen(cell) + 2);
-                    if ( principal ) {
-                        strcpy(principal, uname);
-                        p = principal + strlen(uname);
-                        *p++ = '@';
-                        strcpy(p, cell);
-                        for ( ;*p; p++) {
-                            *p = toupper(*p);
-                        }
-
-                        p = opt.theseCells;
-                        while ( *p ) {
-                            code2 = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
+           /* if Integrated Logon  */
+           if (ISLOGONINTEGRATED(opt.LogonOption))
+           {                   
+               if ( KFW_is_available() ) {
+                   SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
+                    if (opt.realm) {
+                       char * principal, *p;
+                       size_t len, tlen;
+
+                       StringCchLength(opt.realm, MAX_DOMAIN_LENGTH, &tlen);
+                       len = tlen;
+                       StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
+                       len += tlen + 2;
+
+                       /* tlen is now the length of uname in characters */
+                       principal = (char *)malloc(len * sizeof(char));
+                       if ( principal ) {
+                           StringCchCopy(principal, len, uname);
+                           p = principal + tlen;
+                           *p++ = '@';
+                            StringCchCopy(p, len - tlen -1, opt.realm);
+                            code = KFW_AFS_get_cred(principal, cell, password, 0, opt.smbName, &reason);
                             DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
-                                        principal,opt.smbName,p,code2);
-                            p += strlen(p) + 1;
-                        }
-                        
-                        free(principal);
+                                           principal,opt.smbName,cell,code);
+                           free(principal);
+                       }
+                    } else {
+                        code = KFW_AFS_get_cred(uname, cell, password, 0, opt.smbName, &reason);
+                        DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
+                                    uname,opt.smbName,cell,code);
                     }
-                }
-            } else {
-                code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
-                                                    uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
-                                                    &reason);
-               DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
-                           code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
-            }       
-            if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
-                for ( ctemp = uname; *ctemp ; ctemp++) {
-                    *ctemp = tolower(*ctemp);
-                }
-                lowercased_name = TRUE;
-                goto sleeping;
-            }
-
-            /* is service started yet?*/
-
-            /* If we've failed because the client isn't running yet and the
-            * client is set to autostart (and therefore it makes sense for
-            * us to wait for it to start) then sleep a while and try again. 
-            * If the error was something else, then give up. */
-            if (code != KTC_NOCM && code != KTC_NOCMRPC)
-                break;
-        }
-        else {  
-            /*JUST check to see if its running*/
-            if (IsServiceRunning())
-                break;
-            if (!IsServiceStartPending()) {
-                code = KTC_NOCMRPC;
-                reason = "AFS Service start failed";
-                break;
-            }
-        }
-
-        /* If the retry interval has expired and we still aren't
-         * logged in, then just give up if we are not in interactive
-         * mode or the failSilently flag is set, otherwise let the
-         * user know we failed and give them a chance to try again. */
-        if (retryInterval <= 0) {
-            reason = "AFS not running";
-            if (!interactive || opt.failSilently)
-                break;
-            flag = MessageBox(hwndOwner,
-                               "AFS is still starting.  Retry?",
-                               "AFS Logon",
-                               MB_ICONQUESTION | MB_RETRYCANCEL);
-            if (flag == IDCANCEL)
-                break;
-
-            /* Wait just a little while and try again */
-            retryInterval = opt.retryInterval;
-        }
-
-      sleeping:
-        Sleep(sleepInterval * 1000);
-        retryInterval -= sleepInterval;
+                   SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
+                   if (code == 0 && opt.theseCells) { 
+                       char * principal, *p;
+                       size_t len, tlen;
+
+                       StringCchLength(opt.realm ? opt.realm : cell, MAX_DOMAIN_LENGTH, &tlen);
+                       len = tlen;
+                       StringCchLength(uname, MAX_USERNAME_LENGTH, &tlen);
+                       len += tlen + 2;
+
+                       /* tlen is now the length of uname in characters */
+                       principal = (char *)malloc(len * sizeof(char));
+                       if ( principal ) {
+                           StringCchCopy(principal, len, uname);
+                           p = principal + tlen;
+                           *p++ = '@';
+                            if (opt.realm) {
+                                StringCchCopy(p, len - tlen -1, opt.realm);
+                            } else {
+                                StringCchCopy(p, len - tlen - 1, cell);
+                                for ( ;*p; p++) {
+                                    *p = toupper(*p);
+                                }
+                            }
+                           p = opt.theseCells;
+                           while ( *p ) {
+                                if ( cm_stricmp_utf8(p, cell) ) {
+                                    SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, "");
+                                    code2 = KFW_AFS_get_cred(principal, p, 0, 0, opt.smbName, &reason);
+                                    SetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL);
+                                    DebugEvent("KFW_AFS_get_cred  uname=[%s] smbname=[%s] cell=[%s] code=[%d]",
+                                               principal,opt.smbName,p,code2);
+                                }
+                               p += strlen(p) + 1;
+                           }
+                           free(principal);
+                       }
+                   }
+               } else {
+                   code = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
+                                                       uname, "", cell, password, opt.smbName, 0, &pw_exp, 0,
+                                                       &reason);
+                   DebugEvent("AFS AfsLogon - (INTEGRATED only)ka_UserAuthenticateGeneral2 Code[%x] uname[%s] smbname=[%s] Cell[%s] PwExp=[%d] Reason=[%s]",
+                               code,uname,opt.smbName,cell,pw_exp,reason?reason:"");
+               }       
+               if ( code && code != KTC_NOCM && code != KTC_NOCMRPC && !lowercased_name ) {
+                   for ( ctemp = uname; *ctemp ; ctemp++) {
+                       *ctemp = tolower(*ctemp);
+                   }
+                   lowercased_name = TRUE;
+                   goto sleeping;
+               }
+
+               /* is service started yet?*/
+
+               /* If we've failed because the client isn't running yet and the
+                * client is set to autostart (and therefore it makes sense for
+                * us to wait for it to start) then sleep a while and try again. 
+                * If the error was something else, then give up. */
+               if (code != KTC_NOCM && code != KTC_NOCMRPC)
+                   break;
+           }
+           else {  
+               /*JUST check to see if its running*/
+               if (IsServiceRunning())
+                   break;
+               if (!IsServiceStartPending()) {
+                   code = KTC_NOCMRPC;
+                   reason = "AFS Service start failed";
+                   break;
+               }
+           }
+
+           /* If the retry interval has expired and we still aren't
+            * logged in, then just give up if we are not in interactive
+            * mode or the failSilently flag is set, otherwise let the
+            * user know we failed and give them a chance to try again. */
+           if (retryInterval <= 0) {
+               reason = "AFS not running";
+               if (!interactive || opt.failSilently)
+                   break;
+               flag = MessageBox(hwndOwner,
+                                  "AFS is still starting.  Retry?",
+                                  "AFS Logon",
+                                  MB_ICONQUESTION | MB_RETRYCANCEL);
+               if (flag == IDCANCEL)
+                   break;
+
+               /* Wait just a little while and try again */
+               retryInterval = opt.retryInterval;
+           }
+
+         sleeping:
+           Sleep(sleepInterval * 1000);
+           retryInterval -= sleepInterval;
+       }
     }
+    DebugEvent0("while loop exited");
 
-    DebugEvent("while loop exited");
     /* remove any kerberos 5 tickets currently held by the SYSTEM account
      * for this user 
      */
-    if ( KFW_is_available() ) {
-        sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
-        KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
 
-        KFW_AFS_destroy_tickets_for_principal(uname);
+    if (ISLOGONINTEGRATED(opt.LogonOption) && KFW_is_available()) {
+#ifdef KFW_LOGON
+       sprintf(szLogonId,"%d.%d",lpLogonId->HighPart, lpLogonId->LowPart);
+       KFW_AFS_copy_cache_to_system_file(uname, szLogonId);
+#endif
+       KFW_AFS_destroy_tickets_for_principal(uname);
     }
 
     if (code) {
-        char msg[128];
-        HANDLE h;
-        char *ptbuf[1];
+       char msg[128];
+       HANDLE h;
+       char *ptbuf[1];
 
-        StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
+       StringCbPrintf(msg, sizeof(msg), "Integrated login failed: %s", reason);
 
-        if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
-            MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
+       if (ISLOGONINTEGRATED(opt.LogonOption) && interactive && !opt.failSilently)
+           MessageBox(hwndOwner, msg, "AFS Logon", MB_OK);
 
-        h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
-        ptbuf[0] = msg;
-        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
-                     1, 0, ptbuf, NULL);
-        DeregisterEventSource(h);
+       h = RegisterEventSource(NULL, AFS_LOGON_EVENT_NAME);
+       ptbuf[0] = msg;
+       ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1008, NULL,
+                    1, 0, ptbuf, NULL);
+       DeregisterEventSource(h);
            
         code = MapAuthError(code);
         SetLastError(code);
@@ -928,6 +1107,7 @@ DWORD APIENTRY NPLogonNotify(
 
     if (opt.theseCells) free(opt.theseCells);
     if (opt.smbName) free(opt.smbName);
+    if (opt.realm) free(opt.realm);
 
     DebugEvent("AFS AfsLogon - Exit","Return Code[%x]",code);
     return code;
@@ -942,6 +1122,15 @@ DWORD APIENTRY NPPasswordChangeNotify(
        LPVOID StationHandle,
        DWORD dwChangeInfo)
 {
+    BOOLEAN interactive;
+
+    /* Are we interactive? */
+    interactive = (wcsicmp(lpStationName, L"WinSta0") == 0);
+
+    /* Do not do anything if the logon session is not interactive. */
+    if (!interactive)
+       return 0;
+
     /* Make sure the AFS Libraries are initialized */
     AfsLogonInit();
 
@@ -1011,6 +1200,7 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
     DWORD LSPtype, LSPsize;
     HKEY NPKey;
     DWORD LogoffPreserveTokens = 0;
+    LogonOptions_t opt;
 
     /* Make sure the AFS Libraries are initialized */
     AfsLogonInit();
@@ -1024,47 +1214,75 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo )
                      &LSPtype, (LPBYTE)&LogoffPreserveTokens, &LSPsize);
     RegCloseKey (NPKey);
 
-    if (LogoffPreserveTokens) {
-        if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
-        {
-            if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
-                tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
+    if (!LogoffPreserveTokens) {
+       memset(&opt, 0, sizeof(LogonOptions_t));
 
-                if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
-                {
-                    DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
-                }
-            }
-        }
+       if (pInfo->UserName && pInfo->Domain) {
+           char username[MAX_USERNAME_LENGTH] = "";
+           char domain[MAX_DOMAIN_LENGTH] = "";
+           size_t szlen = 0;
 
-        /* We can't use pInfo->Domain for the domain since in the cross realm case 
-         * this is source domain and not the destination domain.
-         */
-        if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
-            WCHAR Domain[64]=L"";
-            GetLocalShortDomain(Domain, sizeof(Domain));
-            if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
-                if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
-                    GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
-            }
-        }
+           StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
+           WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
+                                username, sizeof(username), NULL, NULL);
 
-        if (strlen(profileDir)) {
-            DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
-            if (!IsPathInAfs(profileDir)) {
-                if (code = ktc_ForgetAllTokens())
-                    DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
-                else
-                    DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
-            } else {
-                DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
-            }
-        } else {
-            DebugEvent0("AFS_Logoff_Event - Unable to load profile");
-        }
+           StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
+           WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
+                                domain, sizeof(domain), NULL, NULL);
+
+           GetDomainLogonOptions(NULL, username, domain, &opt);
+       }
 
-        if ( tokenUser )
-            LocalFree(tokenUser);
+        if (ISREMOTE(opt.flags)) {
+           if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
+           {
+               if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
+                   tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
+
+                   if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen))
+                   {
+                       DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError());
+                   }
+               }
+           }
+
+           /* We can't use pInfo->Domain for the domain since in the cross realm case 
+            * this is source domain and not the destination domain.
+            */
+           if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
+               WCHAR Domain[64]=L"";
+               GetLocalShortDomain(Domain, sizeof(Domain));
+               if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
+                   if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len))
+                       GetUserProfileDirectory(pInfo->hToken, profileDir, &len);
+               }
+           }
+
+           if (strlen(profileDir)) {
+               DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir);
+               if (!IsPathInAfs(profileDir)) {
+                   if (code = ktc_ForgetAllTokens())
+                       DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
+                   else
+                       DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
+               } else {
+                   DebugEvent0("AFS_Logoff_Event - Tokens left in place; profile in AFS");
+               }
+           } else {
+               DebugEvent0("AFS_Logoff_Event - Unable to load profile");
+           }
+
+           if ( tokenUser )
+               LocalFree(tokenUser);
+       } else {
+           DebugEvent0("AFS_Logoff_Event - Local Logon");
+           if (code = ktc_ForgetAllTokens())
+               DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code);
+           else
+               DebugEvent0("AFS_Logoff_Event - ForgetAllTokens succeeded");
+       }
+    } else {
+       DebugEvent0("AFS_Logoff_Event - Preserving Tokens");
     }
 
     DebugEvent0("AFS_Logoff_Event - End");
@@ -1083,6 +1301,7 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
     NETRESOURCE nr;
     DWORD res;
     DWORD dwSize;
+    LogonOptions_t opt;
 
     /* Make sure the AFS Libraries are initialized */
     AfsLogonInit();
@@ -1091,6 +1310,42 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
 
     DebugEvent("AFS_Logon_Event Process ID: %d",GetCurrentProcessId());
 
+    memset(&opt, 0, sizeof(LogonOptions_t));
+
+    if (pInfo->UserName && pInfo->Domain) {
+        char username[MAX_USERNAME_LENGTH] = "";
+        char domain[MAX_DOMAIN_LENGTH] = "";
+        size_t szlen = 0;
+
+       DebugEvent0("AFS_Logon_Event - pInfo UserName and Domain");
+
+        StringCchLengthW(pInfo->UserName, MAX_USERNAME_LENGTH, &szlen);
+        WideCharToMultiByte(CP_UTF8, 0, pInfo->UserName, szlen,
+                            username, sizeof(username), NULL, NULL);
+        
+        StringCchLengthW(pInfo->Domain, MAX_DOMAIN_LENGTH, &szlen);
+        WideCharToMultiByte(CP_UTF8, 0, pInfo->Domain, szlen,
+                            domain, sizeof(domain), NULL, NULL);
+
+       DebugEvent0("AFS_Logon_Event - Calling GetDomainLogonOptions");
+        GetDomainLogonOptions(NULL, username, domain, &opt);
+    } else {
+       if (!pInfo->UserName)
+           DebugEvent0("AFS_Logon_Event - No pInfo->UserName");
+       if (!pInfo->Domain)
+           DebugEvent0("AFS_Logon_Event - No pInfo->Domain");
+    }
+
+    DebugEvent("AFS_Logon_Event - opt.LogonOption = %lX opt.flags = %lX", 
+               opt.LogonOption, opt.flags);
+
+    if (!ISLOGONINTEGRATED(opt.LogonOption) || !ISREMOTE(opt.flags)) {
+        DebugEvent0("AFS_Logon_Event - Logon is not integrated or not remote");
+        goto done_logon_event;
+    }
+
+    DebugEvent0("AFS_Logon_Event - Calling GetTokenInformation");
+
     if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen))
     {
         if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
@@ -1106,7 +1361,7 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
     /* We can't use pInfo->Domain for the domain since in the cross realm case 
      * this is source domain and not the destination domain.
      */
-    if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
+    if (tokenUser && QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) {
         WCHAR Domain[64]=L"";
         GetLocalShortDomain(Domain, sizeof(Domain));
         if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) {
@@ -1121,6 +1376,7 @@ VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
         DebugEvent0("AFS_Logon_Event - Unable to load profile");
     }
 
+  done_logon_event:
     dwSize = sizeof(szUserA);
     if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) {
         StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName);
@@ -1178,15 +1434,18 @@ GetSecurityLogonSessionData(HANDLE hToken, PSECURITY_LOGON_SESSION_DATA * ppSess
 
 VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
 {
+#ifdef KFW_LOGON
     WCHAR szUserW[128] = L"";
     char  szUserA[128] = "";
     char szPath[MAX_PATH] = "";
     char szLogonId[128] = "";
     DWORD count;
-    char filename[256];
-    char commandline[512];
+    char filename[MAX_PATH] = "";
+    char newfilename[MAX_PATH] = "";
+    char commandline[MAX_PATH+256] = "";
     STARTUPINFO startupinfo;
     PROCESS_INFORMATION procinfo;
+    HANDLE hf = INVALID_HANDLE_VALUE;
 
     LUID LogonId = {0, 0};
     PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL;
@@ -1216,14 +1475,56 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
         GetWindowsDirectory(filename, sizeof(filename));
     }
 
-    if ( strlen(filename) + strlen(szLogonId) + 2 <= sizeof(filename) ) {
-        strcat(filename, "\\");
-        strcat(filename, szLogonId);    
+    count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
+    if ( count > sizeof(filename) || count == 0 ) {
+        GetWindowsDirectory(filename, sizeof(filename));
+    }
+
+    if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) ) {
+        DebugEvent0("KFW_Logon_Event - filename too long");
+       return;
+    }
+
+    strcat(filename, "\\");
+    strcat(filename, szLogonId);    
 
-        sprintf(commandline, "afscpcc.exe \"%s\"", filename);
+    hf = CreateFile(filename, FILE_ALL_ACCESS, 0, NULL, OPEN_EXISTING, 
+                    FILE_ATTRIBUTE_NORMAL, NULL);
+    if (hf == INVALID_HANDLE_VALUE) {
+       DebugEvent0("KFW_Logon_Event - file cannot be opened");
+       return;
+    }
+    CloseHandle(hf);
+    if (KFW_AFS_set_file_cache_dacl(filename, pInfo->hToken)) {
+       DebugEvent0("KFW_Logon_Event - unable to set dacl");
+       DeleteFile(filename);
+       return;
+    }
+    if (KFW_AFS_obtain_user_temp_directory(pInfo->hToken, newfilename, sizeof(newfilename))) {
+       DebugEvent0("KFW_Logon_Event - unable to obtain temp directory");
+       return;
+    }
 
-        GetStartupInfo(&startupinfo);
-        if (CreateProcessAsUser( pInfo->hToken,
+    if ( strlen(newfilename) + strlen(szLogonId) + 2 > sizeof(newfilename) ) {
+        DebugEvent0("KFW_Logon_Event - new filename too long");
+       return;
+    }
+
+    strcat(newfilename, "\\");
+    strcat(newfilename, szLogonId);    
+
+    if (!MoveFileEx(filename, newfilename, 
+                    MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
+        DebugEvent("KFW_Logon_Event - MoveFileEx failed GLE = 0x%x", GetLastError());
+       return;
+    }
+
+    sprintf(commandline, "afscpcc.exe \"%s\"", newfilename);
+
+    GetStartupInfo(&startupinfo);
+    if (CreateProcessAsUser( pInfo->hToken,
                              "afscpcc.exe",
                              commandline,
                              NULL,
@@ -1234,16 +1535,20 @@ VOID KFW_Logon_Event( PWLX_NOTIFICATION_INFO pInfo )
                              NULL,
                              &startupinfo,
                              &procinfo)) 
-        {
-            WaitForSingleObject(procinfo.hProcess, 30000);
+    {
+       DebugEvent("KFW_Logon_Event - CommandLine %s", commandline);
 
-            CloseHandle(procinfo.hThread);
-            CloseHandle(procinfo.hProcess);
-        }
+       WaitForSingleObject(procinfo.hProcess, 30000);
+
+       CloseHandle(procinfo.hThread);
+       CloseHandle(procinfo.hProcess);
+    } else {
+       DebugEvent0("KFW_Logon_Event - CreateProcessFailed");
     }
 
     DeleteFile(filename);
 
     DebugEvent0("KFW_Logon_Event - End");
+#endif
 }