time_t-200408018
[openafs.git] / src / WINNT / afsd / smb.c
index c49bb7d..7d0f37d 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"
 
@@ -44,12 +43,12 @@ smb_vc_t *active_vcp = NULL;
 /* TODO; logout mechanism needs to be thread-safe */
 char *loggedOutName = NULL;
 smb_user_t *loggedOutUserp = NULL;
-unsigned long loggedOutTime;
+time_t loggedOutTime;
 int loggedOut = 0;
 int smbShutdownFlag = 0;
 
 int smb_LogoffTokenTransfer;
-unsigned long smb_LogoffTransferTimeout;
+time_t smb_LogoffTransferTimeout;
 
 DWORD last_msg_time = 0;
 
@@ -82,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;
@@ -94,7 +98,7 @@ DWORD NCBsessions[NCBmax];
 NCB *NCBs[NCBmax];
 struct smb_packet *bufs[NCBmax];
 
-#define Sessionmax MAXIMUM_WAIT_OBJECTS
+#define Sessionmax MAXIMUM_WAIT_OBJECTS - 4
 EVENT_HANDLE SessionEvents[Sessionmax];
 unsigned short LSNs[Sessionmax];
 int lanas[Sessionmax];
@@ -111,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 */
@@ -139,15 +146,17 @@ 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:
  * Time in Unix format of midnight, 1/1/1970 local time.
  * When added to dosUTime, gives Unix (AFS) time.
  */
-long smb_localZero;
+long smb_localZero = 0;
 
 /* Time difference for converting to kludge-GMT */
 int smb_NowTZ;
@@ -182,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
  *
@@ -246,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:
@@ -257,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:
@@ -332,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)
 {
@@ -392,7 +432,7 @@ static int ExtractBits(WORD bits, short start, short len)
 }
 
 #ifndef DJGPP
-void ShowUnixTime(char *FuncName, long unixTime)
+void ShowUnixTime(char *FuncName, time_t unixTime)
 {
        FILETIME ft;
        WORD wDate, wTime;
@@ -400,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];
@@ -414,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 */
@@ -528,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 - (local_tm.tm_isdst ? 1 : 0);
+       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;
 
@@ -536,12 +583,12 @@ smb_CalculateNowTZ()
 }
 
 #ifndef DJGPP
-void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
+void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
 {
        struct tm *ltp;
        SYSTEMTIME stm;
        struct tm localJunk;
-       long ersatz_unixTime;
+       time_t ersatz_unixTime;
 
        /*
         * Must use kludge-GMT instead of real GMT.
@@ -576,7 +623,7 @@ void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
        SystemTimeToFileTime(&stm, largeTimep);
 }
 #else /* DJGPP */
-void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
+void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
 {
        /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
        /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 ??? */
@@ -598,7 +645,7 @@ void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, long unixTime)
 #endif /* !DJGPP */
 
 #ifndef DJGPP
-void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
+void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
 {
        SYSTEMTIME stm;
        struct tm lt;
@@ -621,7 +668,7 @@ void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
        _timezone = save_timezone;
 }
 #else /* DJGPP */
-void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
+void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
 {
        /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
        /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 GMT? */
@@ -642,32 +689,33 @@ void smb_UnixTimeFromLargeSearchTime(long *unixTimep, FILETIME *largeTimep)
 }
 #endif /* !DJGPP */
 
-void smb_SearchTimeFromUnixTime(long *dosTimep, long unixTime)
+void smb_SearchTimeFromUnixTime(long *dosTimep, time_t unixTime)
 {
-       struct tm *ltp;
-       int dosDate;
-       int dosTime;
-       struct tm localJunk;
-
-       ltp = localtime((time_t*) &unixTime);
-
-       /* if we fail, make up something */
-       if (!ltp) {
-               ltp = &localJunk;
-               localJunk.tm_year = 89 - 20;
-               localJunk.tm_mon = 4;
-               localJunk.tm_mday = 12;
-               localJunk.tm_hour = 0;
-               localJunk.tm_min = 0;
-               localJunk.tm_sec = 0;
-       }       
-
-       dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
-       dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
-       *dosTimep = (dosDate<<16) | dosTime;
+    struct tm *ltp;
+    int dosDate;
+    int dosTime;
+    struct tm localJunk;
+    time_t t = unixTime;
+
+    ltp = localtime((time_t*) &t);
+
+    /* if we fail, make up something */
+    if (!ltp) {
+        ltp = &localJunk;
+        localJunk.tm_year = 89 - 20;
+        localJunk.tm_mon = 4;
+        localJunk.tm_mday = 12;
+        localJunk.tm_hour = 0;
+        localJunk.tm_min = 0;
+        localJunk.tm_sec = 0;
+    }  
+
+    dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
+    dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
+    *dosTimep = (dosDate<<16) | dosTime;
 }      
 
-void smb_UnixTimeFromSearchTime(long *unixTimep, long searchTime)
+void smb_UnixTimeFromSearchTime(time_t *unixTimep, time_t searchTime)
 {
        unsigned short dosDate;
        unsigned short dosTime;
@@ -687,12 +735,12 @@ void smb_UnixTimeFromSearchTime(long *unixTimep, long searchTime)
        *unixTimep = mktime(&localTm);
 }
 
-void smb_DosUTimeFromUnixTime(long *dosUTimep, long unixTime)
+void smb_DosUTimeFromUnixTime(time_t *dosUTimep, time_t unixTime)
 {
        *dosUTimep = unixTime - smb_localZero;
 }
 
-void smb_UnixTimeFromDosUTime(long *unixTimep, long dosTime)
+void smb_UnixTimeFromDosUTime(time_t *unixTimep, time_t dosTime)
 {
 #ifndef DJGPP
        *unixTimep = dosTime + smb_localZero;
@@ -716,6 +764,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;
@@ -725,6 +774,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;
@@ -773,6 +849,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;
@@ -786,8 +863,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)) {
@@ -799,11 +878,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)
@@ -814,7 +897,9 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
        for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
                if (uid == uidp->userID) {
                        uidp->refCount++;
-                       osi_LogEvent("AFS smb_FindUID (Find by UID)",NULL," VCP[%x] found-uid[%d] name[%s]",(int)vcp,uidp->userID,(uidp->unp) ? uidp->unp->name : "");
+                        osi_LogEvent("AFS smb_FindUID (Find by UID)",NULL," VCP[%x] found-uid[%d] name[%s]",
+                                      (int)vcp, uidp->userID, 
+                                      osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
                break;
                }
        }
@@ -824,8 +909,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 : ""));
        }
@@ -882,8 +968,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)) {
@@ -898,12 +986,17 @@ void smb_ReleaseUID(smb_user_t *uidp)
                        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
@@ -935,17 +1028,23 @@ cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp)
  * Return a pointer to a pathname extracted from a TID structure.  The
  * TID structure is not held; assume it won't go away.
  */
-char *smb_GetTIDPath(smb_vc_t *vcp, unsigned short tid)
+long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** treepath)
 {
        smb_tid_t *tidp;
-       char *tpath;
+    long code = 0;
 
        tidp = smb_FindTID(vcp, tid, 0);
-    if (!tidp) 
-        return NULL;
-       tpath = tidp->pathname;
+    if (!tidp) {
+        *treepath = NULL;
+    } else {
+        if(tidp->flags & SMB_TIDFLAG_IPC) {
+            code = CM_ERROR_TIDIPC;
+            /* tidp->pathname would be NULL, but that's fine */
+        }
+        *treepath = tidp->pathname;
        smb_ReleaseTID(tidp);
-       return tpath;
+    }
+    return code;
 }
 
 /* check to see if we have a chained fid, that is, a fid that comes from an
@@ -967,19 +1066,24 @@ 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;
 
 retry:
        for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
@@ -996,20 +1100,30 @@ 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 ) {
+            osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, 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;
+            vcp->fidCounter = fid+1;
             if (vcp->fidCounter == 0) 
                 vcp->fidCounter = 1;
         }
@@ -1021,7 +1135,7 @@ 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)
@@ -1047,6 +1161,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);
 
@@ -1090,6 +1207,7 @@ char VNLCUserName[] = "%LCUSERNAME%";
 char VNComputerName[] = "%COMPUTERNAME%";
 char VNLCComputerName[] = "%LCCOMPUTERNAME%";
 
+#ifdef DJGPP
 /* List available shares */
 int smb_ListShares()
 {
@@ -1153,28 +1271,55 @@ int smb_ListShares()
 
        return num_shares;
 }
+#endif /* DJGPP */
+
+typedef struct smb_findShare_rock {
+    char * shareName;
+    char * match;
+    int matchType;
+} smb_findShare_rock_t;
+
+#define SMB_FINDSHARE_EXACT_MATCH 1
+#define SMB_FINDSHARE_PARTIAL_MATCH 2
+
+long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
+       osi_hyper_t *offp)
+{
+    int matchType = 0;
+    smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
+    if(!strnicmp(dep->name, vrock->shareName, 12)) {
+        if(!stricmp(dep->name, vrock->shareName))
+            matchType = SMB_FINDSHARE_EXACT_MATCH;
+        else
+            matchType = SMB_FINDSHARE_PARTIAL_MATCH;
+        if(vrock->match) free(vrock->match);
+        vrock->match = strdup(dep->name);
+        vrock->matchType = matchType;
+
+        if(matchType == SMB_FINDSHARE_EXACT_MATCH)
+            return CM_ERROR_STOPNOW;
+    }
+    return 0;
+}
+
 
 /* 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;
     DWORD allSubmount = 1;
 
-       if (strcmp(shareName, "IPC$") == 0) {
-               *pathNamep = NULL;
-               return 0;
-       }
-
     /* if allSubmounts == 0, only return the //mountRoot/all share 
      * if in fact it has been been created in the subMounts table.  
      * This is to allow sites that want to restrict access to the 
@@ -1205,14 +1350,33 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
                return 1;
        }
 
+    if (_stricmp(shareName, "IPC$") == 0 ||
+        _stricmp(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
+        _stricmp(shareName, "DESKTOP.INI") == 0
+         ) {
+               *pathNamep = NULL;
+               return 0;
+       }
+
 #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. 
@@ -1229,25 +1393,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)) 
             {
@@ -1268,11 +1426,40 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
         *pathNamep = strdup(p);
         return 1;
     } 
-    else /* create  \\<netbiosName>\<cellname>  */
+    else
     {
+        /* First lookup shareName in root.afs */
+        cm_req_t req;
+        smb_findShare_rock_t vrock;
+        osi_hyper_t thyper;
         char * p = shareName; 
         int rw = 0;
 
+        /*  attempt to locate a partial match in root.afs.  This is because
+            when using the ANSI RAP calls, the share name is limited to 13 chars
+            and hence is truncated. Of course we prefer exact matches. */
+        cm_InitReq(&req);
+        thyper.HighPart = 0;
+        thyper.LowPart = 0;
+
+        vrock.shareName = shareName;
+        vrock.match = NULL;
+        vrock.matchType = 0;
+
+        cm_HoldSCache(cm_rootSCachep);
+        code = cm_ApplyDir(cm_rootSCachep, smb_FindShareProc, &vrock, &thyper,
+            (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
+        cm_ReleaseSCache(cm_rootSCachep);
+
+        if(vrock.matchType) {
+            sprintf(pathName,"/%s/",vrock.match);
+            *pathNamep = strdup(strlwr(pathName));
+            free(vrock.match);
+            return 1;
+        }
+
+        /* if we get here, there was no match for the share in root.afs */
+        /* so try to create  \\<netbiosName>\<cellname>  */
         if ( *p == '.' ) {
             p++;
             rw = 1;
@@ -1297,6 +1484,52 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
     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.
  */
@@ -1506,12 +1739,12 @@ static smb_packet_t *GetPacket(void)
             signed int retval =
                 __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
             if (retval == -1) {
-                afsi_log("Cannot allocate %d paragraphs of DOS memory",
+                osi_Log1(smb_logp, "Cannot allocate %d paragraphs of DOS memory",
                           npar);
                 osi_panic("",__FILE__,__LINE__);
             }
             else {
-                afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
+                osi_Log2(smb_logp, "Allocated %d paragraphs of DOS mem at 0x%X",
                           npar, retval);
                 seg = retval;
             }
@@ -1557,11 +1790,11 @@ static NCB *GetNCB(void)
             signed int retval =
                 __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
             if (retval == -1) {
-                afsi_log("Cannot allocate %d paragraphs of DOS mem in GetNCB",
+                osi_Log1(smb_logp, "Cannot allocate %d paragraphs of DOS mem in GetNCB",
                           npar);
                 osi_panic("",__FILE__,__LINE__);
             } else {
-                afsi_log("Allocated %d paragraphs of DOS mem at 0x%X in GetNCB",
+                osi_Log2(smb_logp, "Allocated %d paragraphs of DOS mem at 0x%X in GetNCB",
                           npar, retval);
                 seg = retval;
             }
@@ -1658,24 +1891,21 @@ unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
        parmCount = *smbp->wctp;
 
        if (parm >= parmCount) {
+               char s[100];
 #ifndef DJGPP
         HANDLE h;
                char *ptbuf[1];
-               char s[100];
                h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+#endif
                sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
                                parm, parmCount, smbp->ncb_length);
+#ifndef DJGPP
                ptbuf[0] = s;
                ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
                                        1, smbp->ncb_length, ptbuf, smbp);
                DeregisterEventSource(h);
-#else /* DJGPP */
-               char s[100];
-
-               sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
-                               parm, parmCount, smbp->ncb_length);
-               osi_Log0(afsd_logp, s);
-#endif /* !DJGPP */
+#endif
+        osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
                osi_panic(s, __FILE__, __LINE__);
        }
        parmDatap = smbp->wctp + (2*parm) + 1;
@@ -1692,26 +1922,21 @@ unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
        parmCount = *smbp->wctp;
 
        if (parm * 2 + offset >= parmCount * 2) {
+               char s[100];
 #ifndef DJGPP
                HANDLE h;
                char *ptbuf[1];
-               char s[100];
                h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
+#endif
                sprintf(s, "Bad SMB param %d offset %d out of %d, ncb len %d",
                                parm, offset, parmCount, smbp->ncb_length);
-               ptbuf[0] = s;
+#ifndef DJGPP
+        ptbuf[0] = s;
                ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
                                        1, smbp->ncb_length, ptbuf, smbp);
                DeregisterEventSource(h);
-#else /* DJGPP */
-               char s[100];
-                
-               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);
-#endif /* !DJGPP */
-
+#endif
+        osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
                osi_panic(s, __FILE__, __LINE__);
        }
        parmDatap = smbp->wctp + (2*parm) + 1 + offset;
@@ -1907,7 +2132,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);
@@ -1918,6 +2143,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 */
        }
@@ -2012,12 +2238,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 %lX as NT %lX", code, NTStatus);
 }
 
 void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
@@ -2163,6 +2401,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;
@@ -2170,7 +2413,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 %lX as SMB %d: %d", code, class, error);
 }
 
 long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
@@ -2224,7 +2467,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);
@@ -2307,7 +2550,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 */
@@ -2338,26 +2581,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;
+       time_t 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;
                        }
@@ -2373,8 +2626,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
@@ -2399,43 +2652,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;
@@ -2454,12 +2670,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);
                /* 
@@ -2477,30 +2704,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);
        }
@@ -2509,13 +2806,32 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
 void smb_Daemon(void *parmp)
 {
-       int count = 0;
+       afs_uint32 count = 0;
 
        while(1) {
                count++;
                thrd_Sleep(10000);
-               if ((count % 360) == 0)         /* every hour */
-                       smb_CalculateNowTZ();
+               if ((count % 72) == 0)  {       /* every five minutes */
+            struct tm myTime;
+            long old_localZero = smb_localZero;
+                
+            /* 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();
+
+#ifdef AFS_FREELANCE
+            if ( smb_localZero != old_localZero )
+                cm_noteLocalMountPointChange();
+#endif
+        }
                /* XXX GC dir search entries */
        }
 }
@@ -2590,7 +2906,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);
@@ -2604,6 +2920,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;
@@ -2613,7 +2930,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);
@@ -2631,7 +2948,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;
@@ -2646,7 +2966,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;
 }
 
@@ -2785,7 +3105,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);
@@ -2850,7 +3170,7 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
        long code = 0;
        cm_scache_t *scp;
        char *dptr;
-       long dosTime;
+       time_t dosTime;
        u_short shortTemp;
        char attr;
        smb_dirListPatch_t *patchp;
@@ -2858,17 +3178,25 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
 
        for(patchp = *dirPatchespp; patchp; patchp =
                 (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
-               code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
-               if (code) continue;
+
+        dptr = patchp->dptr;
+
+        code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
+        if (code) {
+            if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+                *dptr++ = SMB_ATTR_HIDDEN;
+            continue;
+        }
                lock_ObtainMutex(&scp->mx);
                code = cm_SyncOp(scp, NULL, userp, reqp, 0,
                                                  CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
                if (code) {     
                        lock_ReleaseMutex(&scp->mx);
                        cm_ReleaseSCache(scp);
+            if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+                *dptr++ = SMB_ATTR_HIDDEN;
                        continue;
                }
-               dptr = patchp->dptr;
 
                attr = smb_Attributes(scp);
         /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
@@ -2876,7 +3204,7 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
             attr |= SMB_ATTR_HIDDEN;
         *dptr++ = attr;
 
-               /* get dos time */
+        /* get dos time */
                smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
                 
                /* copy out time */
@@ -2986,8 +3314,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 */
@@ -3029,7 +3357,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);
@@ -3045,7 +3373,14 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                spacep = inp->spacep;
                smb_StripLastComponent(spacep->data, NULL, pathp);
                lock_ReleaseMutex(&dsp->mx);
-               tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+               code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+        if(code) {
+            lock_ReleaseMutex(&dsp->mx);
+            cm_ReleaseUser(userp);
+            smb_DeleteDirSearch(dsp);
+            smb_ReleaseDirSearch(dsp);
+            return CM_ERROR_NOFILES;
+        }
                code = cm_NameI(cm_rootSCachep, spacep->data,
                                                caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
                lock_ObtainMutex(&dsp->mx);
@@ -3269,8 +3604,8 @@ 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 "
-                                                 "has filetype %d", dep->name,
+                               osi_Log2(smb_logp, "smb_ReceiveCoreSearchDir: file %s "
+                                                  "has filetype %d", osi_LogSaveString(smb_logp, dep->name),
                                                  fileType);
                                if (fileType == CM_SCACHETYPE_DIRECTORY)
                                        goto nextEntry;
@@ -3358,7 +3693,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) {
@@ -3409,8 +3744,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;
@@ -3422,7 +3757,11 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
        caseFold = CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
        code = cm_NameI(rootScp, pathp,
                                         caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
                                         userp, tidPathp, &req, &newScp);
@@ -3463,7 +3802,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
        unsigned short attribute;
        cm_attr_t attr;
        cm_scache_t *newScp;
-       long dosTime;
+       time_t dosTime;
        cm_user_t *userp;
        int caseFold;
        char *tidPathp;
@@ -3482,7 +3821,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;
@@ -3491,7 +3830,11 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 
        caseFold = CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHFILE;
+    }
        code = cm_NameI(rootScp, pathp, caseFold | CM_FLAG_FOLLOW, userp,
                                        tidPathp, &req, &newScp);
 
@@ -3558,7 +3901,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
        long code = 0;
        cm_scache_t *rootScp;
        cm_scache_t *newScp, *dscp;
-       long dosTime;
+       time_t dosTime;
        int attrs;
        cm_user_t *userp;
        int caseFold;
@@ -3579,8 +3922,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;
         
@@ -3589,7 +3932,11 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
        /* we shouldn't need this for V3 requests, but we seem to */
        caseFold = CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHFILE;
+    }
 
        /*
         * XXX Strange hack XXX
@@ -3692,7 +4039,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);
@@ -3716,7 +4063,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        long code = 0;
     cm_user_t *userp;
     cm_scache_t *scp;
-    long dosTime;
+    time_t dosTime;
     int caseFold;
        cm_space_t *spacep;
        char *tidPathp;
@@ -3727,7 +4074,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
     {
@@ -3767,7 +4114,11 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        caseFold = CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
     code = cm_NameI(cm_rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
                     tidPathp, &req, &scp);
         
@@ -3835,7 +4186,7 @@ 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;
 
@@ -3850,19 +4201,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",
@@ -3872,8 +4223,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;
 
@@ -3913,7 +4268,11 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp,
                                        &req, &dscp);
 
@@ -3930,7 +4289,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;
@@ -3938,7 +4297,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);
         
@@ -3956,7 +4333,7 @@ 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;
 
@@ -3968,16 +4345,15 @@ int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
        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);
@@ -4003,11 +4379,12 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        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;
@@ -4023,9 +4400,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);
@@ -4045,7 +4422,11 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
   */
        caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
                                        userp, tidPathp, &req, &oldDscp);
 
@@ -4079,6 +4460,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;
@@ -4087,16 +4470,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(smb_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(smb_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 */
@@ -4132,11 +4543,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;
 }
 
@@ -4145,7 +4556,7 @@ 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;
 
@@ -4157,12 +4568,15 @@ int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper
        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;
@@ -4211,7 +4625,11 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
        caseFold = CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
                                        userp, tidPathp, &req, &dscp);
 
@@ -4228,14 +4646,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);
         
@@ -4258,7 +4683,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        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);
@@ -4296,17 +4721,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);
@@ -4346,7 +4771,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);
@@ -4601,6 +5026,9 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        DWORD filter = 0;
        cm_req_t req;
 
+    osi_Log3(smb_logp, "smb_WriteData fid %d, off 0x%x, size 0x%x",
+              fidp->fid, offsetp->LowPart, count);
+
        cm_InitReq(&req);
 
        bufferp = NULL;
@@ -4612,10 +5040,14 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        lock_ObtainMutex(&scp->mx);
 
        /* start by looking up the file's end */
+    osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|SETSTATUS|GETSTATUS",
+              fidp->fid);
        code = cm_SyncOp(scp, NULL, userp, &req, 0,
                                         CM_SCACHESYNC_NEEDCALLBACK
                                         | CM_SCACHESYNC_SETSTATUS
                                         | CM_SCACHESYNC_GETSTATUS);
+    osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|SETSTATUS|GETSTATUS returns %d",
+              fidp->fid,code);
        if (code) 
                goto done;
         
@@ -4693,10 +5125,14 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
                        /* now get the data in the cache */
                        while (1) {
+                osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|WRITE|BUFLOCKED",
+                          fidp->fid);
                                code = cm_SyncOp(scp, bufferp, userp, &req, 0,
                                                                 CM_SCACHESYNC_NEEDCALLBACK
                                                                 | CM_SCACHESYNC_WRITE
                                                                 | CM_SCACHESYNC_BUFLOCKED);
+                osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|WRITE|BUFLOCKED returns %d",
+                          fidp->fid,code);
                                if (code) 
                                        goto done;
                                 
@@ -4799,13 +5235,20 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        }
 
        if (code == 0 && doWriteBack) {
+        long code2;
                lock_ObtainMutex(&scp->mx);
-               cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
+        osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
+                  fidp->fid);
+               code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
+        osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns %d",
+                  fidp->fid,code2);
                lock_ReleaseMutex(&scp->mx);
                cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
                                                   writeBackOffset.HighPart, cm_chunkSize, 0, userp);
        }
 
+    osi_Log2(smb_logp, "smb_WriteData fid %d returns %d",
+              fidp->fid, code);
        return code;
 }
 
@@ -4829,7 +5272,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 fid %d, off 0x%x, size 0x%x",
              fd, offset.LowPart, count);
         
        fd = smb_ChainFID(fd, inp);
@@ -4914,7 +5357,7 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        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);
@@ -4995,7 +5438,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);
         
@@ -5100,7 +5543,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);
@@ -5189,7 +5632,11 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
 
     caseFold = CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
 
        code = cm_NameI(cm_rootSCachep, spacep->data,
                     caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
@@ -5207,7 +5654,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;
@@ -5296,7 +5743,11 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     caseFold = CM_FLAG_CASEFOLD;
 
-       tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
+       code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if(code) {
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
        code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
                     userp, tidPathp, &req, &dscp);
 
@@ -5314,7 +5765,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;
@@ -5324,7 +5775,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);
@@ -5472,7 +5923,6 @@ 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 = 0;
@@ -5515,10 +5965,8 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                        1, ncbp->ncb_length, ptbuf, inp);
                DeregisterEventSource(h);
 #else /* DJGPP */
-        osi_Log1(smb_logp, "SMB message too short, len %d",
-                 ncbp->ncb_length);
+        osi_Log1(smb_logp, "SMB message too short, len %d", ncbp->ncb_length);
 #endif /* !DJGPP */
-
                return;
        }
 
@@ -5546,7 +5994,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 */
@@ -5580,10 +6028,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) {
@@ -5599,10 +6047,9 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0,
                             1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp);
                                DeregisterEventSource(h);
-#else /* DJGPP */
-                               osi_Log1(afsd_logp, "Pkt straddled session startup, "
-                         "ncb length %d", ncbp->ncb_length);
 #endif /* !DJGPP */
+                               osi_Log1(smb_logp, "Pkt straddled session startup, "
+                         "ncb length %d", ncbp->ncb_length);
                        }
         }
         else {
@@ -5615,7 +6062,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 */
@@ -5643,10 +6090,9 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
 #ifdef NOTSERVICE
             smb_LogPacket(inp);
 #endif /* NOTSERVICE */
-#else /* DJGPP */
-            osi_Log1(afsd_logp, "Invalid SMB message, length %d",
-                     ncbp->ncb_length);
 #endif /* !DJGPP */
+            osi_Log1(smb_logp, "Invalid SMB message, length %d",
+                     ncbp->ncb_length);
 
                        code = CM_ERROR_INVAL;
                }
@@ -5666,9 +6112,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;
@@ -5760,11 +6208,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;
 }
@@ -5790,23 +6246,23 @@ void smb_ClientWaiter(void *parmp)
         if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
         {
             int abandonIdx = code - WAIT_ABANDONED_0;
-            afsi_log("Error: smb_ClientWaiter event %d abandoned, errno %d\n", abandonIdx, GetLastError());
+            osi_Log2(smb_logp, "Error: smb_ClientWaiter event %d abandoned, errno %d\n", abandonIdx, GetLastError());
         }
 
         if (code == WAIT_IO_COMPLETION)
         {
-            afsi_log("Error: smb_ClientWaiter WAIT_IO_COMPLETION\n");
+            osi_Log0(smb_logp, "Error: smb_ClientWaiter WAIT_IO_COMPLETION\n");
             continue;
         }
         
         if (code == WAIT_TIMEOUT)
         {
-            afsi_log("Error: smb_ClientWaiter WAIT_TIMEOUT, errno %d\n", GetLastError());
+            osi_Log1(smb_logp, "Error: smb_ClientWaiter WAIT_TIMEOUT, errno %d\n", GetLastError());
         }
 
         if (code == WAIT_FAILED)
         {
-            afsi_log("Error: smb_ClientWaiter WAIT_FAILED, errno %d\n", GetLastError());
+            osi_Log1(smb_logp, "Error: smb_ClientWaiter WAIT_FAILED, errno %d\n", GetLastError());
         }
 
         idx = code - WAIT_OBJECT_0;
@@ -5815,7 +6271,7 @@ void smb_ClientWaiter(void *parmp)
         if (idx < 0 || idx > (sizeof(NCBevents) / sizeof(NCBevents[0])))
         {
             /* this is fatal - log as much as possible */
-            afsi_log("Fatal: NCBevents idx [ %d ] out of range.\n", idx);
+            osi_Log1(smb_logp, "Fatal: NCBevents idx [ %d ] out of range.\n", idx);
             osi_assert(0);
         }
         
@@ -5848,23 +6304,23 @@ void smb_ServerWaiter(void *parmp)
         if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numSessions))
         {
             int abandonIdx = code - WAIT_ABANDONED_0;
-            afsi_log("Error: smb_ServerWaiter (SessionEvents) event %d abandoned, errno %d\n", abandonIdx, GetLastError());
+            osi_Log2(smb_logp, "Error: smb_ServerWaiter (SessionEvents) event %d abandoned, errno %d\n", abandonIdx, GetLastError());
         }
        
         if (code == WAIT_IO_COMPLETION)
         {
-            afsi_log("Error: smb_ServerWaiter (SessionEvents) WAIT_IO_COMPLETION\n");
+            osi_Log0(smb_logp, "Error: smb_ServerWaiter (SessionEvents) WAIT_IO_COMPLETION\n");
             continue;
         }
        
         if (code == WAIT_TIMEOUT)
         {
-            afsi_log("Error: smb_ServerWaiter (SessionEvents) WAIT_TIMEOUT, errno %d\n", GetLastError());
+            osi_Log1(smb_logp, "Error: smb_ServerWaiter (SessionEvents) WAIT_TIMEOUT, errno %d\n", GetLastError());
         }
        
         if (code == WAIT_FAILED)
         {
-            afsi_log("Error: smb_ServerWaiter (SessionEvents) WAIT_FAILED, errno %d\n", GetLastError());
+            osi_Log1(smb_logp, "Error: smb_ServerWaiter (SessionEvents) WAIT_FAILED, errno %d\n", GetLastError());
         }
        
         idx_session = code - WAIT_OBJECT_0;
@@ -5873,7 +6329,7 @@ void smb_ServerWaiter(void *parmp)
         if (idx_session < 0 || idx_session > (sizeof(SessionEvents) / sizeof(SessionEvents[0])))
         {
             /* this is fatal - log as much as possible */
-            afsi_log("Fatal: session idx [ %d ] out of range.\n", idx_session);
+            osi_Log1(smb_logp, "Fatal: session idx [ %d ] out of range.\n", idx_session);
             osi_assert(0);
         }
 
@@ -5888,23 +6344,23 @@ void smb_ServerWaiter(void *parmp)
         if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
         {
             int abandonIdx = code - WAIT_ABANDONED_0;
-            afsi_log("Error: smb_ClientWaiter (NCBavails) event %d abandoned, errno %d\n", abandonIdx, GetLastError());
+            osi_Log2(smb_logp, "Error: smb_ClientWaiter (NCBavails) event %d abandoned, errno %d\n", abandonIdx, GetLastError());
         }
        
         if (code == WAIT_IO_COMPLETION)
         {
-            afsi_log("Error: smb_ClientWaiter (NCBavails) WAIT_IO_COMPLETION\n");
+            osi_Log0(smb_logp, "Error: smb_ClientWaiter (NCBavails) WAIT_IO_COMPLETION\n");
             continue;
         }
        
         if (code == WAIT_TIMEOUT)
         {
-            afsi_log("Error: smb_ClientWaiter (NCBavails) WAIT_TIMEOUT, errno %d\n", GetLastError());
+            osi_Log1(smb_logp, "Error: smb_ClientWaiter (NCBavails) WAIT_TIMEOUT, errno %d\n", GetLastError());
         }
        
         if (code == WAIT_FAILED)
         {
-            afsi_log("Error: smb_ClientWaiter (NCBavails) WAIT_FAILED, errno %d\n", GetLastError());
+            osi_Log1(smb_logp, "Error: smb_ClientWaiter (NCBavails) WAIT_FAILED, errno %d\n", GetLastError());
         }
                
         idx_NCB = code - WAIT_OBJECT_0;
@@ -5913,7 +6369,7 @@ void smb_ServerWaiter(void *parmp)
         if (idx_NCB < 0 || idx_NCB > (sizeof(NCBsessions) / sizeof(NCBsessions[0])))
         {
             /* this is fatal - log as much as possible */
-            afsi_log("Fatal: idx_NCB [ %d ] out of range.\n", idx_NCB);
+            osi_Log1(smb_logp, "Fatal: idx_NCB [ %d ] out of range.\n", idx_NCB);
             osi_assert(0);
         }
 
@@ -5963,7 +6419,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;
@@ -5981,7 +6437,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);
                        }
                }
@@ -5997,23 +6453,23 @@ void smb_Server(VOID *parmp)
         if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
         {
             int abandonIdx = code - WAIT_ABANDONED_0;
-            afsi_log("Error: smb_Server ( NCBreturns[%d] ) event %d abandoned, errno %d\n", myIdx, abandonIdx, GetLastError());
+            osi_Log3(smb_logp, "Error: smb_Server ( NCBreturns[%d] ) event %d abandoned, errno %d\n", myIdx, abandonIdx, GetLastError());
         }
        
         if (code == WAIT_IO_COMPLETION)
         {
-            afsi_log("Error: smb_Server ( NCBreturns[%d] ) WAIT_IO_COMPLETION\n", myIdx);
+            osi_Log1(smb_logp, "Error: smb_Server ( NCBreturns[%d] ) WAIT_IO_COMPLETION\n", myIdx);
             continue;
         }
        
         if (code == WAIT_TIMEOUT)
         {
-            afsi_log("Error: smb_Server ( NCBreturns[%d] ) WAIT_TIMEOUT, errno %d\n", myIdx, GetLastError());
+            osi_Log2(smb_logp, "Error: smb_Server ( NCBreturns[%d] ) WAIT_TIMEOUT, errno %d\n", myIdx, GetLastError());
         }
        
         if (code == WAIT_FAILED)
         {
-            afsi_log("Error: smb_Server ( NCBreturns[%d] ) WAIT_FAILED, errno %d\n", myIdx, GetLastError());
+            osi_Log2(smb_logp, "Error: smb_Server ( NCBreturns[%d] ) WAIT_FAILED, errno %d\n", myIdx, GetLastError());
         }
 
         idx_NCB = code - WAIT_OBJECT_0;
@@ -6022,7 +6478,7 @@ void smb_Server(VOID *parmp)
         if (idx_NCB < 0 || idx_NCB > (sizeof(NCBs) / sizeof(NCBs[0])))
         {
             /* this is fatal - log as much as possible */
-            afsi_log("Fatal: idx_NCB [ %d ] out of range.\n", idx_NCB);
+            osi_Log1(smb_logp, "Fatal: idx_NCB [ %d ] out of range.\n", idx_NCB);
             osi_assert(0);
         }
 
@@ -6034,7 +6490,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;
@@ -6050,11 +6506,14 @@ void smb_Server(VOID *parmp)
                                /* Client closed session */
                 if (reportSessionStartups) 
                 {
-                    afsi_log("session [ %d ] closed", idx_session);
+                    osi_Log1(smb_logp, "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, 
@@ -6062,13 +6521,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;
                     }
@@ -6093,8 +6553,6 @@ void smb_Server(VOID *parmp)
                                        char *ptbuf[1];
                                        char s[100];
 
-                                       osi_Log1(smb_logp, "dispatch smb recv failed, message incomplete, ncb_length %d",
-                             ncbp->ncb_length);
                                        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
                                        sprintf(s, "SMB message incomplete, length %d",
                             ncbp->ncb_length);
@@ -6104,14 +6562,13 @@ void smb_Server(VOID *parmp)
                                 ncbp->ncb_length, ptbuf,
                                 bufp);
                                        DeregisterEventSource(h);
-#else /* DJGPP */
+#endif /* !DJGPP */
                                        osi_Log1(smb_logp,
                               "dispatch smb recv failed, message incomplete, ncb_length %d",
                               ncbp->ncb_length);
                     osi_Log1(smb_logp,
                               "SMB message incomplete, "
                               "length %d", ncbp->ncb_length);
-#endif /* !DJGPP */
 
                                        /*
                                         * We used to discard the packet.
@@ -6125,8 +6582,8 @@ void smb_Server(VOID *parmp)
                        default:
                                /* A weird error code.  Log it, sleep, and
                                 * continue. */
-                               if (vcp->errorCount++ > 3) {
-                    afsi_log("session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
+                               if (vcp && vcp->errorCount++ > 3) {
+                    osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
                                        dead_sessions[idx_session] = TRUE;
                 }
                                else {
@@ -6142,6 +6599,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)
@@ -6179,7 +6638,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],"
@@ -6224,7 +6683,7 @@ void smb_Server(VOID *parmp)
                        if (rwc.code == 0) {
                                rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, TEXT("smb_Server() rwevent"));
                 if ( GetLastError() == ERROR_ALREADY_EXISTS )
-                    afsi_log("Event Object Already Exists: %s", eventName);
+                    osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
                                ncbp->ncb_command = NCBRECV | ASYNCH;
                                ncbp->ncb_lsn = (unsigned char) vcp->lsn;
                                ncbp->ncb_lana_num = vcp->lana;
@@ -6265,6 +6724,8 @@ void smb_Server(VOID *parmp)
 doneWithNCB:
                thrd_SetEvent(NCBavails[idx_NCB]);
        }
+    if (vcp)
+        smb_ReleaseVC(vcp);
 }
 
 /*
@@ -6314,17 +6775,17 @@ void InitNCBslot(int idx)
     sprintf(eventName,"NCBavails[%d]", idx);
        NCBavails[idx] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
-        afsi_log("Event Object Already Exists: %s", eventName);
+        osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
 #ifndef DJGPP
     sprintf(eventName,"NCBevents[%d]", idx);
        NCBevents[idx] = thrd_CreateEvent(NULL, TRUE, FALSE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
-        afsi_log("Event Object Already Exists: %s", eventName);
+        osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
 #endif /* !DJGPP */
     sprintf(eventName,"NCBReturns[0<=i<smb_NumServerThreads][%d]", idx);
        retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
-        afsi_log("Event Object Already Exists: %s", eventName);
+        osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
        for (i=0; i<smb_NumServerThreads; i++)
                NCBreturns[i][idx] = retHandle;
        bufp = GetPacket();
@@ -6370,7 +6831,7 @@ void smb_Listener(void *parmp)
                        if (tod > EXPIREDATE) {
                                (*smb_MBfunc)(NULL, "AFS demo expiration",
                                "afsd listener",
-                               MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
+                               MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
 #ifndef DJGPP
                 ExitThread(1);
 #else
@@ -6402,7 +6863,11 @@ void smb_Listener(void *parmp)
 
         if (code != 0)
         {
-                   /* terminate if shutdown flag is set */
+#ifndef DJGPP
+            char tbuffer[256];
+#endif
+
+            /* terminate silently if shutdown flag is set */
                if (smbShutdownFlag == 1) {
 #ifndef DJGPP
                            ExitThread(1);
@@ -6411,17 +6876,29 @@ void smb_Listener(void *parmp)
 #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
-                       osi_assert(0);
+            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 */
         }
 
@@ -6440,7 +6917,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);
 
@@ -6453,8 +6930,8 @@ void smb_Listener(void *parmp)
                                "%s\n",
                 ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
 #endif
-        afsi_log("New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
-                  ncbp->ncb_lsn,ncbp->ncb_lana_num, rname, ongoingOps);
+        osi_Log4(smb_logp, "New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops",
+                  ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps);
 
         if (reportSessionStartups) {
 #ifndef DJGPP
@@ -6469,15 +6946,15 @@ void smb_Listener(void *parmp)
                         1, 0, ptbuf, NULL);
                        DeregisterEventSource(h);
 #else /* DJGPP */
-            afsi_log("NCBLISTEN completed, call from %s",rname);
-            osi_Log1(afsd_logp, "SMB session startup, %d ongoing ops",
-                     ongoingOps);
             time(&now);
             fprintf(stderr, "%s: New session %d starting from host %s\n",
                     asctime(localtime(&now)), ncbp->ncb_lsn, rname);
             fflush(stderr);
 #endif /* !DJGPP */
                }
+            osi_Log1(smb_logp, "NCBLISTEN completed, call from %s", osi_LogSaveString(smb_logp, rname));
+            osi_Log1(smb_logp, "SMB session startup, %d ongoing ops",
+                     ongoingOps);
 
         /* now ncbp->ncb_lsn is the connection ID */
         vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num);
@@ -6489,7 +6966,7 @@ void smb_Listener(void *parmp)
         /* But don't look at session[0], it is reserved */
                for (i = 1; i < numSessions; i++) {
                        if (dead_sessions[i]) {
-                afsi_log("connecting to dead session [ %d ]", i);
+                osi_Log1(smb_logp, "connecting to dead session [ %d ]", i);
                                dead_sessions[i] = FALSE;
                                break;
                        }
@@ -6500,7 +6977,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;
@@ -6509,7 +6987,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++;
@@ -6521,9 +6999,9 @@ void smb_Listener(void *parmp)
             sprintf(eventName, "SessionEvents[%d]", i);
             SessionEvents[i] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
             if ( GetLastError() == ERROR_ALREADY_EXISTS )
-                afsi_log("Event Object Already Exists: %s", eventName);
+                osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
                        numSessions++;
-            afsi_log("increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
+            osi_Log2(smb_logp, "increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
                        thrd_SetEvent(SessionEvents[0]);
                } else {
                        thrd_SetEvent(SessionEvents[i]);
@@ -6571,7 +7049,7 @@ void smb_NetbiosInit()
         code = Netbios(ncbp);
         if (code != 0) {
             sprintf(s, "Netbios NCBENUM error code %d", code);
-            afsi_log(s);
+            osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
             osi_panic(s, __FILE__, __LINE__);
         }
     }
@@ -6593,11 +7071,11 @@ void smb_NetbiosInit()
             code = ncbp->ncb_retcode;
         if (code != 0) {
             sprintf(s, "Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
-            afsi_log(s);
+            osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
             lana_list.lana[i] = 255;  /* invalid lana */
         } else {
             sprintf(s, "Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
-            afsi_log(s);
+            osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
         }
     }
 #else
@@ -6620,7 +7098,7 @@ void smb_NetbiosInit()
     memset(smb_sharename,' ',NCBNAMSZ);
     memcpy(smb_sharename,smb_localNamep,len);
     sprintf(s, "lana_list.length %d", lana_list.length);
-    afsi_log(s);
+    osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
 
     /* Keep the name so we can unregister it later */
     for (l = 0; l < lana_list.length; l++) {
@@ -6635,18 +7113,18 @@ void smb_NetbiosInit()
         code = Netbios(ncbp, dos_ncb);
 #endif /* !DJGPP */
           
-        afsi_log("Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
-                 lana, code, ncbp->ncb_retcode,ncbp->ncb_cmd_cplt);
+        osi_Log4(smb_logp, "Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
+                 lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
         {
             char name[NCBNAMSZ+1];
             name[NCBNAMSZ]=0;
             memcpy(name,ncbp->ncb_name,NCBNAMSZ);
-            afsi_log("Netbios NCBADDNAME added new name >%s<",name);
+            osi_Log1(smb_logp, "Netbios NCBADDNAME added new name >%s<",osi_LogSaveString(smb_logp, name));
         }
 
         if (code == 0) code = ncbp->ncb_retcode;
         if (code == 0) {
-            afsi_log("Netbios NCBADDNAME succeeded on lana %d\n", lana);
+            osi_Log1(smb_logp, "Netbios NCBADDNAME succeeded on lana %d\n", lana);
 #ifdef DJGPP
             /* we only use one LANA with djgpp */
             lana_list.lana[0] = lana;
@@ -6655,13 +7133,13 @@ void smb_NetbiosInit()
         }
         else {
             sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
-            afsi_log(s);
+            osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
             if (code == NRC_BRIDGE) {    /* invalid LANA num */
                 lana_list.lana[l] = 255;
                 continue;
             }
             else if (code == NRC_DUPNAME) {
-                afsi_log("Name already exists; try to delete it");
+                osi_Log0(smb_logp, "Name already exists; try to delete it");
                 memset(ncbp, 0, sizeof(*ncbp));
                 ncbp->ncb_command = NCBDELNAME;
                 memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
@@ -6674,7 +7152,7 @@ void smb_NetbiosInit()
                 if (code == 0) code = ncbp->ncb_retcode;
                 else {
                     sprintf(s, "Netbios NCBDELNAME lana %d error code %d\n", lana, code);
-                    afsi_log(s);
+                    osi_Log0(smb_logp, s);
                 }
                 if (code != 0 || delname_tried) {
                     lana_list.lana[l] = 255;
@@ -6689,7 +7167,7 @@ void smb_NetbiosInit()
             }
             else {
                 sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
-                afsi_log(s);
+                osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
                 lana_list.lana[l] = 255;  /* invalid lana */
                 osi_panic(s, __FILE__, __LINE__);
             }
@@ -6743,7 +7221,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");
@@ -6769,6 +7247,11 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
        /* Initialize kludge-GMT */
        smb_CalculateNowTZ();
 
+#ifdef AFS_FREELANCE_CLIENT
+    /* Make sure the root.afs volume has the correct time */
+    cm_noteLocalMountPointChange();
+#endif
+
        /* initialize the remote debugging log */
        smb_logp = logp;
         
@@ -6837,6 +7320,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);
@@ -6894,6 +7378,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 */
@@ -6948,8 +7436,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++) {
@@ -7035,7 +7602,7 @@ void smb_Shutdown(void)
         /*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(afsd_logp, "Netbios NCBHANGUP error code %d", code);
+            osi_Log1(smb_logp, "Netbios NCBHANGUP error code %d", code);
             fprintf(stderr, "Session %d Netbios NCBHANGUP error code %d", i, code);
         }
     }
@@ -7089,7 +7656,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;
 
@@ -7134,10 +7701,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 ***");
 
 }
 
@@ -7152,6 +7719,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;
@@ -7160,7 +7730,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, 
@@ -7171,7 +7744,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;