smb-extended-20040724
[openafs.git] / src / WINNT / afsd / smb.c
index 73c5ef5..3d6448e 100644 (file)
@@ -9,8 +9,6 @@
 
 //#define NOSERVICE 1
 
-#define NOMOREFILESFIX 1
-
 #include <afs/param.h>
 #include <afs/stds.h>
 
@@ -28,6 +26,7 @@
 #include <time.h>
 
 #include <osi.h>
+#include <ntstatus.h>
 
 #include "afsd.h"
 
@@ -46,9 +45,7 @@ char *loggedOutName = NULL;
 smb_user_t *loggedOutUserp = NULL;
 unsigned long loggedOutTime;
 int loggedOut = 0;
-#ifdef DJGPP
 int smbShutdownFlag = 0;
-#endif /* DJGPP */
 
 int smb_LogoffTokenTransfer;
 unsigned long smb_LogoffTransferTimeout;
@@ -84,11 +81,16 @@ smb_ncb_t *smb_ncbFreeListp;
 
 int smb_NumServerThreads;
 
-int numNCBs, numSessions;
+int numNCBs, numSessions, numVCs;
 
 int smb_maxVCPerServer;
 int smb_maxMpxRequests;
 
+int smb_authType = SMB_AUTH_EXTENDED; /* type of SMB auth to use. One of SMB_AUTH_* */
+HANDLE smb_lsaHandle;
+ULONG smb_lsaSecPackage;
+LSA_STRING smb_lsaLogonOrigin;
+
 #define NCBmax MAXIMUM_WAIT_OBJECTS
 EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
 EVENT_HANDLE **NCBreturns;
@@ -113,6 +115,9 @@ int smb_RawBufSel[SMB_RAW_BUFS];
 char *smb_RawBufs;
 #endif /* DJGPP */
 
+#define SMB_MASKFLAG_TILDE 1
+#define SMB_MASKFLAG_CASEFOLD 2
+
 #define RAWTIMEOUT INFINITE
 
 /* for raw write */
@@ -141,8 +146,10 @@ int smb_hideDotFiles;
 int smb_useV3;         /* try to negotiate V3 */
 
 #ifndef DJGPP
+static showErrors = 1;
 /* MessageBox or something like it */
-int (WINAPI *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+extern HANDLE WaitToTerminate;
 #endif /* DJGPP */
 
 /* GMT time info:
@@ -184,6 +191,16 @@ extern char cm_confDir[];
 
 extern char AFSConfigKeyName[];
 
+char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
+int smb_ServerDomainNameLength = 0;
+char smb_ServerOS[] = "Windows 5.0"; /* Faux OS String */
+int smb_ServerOSLength = sizeof(smb_ServerOS);
+char smb_ServerLanManager[] = "Windows 2000 LAN Manager"; /* Faux LAN Manager string */
+int smb_ServerLanManagerLength = sizeof(smb_ServerLanManager);
+
+/* Faux server GUID. This is never checked. */
+GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
+
 /*
  * Demo expiration
  *
@@ -248,6 +265,10 @@ char * myCrt_Dispatch(int i)
                return "(23)ReceiveV3GetAttributes";
        case 0x24:
                return "(24)ReceiveV3LockingX";
+       case 0x25:
+               return "(25)ReceiveV3Trans";
+       case 0x26:
+               return "(26)ReceiveV3Trans[aux]";
        case 0x29:
                return "(29)SendCoreBadOp";
        case 0x2b:
@@ -259,7 +280,7 @@ char * myCrt_Dispatch(int i)
        case 0x32:
                return "(32)ReceiveV3Tran2A";
        case 0x33:
-               return "(33)ReceiveV3Tran2A";
+               return "(33)ReceiveV3Tran2A[aux]";
        case 0x34:
                return "(34)ReceiveV3FindClose";
        case 0x35:
@@ -334,6 +355,23 @@ char * myCrt_2Dispatch(int i)
        }
 }
 
+char * myCrt_RapDispatch(int i)
+{
+       switch(i)
+       {
+       default:
+               return "unknown RAP OP";
+       case 0:
+               return "RAP(0)NetShareEnum";
+       case 1:
+               return "RAP(1)NetShareGetInfo";
+       case 13:
+               return "RAP(13)NetServerGetInfo";
+       case 63:
+               return "RAP(63)NetWkStaGetInfo";
+       }
+}
+
 /* scache must be locked */
 unsigned int smb_Attributes(cm_scache_t *scp)
 {
@@ -402,7 +440,7 @@ void ShowUnixTime(char *FuncName, long unixTime)
        smb_LargeSearchTimeFromUnixTime(&ft, unixTime);
                 
        if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
-               osi_Log1(afsd_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
+               osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
        else {
                int day, month, year, sec, min, hour;
                char msg[256];
@@ -416,7 +454,7 @@ void ShowUnixTime(char *FuncName, long unixTime)
                hour = ExtractBits(wTime, 11, 5);
 
                sprintf(msg, "%s = %02d-%02d-%04d %02d:%02d:%02d", FuncName, month, day, year, hour, min, sec);
-               osi_Log1(afsd_logp, "%s", osi_LogSaveString(afsd_logp, msg));
+               osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
        }
 }
 #endif /* DJGPP */
@@ -530,7 +568,14 @@ smb_CalculateNowTZ()
        local_tm = *(localtime(&t));
 
        days = local_tm.tm_yday - gmt_tm.tm_yday;
-       hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour;
+       hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour
+#ifdef COMMENT
+        /* There is a problem with DST immediately after the time change
+         * which may continue to exist until the machine is rebooted
+         */
+        - (local_tm.tm_isdst ? 1 : 0)
+#endif /* COMMENT */
+        ;
        minutes = 60 * hours + local_tm.tm_min - gmt_tm.tm_min;
        seconds = 60 * minutes + local_tm.tm_sec - gmt_tm.tm_sec;
 
@@ -718,6 +763,7 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
        if (!vcp && (flags & SMB_FLAG_CREATE)) {
                vcp = malloc(sizeof(*vcp));
                memset(vcp, 0, sizeof(*vcp));
+        vcp->vcID = numVCs++;
                vcp->refCount = 1;
                vcp->tidCounter = 1;
                vcp->fidCounter = 1;
@@ -727,6 +773,33 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
                lock_InitializeMutex(&vcp->mx, "vc_t mutex");
                vcp->lsn = lsn;
                vcp->lana = lana;
+        vcp->secCtx = NULL;
+
+               if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+            /* We must obtain a challenge for extended auth 
+             * in case the client negotiates smb v3 
+             */
+            NTSTATUS nts,ntsEx;
+                       MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
+                       PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp;
+                       ULONG lsaRespSize;
+
+                       lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
+
+                       nts = LsaCallAuthenticationPackage( smb_lsaHandle,
+                                                smb_lsaSecPackage,
+                                                &lsaReq,
+                                                sizeof(lsaReq),
+                                                &lsaResp,
+                                                &lsaRespSize,
+                                                &ntsEx);
+                       osi_assert(nts == STATUS_SUCCESS); /* this had better work! */
+
+                       memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
+            LsaFreeReturnBuffer(lsaResp);
+               }
+               else
+                       memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
        }
        lock_ReleaseWrite(&smb_rctLock);
        return vcp;
@@ -775,6 +848,7 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
                tidp->nextp = vcp->tidsp;
                tidp->refCount = 1;
                tidp->vcp = vcp;
+        vcp->refCount++;
                vcp->tidsp = tidp;
                lock_InitializeMutex(&tidp->mx, "tid_t mutex");
                tidp->tid = tid;
@@ -788,8 +862,10 @@ void smb_ReleaseTID(smb_tid_t *tidp)
        smb_tid_t *tp;
        smb_tid_t **ltpp;
        cm_user_t *userp;
+    smb_vc_t  *vcp;
 
        userp = NULL;
+    vcp = NULL;
        lock_ObtainWrite(&smb_rctLock);
        osi_assert(tidp->refCount-- > 0);
        if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
@@ -801,11 +877,15 @@ void smb_ReleaseTID(smb_tid_t *tidp)
                *ltpp = tp->nextp;
                lock_FinalizeMutex(&tidp->mx);
                userp = tidp->userp;    /* remember to drop ref later */
+        vcp = tidp->vcp;
        }
        lock_ReleaseWrite(&smb_rctLock);
        if (userp) {
                cm_ReleaseUser(userp);
        }       
+    if (vcp) {
+        smb_ReleaseVC(vcp);
+    }
 }      
 
 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
@@ -826,8 +906,9 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
                uidp->nextp = vcp->usersp;
                uidp->refCount = 1;
                uidp->vcp = vcp;
+        vcp->refCount++;
                vcp->usersp = uidp;
-               lock_InitializeMutex(&uidp->mx, "uid_t mutex");
+               lock_InitializeMutex(&uidp->mx, "user_t mutex");
                uidp->userID = uid;
                osi_LogEvent("AFS smb_FindUID (Find by UID)",NULL,"VCP[%x] new-uid[%d] name[%s]",(int)vcp,uidp->userID,(uidp->unp ? uidp->unp->name : ""));
        }
@@ -884,8 +965,10 @@ void smb_ReleaseUID(smb_user_t *uidp)
        smb_user_t *up;
        smb_user_t **lupp;
        cm_user_t *userp;
+    smb_vc_t  *vcp;
 
        userp = NULL;
+    vcp = NULL;
        lock_ObtainWrite(&smb_rctLock);
        osi_assert(uidp->refCount-- > 0);
        if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
@@ -896,14 +979,21 @@ void smb_ReleaseUID(smb_user_t *uidp)
                osi_assert(up != NULL);
                *lupp = up->nextp;
                lock_FinalizeMutex(&uidp->mx);
-               if (uidp->unp)
+               if (uidp->unp) {
                        userp = uidp->unp->userp;       /* remember to drop ref later */
+            uidp->unp->userp = NULL;
+        }
+        vcp = uidp->vcp;
+        uidp->vcp = NULL;
        }               
        lock_ReleaseWrite(&smb_rctLock);
        if (userp) {
                cm_ReleaseUserVCRef(userp);
                cm_ReleaseUser(userp);
        }       
+    if (vcp) {
+        smb_ReleaseVC(vcp);
+    }
 }      
 
 /* retrieve a held reference to a user structure corresponding to an incoming
@@ -967,20 +1057,25 @@ int smb_SUser(cm_user_t *userp)
        return 1;
 }
 
-/* find a file ID.  If pass in 0, we'll allocate on on a create operation. */
+/* find a file ID.  If we pass in 0 we select an used File ID.
+ * If the SMB_FLAG_CREATE flag is set, we allocate a new  
+ * smb_fid_t data structure if desired File ID cannot be found.
+ */
 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
 {
        smb_fid_t *fidp;
-       int newFid;
+       int newFid = 0;
         
+    if (fid == 0 && !(flags & SMB_FLAG_CREATE))
+        return NULL;
+
+       lock_ObtainWrite(&smb_rctLock);
        /* figure out if we need to allocate a new file ID */
        if (fid == 0) {
                newFid = 1;
                fid = vcp->fidCounter;
        }
-       else newFid = 0;
 
-       lock_ObtainWrite(&smb_rctLock);
 retry:
        for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
                if (fid == fidp->fid) {
@@ -996,21 +1091,32 @@ retry:
     }
     if (!fidp && (flags & SMB_FLAG_CREATE)) {
         char eventName[MAX_PATH];
-        sprintf(eventName,"fid_t event fid=%d", fid);
+        EVENT_HANDLE event;
+        sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
+        event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
+        if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+            afsi_log("Event Object Already Exists: %s", eventName);
+            thrd_CloseHandle(event);
+            fid++;
+            if (fid == 0)
+                fid = 1;
+            goto retry;
+        }
+
                fidp = malloc(sizeof(*fidp));
         memset(fidp, 0, sizeof(*fidp));
                osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
         fidp->refCount = 1;
         fidp->vcp = vcp;
+        vcp->refCount++;
         lock_InitializeMutex(&fidp->mx, "fid_t mutex");
         fidp->fid = fid;
                fidp->curr_chunk = fidp->prev_chunk = -2;
-               fidp->raw_write_event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
-        if ( GetLastError() == ERROR_ALREADY_EXISTS )
-            afsi_log("Event Object Already Exists: %s", eventName);
+               fidp->raw_write_event = event;
         if (newFid) {
-                       vcp->fidCounter = fid+1;
-            if (vcp->fidCounter == 0) vcp->fidCounter = 1;
+            vcp->fidCounter = fid+1;
+            if (vcp->fidCounter == 0) 
+                vcp->fidCounter = 1;
         }
     }
     lock_ReleaseWrite(&smb_rctLock);
@@ -1020,11 +1126,11 @@ retry:
 void smb_ReleaseFID(smb_fid_t *fidp)
 {
        cm_scache_t *scp;
-    smb_vc_t *vcp;
+    smb_vc_t *vcp = NULL;
     smb_ioctl_t *ioctlp;
 
     if (!fidp)
-        return NULL;
+        return;
 
        scp = NULL;
        lock_ObtainWrite(&smb_rctLock);
@@ -1046,6 +1152,9 @@ void smb_ReleaseFID(smb_fid_t *fidp)
         }
 
         free(fidp);
+
+        /* do not call smb_ReleaseVC() because we already have the lock */
+        vcp->refCount--;
     }
        lock_ReleaseWrite(&smb_rctLock);
 
@@ -1089,6 +1198,7 @@ char VNLCUserName[] = "%LCUSERNAME%";
 char VNComputerName[] = "%COMPUTERNAME%";
 char VNLCComputerName[] = "%LCCOMPUTERNAME%";
 
+#ifdef DJGPP
 /* List available shares */
 int smb_ListShares()
 {
@@ -1152,18 +1262,19 @@ int smb_ListShares()
 
        return num_shares;
 }
-
+#endif /* DJGPP */
 /* find a shareName in the table of submounts */
-int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
+int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
        char **pathNamep)
 {
        DWORD len;
        char pathName[1024];
        char *var;
-       smb_user_t *uidp;
        char temp[1024];
        DWORD sizeTemp;
+#ifdef DJGPP
     char sbmtpath[MAX_PATH];
+#endif
     char *p, *q;
        HKEY parmKey;
        DWORD code;
@@ -1205,13 +1316,24 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
        }
 
 #ifndef DJGPP
-    strcpy(sbmtpath, "afsdsbmt.ini");
+       code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts",
+                                               0, KEY_QUERY_VALUE, &parmKey);
+       if (code == ERROR_SUCCESS) {
+        len = sizeof(pathName);
+        code = RegQueryValueEx(parmKey, shareName, NULL, NULL,
+                                (BYTE *) pathName, &len);
+               if (code != ERROR_SUCCESS)
+                       len = 0;
+        RegCloseKey (parmKey);
+       } else {
+        len = 0;
+    }   
 #else /* DJGPP */
     strcpy(sbmtpath, cm_confDir);
     strcat(sbmtpath, "/afsdsbmt.ini");
-#endif /* !DJGPP */
        len = GetPrivateProfileString("AFS Submounts", shareName, "",
                                   pathName, sizeof(pathName), sbmtpath);
+#endif /* !DJGPP */
        if (len != 0 && len != sizeof(pathName) - 1) {
         /* We can accept either unix or PC style AFS pathnames.  Convert
          * Unix-style to PC style here for internal use. 
@@ -1228,25 +1350,19 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
         while (1)
         {
             if (var = smb_stristr(p, VNUserName)) {
-                uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
                 if (uidp && uidp->unp)
                     smb_subst(p, var, sizeof(VNUserName),uidp->unp->name);
                 else
                     smb_subst(p, var, sizeof(VNUserName)," ");
-                if (uidp)
-                    smb_ReleaseUID(uidp);
             }
             else if (var = smb_stristr(p, VNLCUserName)) 
             {
-                uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
                 if (uidp && uidp->unp)
                     strcpy(temp, uidp->unp->name);
                 else 
                     strcpy(temp, " ");
                 _strlwr(temp);
                 smb_subst(p, var, sizeof(VNLCUserName), temp);
-                if (uidp)
-                    smb_ReleaseUID(uidp);
             }
             else if (var = smb_stristr(p, VNComputerName)) 
             {
@@ -1269,21 +1385,79 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
     } 
     else /* create  \\<netbiosName>\<cellname>  */
     {
-        if (cm_GetCell_Gen(shareName, temp, CM_FLAG_CREATE))
-        {   
-                       int len = min(strlen(shareName), strlen(temp));
-            if (!_strnicmp(shareName, temp, len)) {  /* partial matches allowed */
-                sprintf(pathName,"/%s/",temp);
-                *pathNamep = strdup(strlwr(pathName));
-                               return 1;
-            }
-        } 
+        char * p = shareName; 
+        int rw = 0;
+
+        if ( *p == '.' ) {
+            p++;
+            rw = 1;
+        }
+        /* Get the full name for this cell */
+        code = cm_SearchCellFile(p, temp, 0, 0);
+#ifdef AFS_AFSDB_ENV
+               if (code && cm_dnsEnabled) {
+            int ttl;
+            code = cm_SearchCellByDNS(p, temp, &ttl, 0, 0);
+        }
+#endif
+        /* construct the path */
+        if (code == 0) {     
+            sprintf(pathName,rw ? "/.%s/" : "/%s/",temp);
+            *pathNamep = strdup(strlwr(pathName));
+            return 1;
+        }
        }
     /* failure */
     *pathNamep = NULL;
     return 0;
 }
 
+/* Client-side offline caching policy types */
+#define CSC_POLICY_MANUAL 0
+#define CSC_POLICY_DOCUMENTS 1
+#define CSC_POLICY_PROGRAMS 2
+#define CSC_POLICY_DISABLE 3
+
+int smb_FindShareCSCPolicy(char *shareName)
+{
+       DWORD len;
+       char policy[1024];
+    DWORD dwType;
+    HKEY hkCSCPolicy;
+    int  retval = CSC_POLICY_MANUAL;
+
+    RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
+                    "SOFTWARE\\OpenAFS\\Client\\CSCPolicy",
+                    0, 
+                    "AFS", 
+                    REG_OPTION_NON_VOLATILE,
+                    KEY_READ,
+                    NULL, 
+                    &hkCSCPolicy,
+                    NULL );
+
+    len = sizeof(policy);
+    if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) ||
+         len == 0) {
+               retval = CSC_POLICY_MANUAL;
+    }
+       else if (stricmp(policy, "documents") == 0)
+       {
+               retval = CSC_POLICY_DOCUMENTS;
+       }
+       else if (stricmp(policy, "programs") == 0)
+       {
+               retval = CSC_POLICY_PROGRAMS;
+       }
+       else if (stricmp(policy, "disable") == 0)
+       {
+               retval = CSC_POLICY_DISABLE;
+       }
+       
+    RegCloseKey(hkCSCPolicy);
+       return retval;
+}
+
 /* find a dir search structure by cookie value, and return it held.
  * Must be called with smb_globalLock held.
  */
@@ -1661,7 +1835,7 @@ unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
 
                sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
                                parm, parmCount, smbp->ncb_length);
-               osi_Log0(afsd_logp, s);
+               osi_Log0(smb_logp, s);
 #endif /* !DJGPP */
                osi_panic(s, __FILE__, __LINE__);
        }
@@ -1696,7 +1870,7 @@ unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
                sprintf(s, "Bad SMB param %d offset %d out of %d, "
                                "ncb len %d",
                                 parm, offset, parmCount, smbp->ncb_length);
-               osi_Log0(afsd_logp, s);
+               osi_Log0(smb_logp, s);
 #endif /* !DJGPP */
 
                osi_panic(s, __FILE__, __LINE__);
@@ -1853,7 +2027,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
 {
        NCB *ncbp;
        int extra;
-       long code;
+       long code = 0;
        unsigned char *tp;
        int localNCB = 0;
 #ifdef DJGPP
@@ -1894,7 +2068,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
 #endif /* !DJGPP */
         
        if (code != 0)
-               osi_Log1(afsd_logp, "SendPacket failure code %d", code);
+               osi_Log1(smb_logp, "SendPacket failure code %d", code);
 
        if (localNCB)
                FreeNCB(ncbp);
@@ -1905,6 +2079,7 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
        unsigned long NTStatus;
 
        /* map CM_ERROR_* errors to NT 32-bit status codes */
+    /* NT Status codes are listed in ntstatus.h not winerror.h */
        if (code == CM_ERROR_NOSUCHCELL) {
                NTStatus = 0xC000000FL; /* No such file */
        }
@@ -1999,12 +2174,24 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
        else if (code == CM_ERROR_BUFFERTOOSMALL) {
                NTStatus = 0xC0000023L; /* Buffer too small */
        }
+    else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+               NTStatus = 0xC0000035L; /* Object name collision */
+    }
+       else if (code == CM_ERROR_BADPASSWORD) {
+               NTStatus = 0xC000006DL; /* unknown username or bad password */
+       }
+       else if (code == CM_ERROR_BADLOGONTYPE) {
+               NTStatus = 0xC000015BL; /* logon type not granted */
+       }
+       else if (code == CM_ERROR_GSSCONTINUE) {
+               NTStatus = 0xC0000016L; /* more processing required */
+       }
        else {
                NTStatus = 0xC0982001L; /* SMB non-specific error */
        }
 
        *NTStatusp = NTStatus;
-       osi_Log2(afsd_logp, "SMB SEND code %x as NT %x", code, NTStatus);
+       osi_Log2(smb_logp, "SMB SEND code %x as NT %x", code, NTStatus);
 }
 
 void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
@@ -2150,6 +2337,11 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
                class = 1;
                error = 183;     /* Samba uses this */
        }
+       else if (code == CM_ERROR_BADPASSWORD || code == CM_ERROR_BADLOGONTYPE) {
+               /* we don't have a good way of reporting CM_ERROR_BADLOGONTYPE */
+               class = 2;
+               error = 2; /* bad password */
+       }
        else {
                class = 2;
                error = 1;
@@ -2157,7 +2349,7 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
 
        *scodep = error;
        *classp = class;
-       osi_Log3(afsd_logp, "SMB SEND code %x as SMB %d: %d", code, class, error);
+       osi_Log3(smb_logp, "SMB SEND code %x as SMB %d: %d", code, class, error);
 }
 
 long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
@@ -2191,7 +2383,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        long count, minCount, finalCount;
        unsigned short fd;
        smb_fid_t *fidp;
-       long code;
+       long code = 0;
        cm_user_t *userp = NULL;
     NCB *ncbp;
     int rc;
@@ -2211,7 +2403,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        offset.HighPart = 0;    /* too bad */
        offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
 
-       osi_Log3(afsd_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
+       osi_Log3(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
              fd, offset.LowPart, count);
 
        fidp = smb_FindFID(vcp, fd, 0);
@@ -2294,7 +2486,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        code = Netbios(ncbp, dos_ncb);
 #endif /* !DJGPP */
        if (code != 0)
-               osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
+               osi_Log1(smb_logp, "ReadRaw send failure code %d", code);
 
        if (rawBuf) {
                /* Give back raw buffer */
@@ -2325,26 +2517,36 @@ long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *namep;
+    char *datap;
        int coreProtoIndex;
        int v3ProtoIndex;
        int NTProtoIndex;
-       int protoIndex;                 /* index we're using */
+       int protoIndex;                         /* index we're using */
        int namex;
        int dbytes;
        int entryLength;
        int tcounter;
-       char protocol_array[10][1024]; /* protocol signature of the client */
+       char protocol_array[10][1024];  /* protocol signature of the client */
+    int caps;                       /* capabilities */
+    time_t unixTime;
+       long dosTime;
+       TIME_ZONE_INFORMATION tzi;
 
-        
-       osi_Log1(afsd_logp, "SMB receive negotiate; %d + 1 ongoing ops",
+    osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops",
                         ongoingOps - 1);
        if (!isGateway) {
                if (active_vcp) {
                        DWORD now = GetCurrentTime();
                        if (now - last_msg_time >= 30000
                                && now - last_msg_time <= 90000) {
-                               osi_Log1(afsd_logp,
+                               osi_Log1(smb_logp,
                                                 "Setting dead_vcp %x", active_vcp);
+                if (dead_vcp) {
+                    smb_ReleaseVC(dead_vcp);
+                    osi_Log1(smb_logp,
+                              "Previous dead_vcp %x", dead_vcp);
+                }
+                smb_HoldVC(active_vcp);
                                dead_vcp = active_vcp;
                                dead_vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
                        }
@@ -2360,8 +2562,8 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        v3ProtoIndex = -1;
        NTProtoIndex = -1;
        while(namex < dbytes) {
-               osi_Log1(afsd_logp, "Protocol %s",
-                                osi_LogSaveString(afsd_logp, namep+1));
+               osi_Log1(smb_logp, "Protocol %s",
+                                osi_LogSaveString(smb_logp, namep+1));
                strcpy(protocol_array[tcounter], namep+1);
 
                /* namep points at the first protocol, or really, a 0x02
@@ -2386,43 +2588,6 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         namep += entryLength;
         tcounter++;            /* which proto entry we're looking at */
        }
-#ifndef NOMOREFILESFIX
-       /* 
-        * NOTE: We can determine what OS (NT4.0, W2K, W9X, etc)
-        * the client is running by reading the protocol signature.
-        * ie. the order in which it sends us the protocol list.
-        *
-        * Special handling for Windows 2000 clients (defect 11765 )
-     * <asanka:11Jun03> Proto signature is the same for Win XP. </>
-        */
-       if (tcounter == 6) {
-               int i = 0;
-               smb_t *ip = (smb_t *) inp;
-               smb_t *op = (smb_t *) outp;
-
-               if ((strcmp("PC NETWORK PROGRAM 1.0", protocol_array[0]) == 0) &&
-                        (strcmp("LANMAN1.0", protocol_array[1]) == 0) &&
-                        (strcmp("Windows for Workgroups 3.1a", protocol_array[2]) == 0) &&
-                        (strcmp("LM1.2X002", protocol_array[3]) == 0) &&
-                        (strcmp("LANMAN2.1", protocol_array[4]) == 0) &&
-                        (strcmp("NT LM 0.12", protocol_array[5]) == 0)) {
-                       isWindows2000 = TRUE;
-                       osi_Log0(afsd_logp, "Looks like a Windows 2000 client");
-                       /* 
-                        * HACK: for now - just negotiate a lower protocol till we 
-                        * figure out which flag/flag2 or some other field 
-                        * (capabilities maybe?) to set in order for this to work
-                        * correctly with Windows 2000 clients (defect 11765)
-                        */
-                       NTProtoIndex = -1;
-                       /* Things to try (after looking at tcpdump output could be
-                        * setting flags and flags2 to 0x98 and 0xc853 like this
-                        * op->reb = 0x98; op->flg2 = 0xc853;
-                        * osi_Log2(afsd_logp, "Flags:0x%x Flags2:0x%x", ip->reb, ip->flg2);
-                        */
-               }       
-       }       
-#endif /* NOMOREFILESFIX */
 
        if (NTProtoIndex != -1) {
                protoIndex = NTProtoIndex;
@@ -2441,12 +2606,23 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        if (protoIndex == -1)
                return CM_ERROR_INVAL;
        else if (NTProtoIndex != -1) {
-               smb_SetSMBParm(outp, 0, protoIndex);
-        smb_SetSMBParmByte(outp, 1, 0);        /* share level security, no passwd encrypt */
+        smb_SetSMBParm(outp, 0, protoIndex);
+               if (smb_authType != SMB_AUTH_NONE) {
+                       smb_SetSMBParmByte(outp, 1,
+                               NEGOTIATE_SECURITY_USER_LEVEL |
+                               NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
+               } else {
+            smb_SetSMBParmByte(outp, 1, 0); /* share level auth with plaintext password. */
+               }
         smb_SetSMBParm(outp, 1, smb_maxMpxRequests);   /* max multiplexed requests */
         smb_SetSMBParm(outp, 2, smb_maxVCPerServer);   /* max VCs per consumer/server connection */
-        smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */
-               smb_SetSMBParmLong(outp, 5, 65536);     /* raw buffer size */
+        smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE);    /* xmit buffer size */
+               smb_SetSMBParmLong(outp, 5, SMB_MAXRAWSIZE);    /* raw buffer size */
+        /* The session key is not a well documented field however most clients
+         * will echo back the session key to the server.  Currently we are using
+         * the same value for all sessions.  We should generate a random value
+         * and store it into the vcp 
+         */
         smb_SetSMBParm(outp, 7, 1);    /* next 2: session key */
         smb_SetSMBParm(outp, 8, 1);
                /* 
@@ -2464,30 +2640,100 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 * and NT Find *
                 * and NT SMB's *
                 * and raw mode */
-               smb_SetSMBParmLong(outp, 9, 0x251);     
-               smb_SetSMBParmLong(outp, 11, 0);/* XXX server time: do we need? */
-               smb_SetSMBParmLong(outp, 13, 0);/* XXX server date: do we need? */
-               smb_SetSMBParm(outp, 15, 0);    /* XXX server tzone: do we need? */
-               smb_SetSMBParmByte(outp, 16, 0);/* Encryption key length */
-               smb_SetSMBDataLength(outp, 0);  /* perhaps should specify 8 bytes anyway */
+        caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
+                          NTNEGOTIATE_CAPABILITY_NTFIND |
+               NTNEGOTIATE_CAPABILITY_RAWMODE |
+                          NTNEGOTIATE_CAPABILITY_NTSMB;
+
+        if ( smb_authType == SMB_AUTH_EXTENDED )
+            caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY;
+
+        smb_SetSMBParmLong(outp, 9, caps);
+               time(&unixTime);
+               smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+               smb_SetSMBParmLong(outp, 11, LOWORD(dosTime));/* server time */
+               smb_SetSMBParmLong(outp, 13, HIWORD(dosTime));/* server date */
+
+               GetTimeZoneInformation(&tzi);
+               smb_SetSMBParm(outp, 15, (unsigned short) tzi.Bias);    /* server tzone */
+
+               if (smb_authType == SMB_AUTH_NTLM) {
+                       smb_SetSMBParmByte(outp, 16, MSV1_0_CHALLENGE_LENGTH);/* Encryption key length */
+                       smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength);
+                       /* paste in encryption key */
+                       datap = smb_GetSMBData(outp, NULL);
+                       memcpy(datap,vcp->encKey,MSV1_0_CHALLENGE_LENGTH);
+                       /* and the faux domain name */
+                       strcpy(datap + MSV1_0_CHALLENGE_LENGTH,smb_ServerDomainName);
+               } else if ( smb_authType == SMB_AUTH_EXTENDED ) {
+            void * secBlob;
+                       int secBlobLength;
+
+                       smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
+
+                       smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
+
+                       smb_SetSMBDataLength(outp, secBlobLength + sizeof(smb_ServerGUID));
+                       
+                       datap = smb_GetSMBData(outp, NULL);
+                       memcpy(datap, &smb_ServerGUID, sizeof(smb_ServerGUID));
+
+                       if (secBlob) {
+                               datap += sizeof(smb_ServerGUID);
+                               memcpy(datap, secBlob, secBlobLength);
+                               free(secBlob);
+                       }
+        } else {
+                       smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
+                       smb_SetSMBDataLength(outp, 0);   /* Perhaps we should specify 8 bytes anyway */
+               }
        }
        else if (v3ProtoIndex != -1) {
                smb_SetSMBParm(outp, 0, protoIndex);
-               smb_SetSMBParm(outp, 1, 0);     /* share level security, no passwd encrypt */
+
+        /* NOTE: Extended authentication cannot be negotiated with v3
+         * therefore we fail over to NTLM 
+         */
+        if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+                       smb_SetSMBParm(outp, 1,
+                               NEGOTIATE_SECURITY_USER_LEVEL |
+                               NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
+               } else {
+                       smb_SetSMBParm(outp, 1, 0); /* share level auth with clear password */
+               }
                smb_SetSMBParm(outp, 2, SMB_PACKETSIZE);
                smb_SetSMBParm(outp, 3, smb_maxMpxRequests);    /* max multiplexed requests */
                smb_SetSMBParm(outp, 4, smb_maxVCPerServer);    /* max VCs per consumer/server connection */
                smb_SetSMBParm(outp, 5, 0);     /* no support of block mode for read or write */
                smb_SetSMBParm(outp, 6, 1);     /* next 2: session key */
                smb_SetSMBParm(outp, 7, 1);
-               smb_SetSMBParm(outp, 8, 0);     /* XXX server time: do we need? */
-               smb_SetSMBParm(outp, 9, 0);     /* XXX server date: do we need? */
-               smb_SetSMBParm(outp, 10, 0);    /* XXX server tzone: do we need? */
-               smb_SetSMBParm(outp, 11, 0);    /* resvd */
-               smb_SetSMBParm(outp, 12, 0);    /* resvd */
-               smb_SetSMBDataLength(outp, 0);  /* perhaps should specify 8 bytes anyway */
+               time(&unixTime);
+               smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+               smb_SetSMBParm(outp, 8, LOWORD(dosTime));       /* server time */
+               smb_SetSMBParm(outp, 9, HIWORD(dosTime));       /* server date */
+
+               GetTimeZoneInformation(&tzi);
+               smb_SetSMBParm(outp, 10, (unsigned short) tzi.Bias);    /* server tzone */
+
+        /* NOTE: Extended authentication cannot be negotiated with v3
+         * therefore we fail over to NTLM 
+         */
+               if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+                       smb_SetSMBParm(outp, 11, MSV1_0_CHALLENGE_LENGTH);      /* encryption key length */
+            smb_SetSMBParm(outp, 12, 0);       /* resvd */
+                       smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength);       /* perhaps should specify 8 bytes anyway */
+                       datap = smb_GetSMBData(outp, NULL);
+                       /* paste in a new encryption key */
+                       memcpy(datap, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
+                       /* and the faux domain name */
+                       strcpy(datap + MSV1_0_CHALLENGE_LENGTH, smb_ServerDomainName);
+               } else {
+                       smb_SetSMBParm(outp, 11, 0); /* encryption key length */
+                       smb_SetSMBParm(outp, 12, 0); /* resvd */
+                       smb_SetSMBDataLength(outp, 0);
+               }
        }
-       else if (coreProtoIndex != -1) {
+       else if (coreProtoIndex != -1) {     /* not really supported anymore */
                smb_SetSMBParm(outp, 0, protoIndex);
                smb_SetSMBDataLength(outp, 0);
        }
@@ -2501,8 +2747,21 @@ void smb_Daemon(void *parmp)
        while(1) {
                count++;
                thrd_Sleep(10000);
-               if ((count % 360) == 0)         /* every hour */
-                       smb_CalculateNowTZ();
+               if ((count % 360) == 0) {       /* every hour */
+            struct tm myTime;
+                
+            /* Initialize smb_localZero */
+            myTime.tm_isdst = -1;              /* compute whether on DST or not */
+            myTime.tm_year = 70;
+            myTime.tm_mon = 0;
+            myTime.tm_mday = 1;
+            myTime.tm_hour = 0;
+            myTime.tm_min = 0;
+            myTime.tm_sec = 0;
+            smb_localZero = mktime(&myTime);
+
+            smb_CalculateNowTZ();
+        }
                /* XXX GC dir search entries */
        }
 }
@@ -2514,7 +2773,7 @@ void smb_WaitingLocksDaemon()
        smb_vc_t *vcp;
        smb_packet_t *inp, *outp;
        NCB *ncbp;
-       long code;
+       long code = 0;
 
        while(1) {
                lock_ObtainWrite(&smb_globalLock);
@@ -2577,7 +2836,7 @@ void smb_WaitingLocksDaemon()
 
 long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       osi_Log0(afsd_logp, "SMB receive get disk attributes");
+       osi_Log0(smb_logp, "SMB receive get disk attributes");
 
        smb_SetSMBParm(outp, 0, 32000);
        smb_SetSMBParm(outp, 1, 64);
@@ -2591,6 +2850,7 @@ long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp)
 {
        smb_tid_t *tidp;
+    smb_user_t *uidp;
        unsigned short newTid;
        char shareName[256];
        char *sharePath;
@@ -2600,7 +2860,7 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
        char *passwordp;
        cm_user_t *userp;
 
-       osi_Log0(afsd_logp, "SMB receive tree connect");
+       osi_Log0(smb_logp, "SMB receive tree connect");
 
        /* parse input parameters */
        tp = smb_GetSMBData(inp, NULL);
@@ -2618,7 +2878,10 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
        lock_ReleaseMutex(&vcp->mx);
         
        tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
-       shareFound = smb_FindShare(vcp, inp, shareName, &sharePath);
+    uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+       shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
+    if (uidp)
+        smb_ReleaseUID(uidp);
        if (!shareFound) {
                smb_ReleaseTID(tidp);
                return CM_ERROR_BADSHARENAME;
@@ -2633,7 +2896,7 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
        smb_SetSMBParm(rsp, 1, newTid);
        smb_SetSMBDataLength(rsp, 0);
 
-       osi_Log1(afsd_logp, "SMB tree connect created ID %d", newTid);
+       osi_Log1(smb_logp, "SMB tree connect created ID %d", newTid);
        return 0;
 }
 
@@ -2772,7 +3035,7 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
        unsigned char initStatBlock[21];
        int statLen;
         
-       osi_Log0(afsd_logp, "SMB receive search volume");
+       osi_Log0(smb_logp, "SMB receive search volume");
 
        /* pull pathname and stat block out of request */
        tp = smb_GetSMBData(inp, NULL);
@@ -2834,7 +3097,7 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
        cm_user_t *userp, cm_req_t *reqp)
 {
-       long code;
+       long code = 0;
        cm_scache_t *scp;
        char *dptr;
        long dosTime;
@@ -2900,7 +3163,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        int attribute;
        long nextCookie;
        char *tp;
-       long code;
+       long code = 0;
        char *pathp;
        cm_dirEntry_t *dep;
        int maxCount;
@@ -2973,8 +3236,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                if (attribute & 0x8)
                        return smb_ReceiveCoreSearchVolume(vcp, inp, outp);
 
-               osi_Log2(afsd_logp, "SMB receive search dir count %d [%s]",
-                                maxCount, osi_LogSaveString(afsd_logp, pathp));
+               osi_Log2(smb_logp, "SMB receive search dir count %d [%s]",
+                                maxCount, osi_LogSaveString(smb_logp, pathp));
 
                if (*pathp == 0) {      /* null pathp, treat as root dir */
                        if (!(attribute & SMB_ATTR_DIRECTORY))  /* exclude dirs */
@@ -3016,7 +3279,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                starPattern = 1;
        }
 
-       osi_Log3(afsd_logp, "SMB dir search cookie 0x%x, connection %d, attr 0x%x",
+       osi_Log3(smb_logp, "SMB dir search cookie 0x%x, connection %d, attr 0x%x",
                         nextCookie, dsp->cookie, attribute);
 
        userp = smb_GetUser(vcp, inp);
@@ -3256,7 +3519,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                                fid.vnode = ntohl(dep->fid.vnode);
                                fid.unique = ntohl(dep->fid.unique);
                                fileType = cm_FindFileType(&fid);
-                               osi_Log2(afsd_logp, "smb_ReceiveCoreSearchDir: file %s "
+                               osi_Log2(smb_logp, "smb_ReceiveCoreSearchDir: file %s "
                                                  "has filetype %d", dep->name,
                                                  fileType);
                                if (fileType == CM_SCACHETYPE_DIRECTORY)
@@ -3345,7 +3608,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        if (code == 0 && dataLength < 21 && returnedNames == 0)
                code = CM_ERROR_NOFILES;
 
-       osi_Log2(afsd_logp, "SMB search dir done, %d names, code %d",
+       osi_Log2(smb_logp, "SMB search dir done, %d names, code %d",
                 returnedNames, code);
 
        if (code != 0) {
@@ -3383,7 +3646,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-       long code;
+       long code = 0;
        cm_scache_t *rootScp;
        cm_scache_t *newScp;
        cm_user_t *userp;
@@ -3396,8 +3659,8 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
        pathp = smb_GetSMBData(inp, NULL);
        pathp = smb_ParseASCIIBlock(pathp, NULL);
-       osi_Log1(afsd_logp, "SMB receive check path %s",
-                         osi_LogSaveString(afsd_logp, pathp));
+       osi_Log1(smb_logp, "SMB receive check path %s",
+                         osi_LogSaveString(smb_logp, pathp));
 
        if (!pathp) {
                return CM_ERROR_BADFD;
@@ -3445,7 +3708,7 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-       long code;
+       long code = 0;
        cm_scache_t *rootScp;
        unsigned short attribute;
        cm_attr_t attr;
@@ -3469,7 +3732,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
                return CM_ERROR_BADSMB;
        }
         
-       osi_Log2(afsd_logp, "SMB receive setfile attributes time %d, attr 0x%x",
+       osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
                         dosTime, attribute);
 
        rootScp = cm_rootSCachep;
@@ -3542,7 +3805,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-       long code;
+       long code = 0;
        cm_scache_t *rootScp;
        cm_scache_t *newScp, *dscp;
        long dosTime;
@@ -3566,8 +3829,8 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
        if (*pathp == 0)                /* null path */
                pathp = "\\";
 
-       osi_Log1(afsd_logp, "SMB receive getfile attributes path %s",
-                        osi_LogSaveString(afsd_logp, pathp));
+       osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
+                        osi_LogSaveString(smb_logp, pathp));
 
        rootScp = cm_rootSCachep;
         
@@ -3679,7 +3942,7 @@ long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_
 {
        smb_tid_t *tidp;
         
-       osi_Log0(afsd_logp, "SMB receive tree disconnect");
+       osi_Log0(smb_logp, "SMB receive tree disconnect");
 
        /* find the tree and free it */
        tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
@@ -3700,7 +3963,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        char *lastNamep;
     int share;
     int attribute;
-       long code;
+       long code = 0;
     cm_user_t *userp;
     cm_scache_t *scp;
     long dosTime;
@@ -3714,7 +3977,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     pathp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(pathp, NULL);
        
-    osi_Log1(afsd_logp, "SMB receive open file [%s]", osi_LogSaveString(afsd_logp, pathp));
+    osi_Log1(smb_logp, "SMB receive open file [%s]", osi_LogSaveString(smb_logp, pathp));
 
 #ifdef DEBUG_VERBOSE
     {
@@ -3822,13 +4085,13 @@ typedef struct smb_unlinkRock {
        cm_req_t *reqp;
        smb_vc_t *vcp;
        char *maskp;            /* pointer to the star pattern */
-       int hasTilde;
+       int flags;
        int any;
 } smb_unlinkRock_t;
 
 int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
-       long code;
+       long code = 0;
        smb_unlinkRock_t *rockp;
        int caseFold;
        int match;
@@ -3837,19 +4100,19 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
         
        rockp = vrockp;
 
-       if (rockp->vcp->flags & SMB_VCFLAG_USEV3)
-               caseFold = CM_FLAG_CASEFOLD;
-       else 
-               caseFold = CM_FLAG_CASEFOLD | CM_FLAG_8DOT3;
+    caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
+    if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
+        caseFold |= CM_FLAG_8DOT3;
 
        matchName = dep->name;
        match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                matchName = shortName;
-               match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
+        /* 8.3 matches are always case insensitive */
+        match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
        }
        if (match) {
                osi_Log1(smb_logp, "Unlinking %s",
@@ -3859,8 +4122,12 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
                        smb_NotifyChange(FILE_ACTION_REMOVED,
                                                         FILE_NOTIFY_CHANGE_FILE_NAME,
                                                         dscp, dep->name, NULL, TRUE);
-               if (code == 0)
+               if (code == 0) {
                        rockp->any = 1;
+            /* If we made a case sensitive exact match, we might as well quit now. */
+            if(!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
+                code = CM_ERROR_STOPNOW;
+        }
        }
        else code = 0;
 
@@ -3870,7 +4137,7 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
 long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        int attribute;
-       long code;
+       long code = 0;
        char *pathp;
        char *tp;
        cm_space_t *spacep;
@@ -3917,7 +4184,7 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        rock.any = 0;
        rock.maskp = smb_FindMask(pathp);
-       rock.hasTilde = ((strchr(rock.maskp, '~') != NULL) ? 1 : 0);
+       rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
         
        thyper.LowPart = 0;
        thyper.HighPart = 0;
@@ -3925,7 +4192,25 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        rock.reqp = &req;
        rock.dscp = dscp;
        rock.vcp = vcp;
-       code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+
+    /* Now, if we aren't dealing with a wildcard match, we first try an exact 
+     * match.  If that fails, we do a case insensitve match. 
+     */
+    if (!(rock.flags & SMB_MASKFLAG_TILDE) &&
+        !smb_IsStarMask(rock.maskp)) {
+        code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+        if(!rock.any) {
+            thyper.LowPart = 0;
+            thyper.HighPart = 0;
+            rock.flags |= SMB_MASKFLAG_CASEFOLD;
+        }
+    }
+    if (!rock.any)
+        code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+    
+    if (code == CM_ERROR_STOPNOW) 
+        code = 0;
 
        cm_ReleaseUser(userp);
         
@@ -3943,28 +4228,27 @@ typedef struct smb_renameRock {
        cm_req_t *reqp;         /* request struct */
        smb_vc_t *vcp;          /* virtual circuit */
        char *maskp;            /* pointer to star pattern of old file name */
-       int hasTilde;           /* star pattern might be shortname? */
+       int flags;                  /* tilde, casefold, etc */
        char *newNamep;         /* ptr to the new file's name */
 } smb_renameRock_t;
 
 int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
-       long code;
+       long code = 0;
        smb_renameRock_t *rockp;
        int caseFold;
        int match;
        char shortName[13];
         
-       rockp = vrockp;
+       rockp = (smb_renameRock_t *) vrockp;
 
-       if (rockp->vcp->flags & SMB_VCFLAG_USEV3)
-               caseFold = CM_FLAG_CASEFOLD;
-       else 
-               caseFold = CM_FLAG_CASEFOLD | CM_FLAG_8DOT3;
+    caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
+    if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
+        caseFold |= CM_FLAG_8DOT3;
 
        match = smb_V3MatchMask(dep->name, rockp->maskp, caseFold);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
@@ -3986,15 +4270,16 @@ int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
 
 long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       long code;
+       long code = 0;
        char *oldPathp;
        char *newPathp;
        char *tp;
-       cm_space_t *spacep;
+       cm_space_t *spacep = NULL;
        smb_renameRock_t rock;
-       cm_scache_t *oldDscp;
-       cm_scache_t *newDscp;
-       cm_scache_t *tmpscp;
+       cm_scache_t *oldDscp = NULL;
+       cm_scache_t *newDscp = NULL;
+       cm_scache_t *tmpscp= NULL;
+       cm_scache_t *tmpscp2 = NULL;
        char *oldLastNamep;
        char *newLastNamep;
        osi_hyper_t thyper;
@@ -4010,9 +4295,9 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        oldPathp = smb_ParseASCIIBlock(tp, &tp);
        newPathp = smb_ParseASCIIBlock(tp, &tp);
 
-       osi_Log2(afsd_logp, "smb rename %s to %s",
-                        osi_LogSaveString(afsd_logp, oldPathp),
-                        osi_LogSaveString(afsd_logp, newPathp));
+       osi_Log2(smb_logp, "smb rename [%s] to [%s]",
+                        osi_LogSaveString(smb_logp, oldPathp),
+                        osi_LogSaveString(smb_logp, newPathp));
 
        spacep = inp->spacep;
        smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
@@ -4066,6 +4351,8 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                newLastNamep = newPathp;
        else 
                newLastNamep++;
+
+    /* TODO: The old name could be a wildcard.  The new name must not be */
        
        /* do the vnode call */
        rock.odscp = oldDscp;
@@ -4074,16 +4361,44 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        rock.reqp = &req;
        rock.vcp = vcp;
        rock.maskp = oldLastNamep;
-       rock.hasTilde = ((strchr(oldLastNamep, '~') != NULL) ? 1 : 0);
+       rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
        rock.newNamep = newLastNamep;
 
     /* Check if the file already exists; if so return error */
        code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp);
-       if((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) {
-           cm_ReleaseSCache(tmpscp);
-           return CM_ERROR_EXISTS; /* file exist, do not rename, also 
-                                        * fixes move
-                                                                */
+       if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) {
+        osi_Log2(afsd_logp, "  lookup returns %ld for [%s]", code,
+                 osi_LogSaveString(afsd_logp, newLastNamep));
+        /* Check if the old and the new names differ only in case. If so return
+         * success, else return CM_ERROR_EXISTS 
+         */
+        if (!code && oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
+
+            /* This would be a success only if the old file is *as same as* the new file */
+            code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH, userp, &req, &tmpscp2);
+            if (!code) {
+                if (tmpscp == tmpscp2) 
+                    code = 0;
+                else 
+                    code = CM_ERROR_EXISTS;
+                cm_ReleaseSCache(tmpscp2);
+                               tmpscp2 = NULL;
+            } else {
+                code = CM_ERROR_NOSUCHFILE;
+            }
+        } else {
+            /* file exist, do not rename, also fixes move */
+            osi_Log0(afsd_logp, "Can't rename.  Target already exists");
+            code = CM_ERROR_EXISTS;
+        }
+
+               if(tmpscp != NULL)
+            cm_ReleaseSCache(tmpscp);
+        cm_ReleaseSCache(newDscp);
+        cm_ReleaseSCache(oldDscp);
+        cm_ReleaseUser(userp);
+           return code; 
        }
 
     /* Now search the directory for the pattern, and do the appropriate rename when found */
@@ -4119,11 +4434,11 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                                                         NULL, TRUE);
        }
 
-       cm_ReleaseUser(userp);
-        
+    if(tmpscp != NULL) 
+        cm_ReleaseSCache(tmpscp);
+    cm_ReleaseUser(userp);
        cm_ReleaseSCache(oldDscp);
        cm_ReleaseSCache(newDscp);
-
        return code;
 }
 
@@ -4132,24 +4447,27 @@ typedef struct smb_rmdirRock {
        cm_user_t *userp;
        cm_req_t *reqp;
        char *maskp;            /* pointer to the star pattern */
-       int hasTilde;
+       int flags;
        int any;
 } smb_rmdirRock_t;
 
 int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper_t *offp)
 {
-       long code;
+       long code = 0;
        smb_rmdirRock_t *rockp;
        int match;
        char shortName[13];
        char *matchName;
         
-       rockp = vrockp;
+       rockp = (smb_rmdirRock_t *) vrockp;
 
        matchName = dep->name;
-       match = (cm_stricmp(matchName, rockp->maskp) == 0);
+    if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
+        match = (cm_stricmp(matchName, rockp->maskp) == 0);
+    else
+        match = (strcmp(matchName, rockp->maskp) == 0);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                matchName = shortName;
@@ -4173,7 +4491,7 @@ int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper
 
 long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       long code;
+       long code = 0;
        char *pathp;
        char *tp;
        cm_space_t *spacep;
@@ -4215,14 +4533,21 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        
        rock.any = 0;
        rock.maskp = lastNamep;
-       rock.hasTilde = ((strchr(rock.maskp, '~') != NULL) ? 1 : 0);
+       rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
 
        thyper.LowPart = 0;
        thyper.HighPart = 0;
        rock.userp = userp;
        rock.reqp = &req;
        rock.dscp = dscp;
-       code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    /* First do a case sensitive match, and if that fails, do a case insensitive match */
+    code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    if (code == 0 && !rock.any) {
+        thyper.LowPart = 0;
+        thyper.HighPart = 0;
+        rock.flags |= SMB_MASKFLAG_CASEFOLD;
+        code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    }
 
        cm_ReleaseUser(userp);
         
@@ -4238,14 +4563,14 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        unsigned short fid;
     smb_fid_t *fidp;
     cm_user_t *userp;
-    long code;
+    long code = 0;
     cm_req_t req;
 
        cm_InitReq(&req);
 
        fid = smb_GetSMBParm(inp, 0);
         
-       osi_Log1(afsd_logp, "SMB flush fid %d", fid);
+       osi_Log1(smb_logp, "SMB flush fid %d", fid);
 
        fid = smb_ChainFID(fid, inp);
     fidp = smb_FindFID(vcp, fid, 0);
@@ -4283,17 +4608,17 @@ int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
        char shortName[13];
        struct smb_FullNameRock *vrockp;
 
-       vrockp = rockp;
+       vrockp = (struct smb_FullNameRock *)rockp;
 
        if (!cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
 
-               if (strcmp(shortName, vrockp->name) == 0) {
+               if (cm_stricmp(shortName, vrockp->name) == 0) {
                        vrockp->fullName = strdup(dep->name);
                        return CM_ERROR_STOPNOW;
                }
        }
-       if (stricmp(dep->name, vrockp->name) == 0
+       if (cm_stricmp(dep->name, vrockp->name) == 0
            && ntohl(dep->fid.vnode) == vrockp->vnode->fid.vnode
            && ntohl(dep->fid.unique) == vrockp->vnode->fid.unique) {
                vrockp->fullName = strdup(dep->name);
@@ -4306,7 +4631,7 @@ void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp,
        char **newPathp, cm_user_t *userp, cm_req_t *reqp)
 {
        struct smb_FullNameRock rock;
-       long code;
+       long code = 0;
 
        rock.name = pathp;
        rock.vnode = scp;
@@ -4325,7 +4650,7 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_fid_t *fidp;
     cm_user_t *userp;
        long dosTime;
-    long code;
+    long code = 0;
        cm_req_t req;
 
        cm_InitReq(&req);
@@ -4333,7 +4658,7 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        fid = smb_GetSMBParm(inp, 0);
        dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
         
-       osi_Log1(afsd_logp, "SMB close fid %d", fid);
+       osi_Log1(smb_logp, "SMB close fid %d", fid);
 
        fid = smb_ChainFID(fid, inp);
     fidp = smb_FindFID(vcp, fid, 0);
@@ -4418,7 +4743,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 #endif /* !DJGPP */
 {
        osi_hyper_t offset;
-       long code;
+       long code = 0;
        cm_scache_t *scp;
        cm_buf_t *bufferp;
        osi_hyper_t fileLength;
@@ -4572,7 +4897,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 #endif /* !DJGPP */
 {
        osi_hyper_t offset;
-       long code;
+       long code = 0;
        long written = 0;
        cm_scache_t *scp;
        osi_hyper_t fileLength; /* file's length at start of write */
@@ -4755,9 +5080,10 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
                /* and record the last writer */
                if (bufferp->userp != userp) {
-                       if (bufferp->userp) cm_ReleaseUser(bufferp->userp);
-                       bufferp->userp = userp;
                        cm_HoldUser(userp);
+                       if (bufferp->userp) 
+                cm_ReleaseUser(bufferp->userp);
+                       bufferp->userp = userp;
                }
                 
                /* adjust counters, pointers, etc. */
@@ -4801,7 +5127,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     long count, written = 0;
     unsigned short fd;
     smb_fid_t *fidp;
-    long code;
+    long code = 0;
     cm_user_t *userp;
     cm_attr_t truncAttr;       /* attribute struct used for truncating file */
     char *op;
@@ -4815,7 +5141,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     op = smb_GetSMBData(inp, NULL);
        op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
 
-    osi_Log3(afsd_logp, "smb_ReceiveCoreWrite fd %d, off 0x%x, size 0x%x",
+    osi_Log3(smb_logp, "smb_ReceiveCoreWrite fd %d, off 0x%x, size 0x%x",
              fd, offset.LowPart, count);
         
        fd = smb_ChainFID(fd, inp);
@@ -4895,12 +5221,12 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        dos_ptr rawBuf;
 #endif /* !DJGPP */
        long written = 0;
-       long code;
+       long code = 0;
 
        fd = smb_GetSMBParm(inp, 0);
        fidp = smb_FindFID(vcp, fd, 0);
 
-       osi_Log2(afsd_logp, "Completing Raw Write offset %x count %x",
+       osi_Log2(smb_logp, "Completing Raw Write offset %x count %x",
                 rwcp->offset.LowPart, rwcp->count);
 
        userp = smb_GetUser(vcp, inp);
@@ -4961,7 +5287,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        long totalCount;
     unsigned short fd;
     smb_fid_t *fidp;
-    long code;
+    long code = 0;
     cm_user_t *userp;
     char *op;
        unsigned short writeMode;
@@ -4981,7 +5307,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        op = (char *) inp->data;
        op += smb_GetSMBParm(inp, 11);
 
-    osi_Log4(afsd_logp,
+    osi_Log4(smb_logp,
              "smb_ReceiveCoreWriteRaw fd %d, off 0x%x, size 0x%x, WriteMode 0x%x",
              fd, offset.LowPart, count, writeMode);
         
@@ -5077,7 +5403,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     long count, finalCount;
     unsigned short fd;
     smb_fid_t *fidp;
-    long code;
+    long code = 0;
     cm_user_t *userp;
     char *op;
         
@@ -5086,7 +5412,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     offset.HighPart = 0;       /* too bad */
     offset.LowPart = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
         
-    osi_Log3(afsd_logp, "smb_ReceiveCoreRead fd %d, off 0x%x, size 0x%x",
+    osi_Log3(smb_logp, "smb_ReceiveCoreRead fd %d, off 0x%x, size 0x%x",
              fd, offset.LowPart, count);
         
        fd = smb_ChainFID(fd, inp);
@@ -5142,7 +5468,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-    long code;
+    long code = 0;
        cm_space_t *spacep;
     char *tp;
     cm_user_t *userp;
@@ -5193,7 +5519,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         lastNamep = pathp;
     else 
         lastNamep++;
-    code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
+    code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp);
     if (scp) cm_ReleaseSCache(scp);
     if (code != CM_ERROR_NOSUCHFILE) {
         if (code == 0) code = CM_ERROR_EXISTS;
@@ -5243,7 +5569,7 @@ BOOL smb_IsLegalFilename(char *filename)
 long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-    long code;
+    long code = 0;
        cm_space_t *spacep;
     char *tp;
     int excl;
@@ -5300,7 +5626,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (!smb_IsLegalFilename(lastNamep))
         return CM_ERROR_BADNTFILENAME;
 
-    osi_Log1(afsd_logp, "SMB receive create [%s]", osi_LogSaveString( afsd_logp, pathp ));
+    osi_Log1(smb_logp, "SMB receive create [%s]", osi_LogSaveString( smb_logp, pathp ));
 #ifdef DEBUG_VERBOSE
     {
         char *hexp;
@@ -5310,7 +5636,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     }
 #endif    
 
-    code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
+    code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp);
     if (code && code != CM_ERROR_NOSUCHFILE) {
                cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
@@ -5402,7 +5728,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
 long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    long code;
+    long code = 0;
     long offset;
     int whence;
     unsigned short fd;
@@ -5458,10 +5784,9 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        NCB *ncbp, raw_write_cont_t *rwcp)
 {
-    static showErrors = 0;
     smb_dispatch_t *dp;
     smb_t *smbp;
-    unsigned long code;
+    unsigned long code = 0;
     unsigned char *outWctp;
     int nparms;                        /* # of bytes of parameters */
     char tbuffer[200];
@@ -5532,7 +5857,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
         /* process each request in the packet; inCom, wctp and inCount
          * are already set up.
          */
-               osi_Log2(afsd_logp, "SMB received op 0x%x lsn %d", inp->inCom,
+               osi_Log2(smb_logp, "SMB received op 0x%x lsn %d", inp->inCom,
                  ncbp->ncb_lsn);
 
                /* now do the dispatch */
@@ -5566,10 +5891,10 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                                                 rwcp);
                        else {
                                        osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
-                                       osi_Log4(afsd_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn);
+                                       osi_Log4(smb_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn);
                                        code = (*(dp->procp)) (vcp, inp, outp);
                                        osi_LogEvent("AFS Dispatch return",NULL,"Code[%d]",(code==0)?0:code-CM_ERROR_BASE);
-                                       osi_Log1(afsd_logp,"Dispatch return  code[%d]",(code==0)?0:code-CM_ERROR_BASE);
+                                       osi_Log1(smb_logp,"Dispatch return  code[%d]",(code==0)?0:code-CM_ERROR_BASE);
             }
 
                        if (oldGen != sessionGen) {
@@ -5586,7 +5911,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                             1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp);
                                DeregisterEventSource(h);
 #else /* DJGPP */
-                               osi_Log1(afsd_logp, "Pkt straddled session startup, "
+                               osi_Log1(smb_logp, "Pkt straddled session startup, "
                          "ncb length %d", ncbp->ncb_length);
 #endif /* !DJGPP */
                        }
@@ -5601,7 +5926,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                        if (showErrors) {
                                sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom);
                 code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again",
-                                     MB_OKCANCEL);
+                                     MB_OKCANCEL|MB_SERVICE_NOTIFICATION);
                 if (code == IDCANCEL) showErrors = 0;
                        }
 #endif /* DJGPP */
@@ -5630,7 +5955,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
             smb_LogPacket(inp);
 #endif /* NOTSERVICE */
 #else /* DJGPP */
-            osi_Log1(afsd_logp, "Invalid SMB message, length %d",
+            osi_Log1(smb_logp, "Invalid SMB message, length %d",
                      ncbp->ncb_length);
 #endif /* !DJGPP */
 
@@ -5652,9 +5977,11 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                                outWctp = outp->wctp;
                                smbp = (smb_t *) &outp->data;
                                if (code != CM_ERROR_PARTIALWRITE
-                                   && code != CM_ERROR_BUFFERTOOSMALL) {
+                                   && code != CM_ERROR_BUFFERTOOSMALL 
+                    && code != CM_ERROR_GSSCONTINUE) {
                                        /* nuke wct and bcc.  For a partial
-                                        * write, assume they're OK.
+                                        * write or an in-process authentication handshake, 
+                     * assume they're OK.
                                         */
                                        *outWctp++ = 0;
                                        *outWctp++ = 0;
@@ -5746,11 +6073,19 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        thrd_Decrement(&ongoingOps);
 
        if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+        if (active_vcp) {
+            smb_ReleaseVC(active_vcp);
+            osi_Log2(smb_logp,
+                      "Replacing active_vcp %x with %x", active_vcp, vcp);
+        }
+        smb_HoldVC(vcp);
                active_vcp = vcp;
                last_msg_time = GetCurrentTime();
        }
-       else if (active_vcp == vcp)
+       else if (active_vcp == vcp) {
+        smb_ReleaseVC(active_vcp);
                active_vcp = NULL;
+    }
 
     return;
 }
@@ -5949,7 +6284,7 @@ void smb_Server(VOID *parmp)
     DWORD code, rcode;
     int idx_NCB, idx_session;
        UCHAR rc;
-       smb_vc_t *vcp;
+       smb_vc_t *vcp = NULL;
        smb_t *smbp;
 #ifdef DJGPP
     dos_ptr dos_ncb;
@@ -5967,7 +6302,7 @@ void smb_Server(VOID *parmp)
                        if (tod > EXPIREDATE) {
                                (*smb_MBfunc)(NULL, "AFS demo expiration",
                                           "afsd dispatcher",
-                                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
+                                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
                                trhd_Exit(1);
                        }
                }
@@ -6020,7 +6355,7 @@ void smb_Server(VOID *parmp)
                rc = ncbp->ncb_retcode;
 
                if (rc != NRC_PENDING && rc != NRC_GOODRET)
-                       osi_Log1(afsd_logp, "NCBRECV failure code %d", rc);
+                       osi_Log1(smb_logp, "NCBRECV failure code %d", rc);
 
                switch (rc) {
                        case NRC_GOODRET: break;
@@ -6039,8 +6374,11 @@ void smb_Server(VOID *parmp)
                     afsi_log("session [ %d ] closed", idx_session);
                 }
                                dead_sessions[idx_session] = TRUE;
+                if (vcp)
+                    smb_ReleaseVC(vcp);
                                vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
-                               /* Should also release vcp.  Also, would do
+                               /* Should also release vcp.  [done] 2004-05-11 jaltman
+                 * Also, should do
                                 * sanity check that all TID's are gone. 
                  *
                  * TODO: check if we could use LSNs[idx_session] instead, 
@@ -6048,13 +6386,14 @@ void smb_Server(VOID *parmp)
                  */
                 if (vcp) {
                     if (dead_vcp)
-                        osi_Log1(afsd_logp,
+                        osi_Log1(smb_logp,
                                   "dead_vcp already set, %x",
                                   dead_vcp);
                     if (!dead_vcp && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
-                        osi_Log2(afsd_logp,
+                        osi_Log2(smb_logp,
                                   "setting dead_vcp %x, user struct %x",
                                   vcp, vcp->usersp);
+                        smb_HoldVC(vcp);
                         dead_vcp = vcp;
                         vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
                     }
@@ -6111,7 +6450,7 @@ void smb_Server(VOID *parmp)
                        default:
                                /* A weird error code.  Log it, sleep, and
                                 * continue. */
-                               if (vcp->errorCount++ > 3) {
+                               if (vcp && vcp->errorCount++ > 3) {
                     afsi_log("session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
                                        dead_sessions[idx_session] = TRUE;
                 }
@@ -6128,6 +6467,8 @@ void smb_Server(VOID *parmp)
                if (smb_concurrentCalls > smb_maxObsConcurrentCalls)
                        smb_maxObsConcurrentCalls = smb_concurrentCalls;
 
+        if (vcp)
+            smb_ReleaseVC(vcp);
                vcp = smb_FindVC(ncbp->ncb_lsn, 0, ncbp->ncb_lana_num);
         /*
                * If at this point vcp is NULL (implies that packet was invalid)
@@ -6165,7 +6506,7 @@ void smb_Server(VOID *parmp)
                        }
 
                        /* Also log in the trace log. */
-                       osi_Log4(afsd_logp, "Server: BAD VCP!"
+                       osi_Log4(smb_logp, "Server: BAD VCP!"
                                "LSNs[idx_session]=[%d],"
                                "lanas[idx_session]=[%d],"
                                "ncbp->ncb_lsn=[%d],"
@@ -6251,6 +6592,8 @@ void smb_Server(VOID *parmp)
 doneWithNCB:
                thrd_SetEvent(NCBavails[idx_NCB]);
        }
+    if (vcp)
+        smb_ReleaseVC(vcp);
 }
 
 /*
@@ -6322,7 +6665,7 @@ void InitNCBslot(int idx)
 void smb_Listener(void *parmp)
 {
        NCB *ncbp;
-    long code;
+    long code = 0;
     long len;
        long i, j;
     smb_vc_t *vcp;
@@ -6348,11 +6691,6 @@ void smb_Listener(void *parmp)
        while (1) {
                memset(ncbp, 0, sizeof(NCB));
                flags = 0;
-#ifdef DJGPP
-        /* terminate if shutdown flag is set */
-        if (smbShutdownFlag == 1)
-            thrd_Exit(1);
-#endif /* DJGPP */
 
 #ifndef NOEXPIRE
                /* check for demo expiration */
@@ -6361,8 +6699,12 @@ void smb_Listener(void *parmp)
                        if (tod > EXPIREDATE) {
                                (*smb_MBfunc)(NULL, "AFS demo expiration",
                                "afsd listener",
-                               MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
-                               ExitThread(1);
+                               MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
+#ifndef DJGPP
+                ExitThread(1);
+#else
+                thrd_Exit(1);
+#endif
                        }
                }
 #endif /* !NOEXPIRE */
@@ -6385,21 +6727,48 @@ void smb_Listener(void *parmp)
         code = Netbios(ncbp);
 #else /* DJGPP */
         code = Netbios(ncbp, dos_ncb);
+#endif
 
         if (code != 0)
         {
+#ifndef DJGPP
+            char tbuffer[256];
+#endif
+
+            /* terminate silently if shutdown flag is set */
+               if (smbShutdownFlag == 1) {
+#ifndef DJGPP
+                           ExitThread(1);
+#else
+                               thrd_Exit(1);
+#endif
+                       }
+
+            osi_Log2(smb_logp, 
+                     "NCBLISTEN lana=%d failed with code %d",
+                     ncbp->ncb_lana_num, code);
+            osi_Log0(smb_logp, 
+                     "Client exiting due to network failure. Please restart client.\n");
+
+#ifndef DJGPP
+            sprintf(tbuffer, 
+                     "Client exiting due to network failure.  Please restart client.\n"
+                     "NCBLISTEN lana=%d failed with code %d",
+                     ncbp->ncb_lana_num, code);
+                       if (showErrors)
+                code = (*smb_MBfunc)(NULL, tbuffer, "AFS Client Service: Fatal Error",
+                                     MB_OK|MB_SERVICE_NOTIFICATION);
+            osi_assert(tbuffer);
+            ExitThread(1);
+#else
             fprintf(stderr, "NCBLISTEN lana=%d failed with code %d\n",
                      ncbp->ncb_lana_num, code);
-            osi_Log2(0, "NCBLISTEN lana=%d failed with code %d",
-                      ncbp->ncb_lana_num, code);
             fprintf(stderr, "\nClient exiting due to network failure "
                      "(possibly due to power-saving mode)\n");
             fprintf(stderr, "Please restart client.\n");
-            afs_exit(AFS_EXITCODE_NETWORK_FAILURE);
-        }
+                       afs_exit(AFS_EXITCODE_NETWORK_FAILURE);
 #endif /* !DJGPP */
-
-               osi_assert(code == 0);
+        }
 
                /* check for remote conns */
                /* first get remote name and insert null terminator */
@@ -6416,7 +6785,7 @@ void smb_Listener(void *parmp)
                        if (strncmp(rname, cname, NCBNAMSZ) != 0)
                                flags |= SMB_VCFLAG_REMOTECONN;
 
-               osi_Log1(afsd_logp, "New session lsn %d", ncbp->ncb_lsn);
+               osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
                /* lock */
                lock_ObtainMutex(&smb_ListenerLock);
 
@@ -6446,7 +6815,7 @@ void smb_Listener(void *parmp)
                        DeregisterEventSource(h);
 #else /* DJGPP */
             afsi_log("NCBLISTEN completed, call from %s",rname);
-            osi_Log1(afsd_logp, "SMB session startup, %d ongoing ops",
+            osi_Log1(smb_logp, "SMB session startup, %d ongoing ops",
                      ongoingOps);
             time(&now);
             fprintf(stderr, "%s: New session %d starting from host %s\n",
@@ -6476,7 +6845,8 @@ void smb_Listener(void *parmp)
          * we run out.
          */
 
-        osi_assert(i < Sessionmax && numNCBs < NCBmax - 1);
+        osi_assert(i < Sessionmax - 1);
+        osi_assert(numNCBs < NCBmax - 1);   /* if we pass this test we can allocate one more */
 
                LSNs[i] = ncbp->ncb_lsn;
                lanas[i] = ncbp->ncb_lana_num;
@@ -6485,7 +6855,7 @@ void smb_Listener(void *parmp)
                        /* Add new NCB for new session */
             char eventName[MAX_PATH];
 
-            osi_Log1(afsd_logp, "smb_Listener creating new session %d", i);
+            osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
 
                        InitNCBslot(numNCBs);
                        numNCBs++;
@@ -6507,7 +6877,7 @@ void smb_Listener(void *parmp)
                /* unlock */
                lock_ReleaseMutex(&smb_ListenerLock);
 
-        }      /* dispatch while loop */
+    }  /* dispatch while loop */
 }
 
 /* initialize Netbios */
@@ -6719,7 +7089,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
                if (tod > EXPIREDATE) {
 #ifndef DJGPP
                        (*smb_MBfunc)(NULL, "AFS demo expiration", "afsd",
-                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
+                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
                        exit(1);
 #else /* DJGPP */
             fprintf(stderr, "AFS demo expiration\n");
@@ -6813,6 +7183,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     smb_NetbiosInit();
 
        /* Initialize listener and server structures */
+    numVCs = 0;
        memset(dead_sessions, 0, sizeof(dead_sessions));
     sprintf(eventName, "SessionEvents[0]");
        SessionEvents[0] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
@@ -6870,6 +7241,10 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        smb_dispatchTable[0x23].procp = smb_ReceiveV3GetAttributes;
        smb_dispatchTable[0x24].procp = smb_ReceiveV3LockingX;
        smb_dispatchTable[0x24].flags |= SMB_DISPATCHFLAG_CHAINED;
+       smb_dispatchTable[0x25].procp = smb_ReceiveV3Trans;
+       smb_dispatchTable[0x25].flags |= SMB_DISPATCHFLAG_NORESPONSE;
+       smb_dispatchTable[0x26].procp = smb_ReceiveV3Trans;
+       smb_dispatchTable[0x26].flags |= SMB_DISPATCHFLAG_NORESPONSE;
        smb_dispatchTable[0x29].procp = smb_SendCoreBadOp;      /* copy file */
        smb_dispatchTable[0x2b].procp = smb_ReceiveCoreEcho;
        /* Set NORESPONSE because smb_ReceiveCoreEcho() does the responses itself */
@@ -6924,8 +7299,87 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext;
        smb_tran2DispatchTable[13].procp = smb_ReceiveTran2MKDir;
 
+    /* setup the rap dispatch table */
+    memset(smb_rapDispatchTable, 0, sizeof(smb_rapDispatchTable));
+    smb_rapDispatchTable[0].procp = smb_ReceiveRAPNetShareEnum;
+    smb_rapDispatchTable[1].procp = smb_ReceiveRAPNetShareGetInfo;
+    smb_rapDispatchTable[63].procp = smb_ReceiveRAPNetWkstaGetInfo;
+    smb_rapDispatchTable[13].procp = smb_ReceiveRAPNetServerGetInfo;
+
        smb3_Init();
 
+       /* if we are doing SMB authentication we have register outselves as a logon process */
+       if (smb_authType != SMB_AUTH_NONE) {
+        NTSTATUS nts;
+               LSA_STRING afsProcessName;
+               LSA_OPERATIONAL_MODE dummy; /*junk*/
+
+               afsProcessName.Buffer = "OpenAFSClientDaemon";
+               afsProcessName.Length = strlen(afsProcessName.Buffer);
+               afsProcessName.MaximumLength = afsProcessName.Length + 1;
+
+               nts = LsaRegisterLogonProcess(&afsProcessName, &smb_lsaHandle, &dummy);
+
+               if (nts == STATUS_SUCCESS) {
+                       LSA_STRING packageName;
+                       /* we are registered. Find out the security package id */
+                       packageName.Buffer = MSV1_0_PACKAGE_NAME;
+                       packageName.Length = strlen(packageName.Buffer);
+                       packageName.MaximumLength = packageName.Length + 1;
+                       nts = LsaLookupAuthenticationPackage(smb_lsaHandle, &packageName , &smb_lsaSecPackage);
+                       if (nts == STATUS_SUCCESS) {
+                               smb_lsaLogonOrigin.Buffer = "OpenAFS";
+                               smb_lsaLogonOrigin.Length = strlen(smb_lsaLogonOrigin.Buffer);
+                               smb_lsaLogonOrigin.MaximumLength = smb_lsaLogonOrigin.Length + 1;
+                       } else {
+                               afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%l]",nts);
+                       }
+               } else {
+                       afsi_log("Can't register logon process!! NTSTATUS=[%l]",nts);
+               }
+
+               if (nts != STATUS_SUCCESS) {
+                       /* something went wrong. We report the error and revert back to no authentication
+                          because we can't perform any auth requests without a successful lsa handle
+                          or sec package id. */
+                       afsi_log("Reverting to NO SMB AUTH");
+                       smb_authType = SMB_AUTH_NONE;
+               } 
+#ifdef COMMENT
+        /* Don't fallback to SMB_AUTH_NTLM.  Apparently, allowing SPNEGO to be used each
+         * time prevents the failure of authentication when logged into Windows with an
+         * external Kerberos principal mapped to a local account.
+         */
+        else if ( smb_authType == SMB_AUTH_EXTENDED) {
+            /* Test to see if there is anything to negotiate.  If SPNEGO is not going to be used 
+            * then the only option is NTLMSSP anyway; so just fallback. 
+            */
+            void * secBlob;
+            int secBlobLength;
+
+            smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
+            if (secBlobLength == 0) {
+                smb_authType = SMB_AUTH_NTLM;
+                afsi_log("Reverting to SMB AUTH NTLM");
+            } else
+                free(secBlob);
+        }
+#endif
+       }
+
+       {
+               DWORD bufsize;
+               /* Now get ourselves a domain name. */
+               /* For now we are using the local computer name as the domain name.
+               * It is actually the domain for local logins, and we are acting as
+               * a local SMB server. 
+               */
+               bufsize = sizeof(smb_ServerDomainName) - 1;
+               GetComputerName(smb_ServerDomainName, &bufsize);
+               smb_ServerDomainNameLength = bufsize + 1; /* bufsize doesn't include terminator */
+               afsi_log("Setting SMB server domain name to [%s]", smb_ServerDomainName);
+       }
+
        /* Start listeners, waiters, servers, and daemons */
 
        for (i = 0; i < lana_list.length; i++) {
@@ -6972,49 +7426,62 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        return;
 }
 
-#ifdef DJGPP
 void smb_Shutdown(void)
 {
     NCB *ncbp;
+#ifdef DJGPP
     dos_ptr dos_ncb;
-    long code;
+#endif
+    long code = 0;
     int i;
 
     /*fprintf(stderr, "Entering smb_Shutdown\n");*/
         
     /* setup the NCB system */
     ncbp = GetNCB();
+#ifdef DJGPP
     dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
+#endif
 
     /* Block new sessions by setting shutdown flag */
-    /*smbShutdownFlag = 1;*/
+    smbShutdownFlag = 1;
 
     /* Hang up all sessions */
+    memset((char *)ncbp, 0, sizeof(NCB));
     for (i = 1; i < numSessions; i++)
     {
         if (dead_sessions[i])
             continue;
-          
+      
         /*fprintf(stderr, "NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
         ncbp->ncb_command = NCBHANGUP;
         ncbp->ncb_lana_num = lanas[i];  /*smb_LANadapter;*/
         ncbp->ncb_lsn = LSNs[i];
-        code = Netbios(ncbp, dos_ncb);
+#ifndef DJGPP
+        code = Netbios(ncbp);
+#else
+               code = Netbios(ncbp, dos_ncb);
+#endif
         /*fprintf(stderr, "returned from NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
         if (code == 0) code = ncbp->ncb_retcode;
         if (code != 0) {
+            osi_Log1(smb_logp, "Netbios NCBHANGUP error code %d", code);
             fprintf(stderr, "Session %d Netbios NCBHANGUP error code %d", i, code);
         }
-        }
+    }
 
-#if 1
     /* Delete Netbios name */
+    memset((char *)ncbp, 0, sizeof(NCB));
        for (i = 0; i < lana_list.length; i++) {
                if (lana_list.lana[i] == 255) continue;
                ncbp->ncb_command = NCBDELNAME;
                ncbp->ncb_lana_num = lana_list.lana[i];
                memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
+#ifndef DJGPP
+        code = Netbios(ncbp);
+#else
                code = Netbios(ncbp, dos_ncb);
+#endif
                if (code == 0) code = ncbp->ncb_retcode;
                if (code != 0) {
                        fprintf(stderr, "Netbios NCBDELNAME lana %d error code %d",
@@ -7022,9 +7489,7 @@ void smb_Shutdown(void)
                }
                fflush(stderr);
        }
-#endif
 }
-#endif /* DJGPP */
 
 /* Get the UNC \\<servername>\<sharename> prefix. */
 char *smb_GetSharename()
@@ -7054,7 +7519,7 @@ void smb_LogPacket(smb_packet_t *packet)
 
        if(!packet) return;
 
-       osi_Log0(afsd_logp, "*** SMB packet dump ***");
+       osi_Log0(smb_logp, "*** SMB packet dump ***");
 
        vp = (BYTE *) packet->data;
 
@@ -7099,10 +7564,10 @@ void smb_LogPacket(smb_packet_t *packet)
 
                *cp = 0;
 
-               osi_Log0( afsd_logp, buf );
+               osi_Log0( smb_logp, buf );
        }
 
-       osi_Log0(afsd_logp, "*** End SMB packet dump ***");
+       osi_Log0(smb_logp, "*** End SMB packet dump ***");
 
 }
 
@@ -7117,6 +7582,9 @@ int smb_DumpVCP(FILE *outputFile, char *cookie)
   
     lock_ObtainRead(&smb_rctLock);
   
+    sprintf(output, "begin dumping vcpsp\n");
+    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+
     for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) 
     {
         smb_fid_t *fidp;
@@ -7125,7 +7593,10 @@ int smb_DumpVCP(FILE *outputFile, char *cookie)
                  cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
         WriteFile(outputFile, output, strlen(output), &zilch, NULL);
       
-        for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) 
+        sprintf(output, "begin dumping fidsp\n");
+        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+
+        for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
         {
             sprintf(output, "%s -- fidp=0x%08X, refCount=%d, fid=%d, vcp=0x%08X, scp=0x%08X, ioctlp=0x%08X, NTopen_pathp=%s, NTopen_wholepathp=%s\n", 
                      cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
@@ -7136,7 +7607,10 @@ int smb_DumpVCP(FILE *outputFile, char *cookie)
       
         sprintf(output, "done dumping fidsp\n");
         WriteFile(outputFile, output, strlen(output), &zilch, NULL);
-    }       
+    }
+
+    sprintf(output, "done dumping vcpsp\n");
+    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
   
     lock_ReleaseRead(&smb_rctLock);
     return 0;