windows-dafs-20060320
[openafs.git] / src / WINNT / afsd / smb.c
index 2833abd..58bd190 100644 (file)
 static char *illegalChars = "\\/:*?\"<>|";
 BOOL isWindows2000 = FALSE;
 
-smb_vc_t *dead_vcp = NULL;
 smb_vc_t *active_vcp = NULL;
 
-/* TODO; logout mechanism needs to be thread-safe */
-char *loggedOutName = NULL;
-smb_user_t *loggedOutUserp = NULL;
-time_t loggedOutTime;
-int loggedOut = 0;
 int smbShutdownFlag = 0;
 
 int smb_LogoffTokenTransfer;
@@ -94,20 +88,20 @@ HANDLE smb_lsaHandle;
 ULONG smb_lsaSecPackage;
 LSA_STRING smb_lsaLogonOrigin;
 
-#define NCBmax MAXIMUM_WAIT_OBJECTS
-EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
+#define NCB_MAX MAXIMUM_WAIT_OBJECTS
+EVENT_HANDLE NCBavails[NCB_MAX], NCBevents[NCB_MAX];
 EVENT_HANDLE **NCBreturns;
 EVENT_HANDLE **NCBShutdown;
 EVENT_HANDLE *smb_ServerShutdown;
-DWORD NCBsessions[NCBmax];
-NCB *NCBs[NCBmax];
-struct smb_packet *bufs[NCBmax];
-
-#define Sessionmax MAXIMUM_WAIT_OBJECTS - 4
-EVENT_HANDLE SessionEvents[Sessionmax];
-unsigned short LSNs[Sessionmax];
-int lanas[Sessionmax];
-BOOL dead_sessions[Sessionmax];
+DWORD NCBsessions[NCB_MAX];
+NCB *NCBs[NCB_MAX];
+struct smb_packet *bufs[NCB_MAX];
+
+#define SESSION_MAX MAXIMUM_WAIT_OBJECTS - 4
+EVENT_HANDLE SessionEvents[SESSION_MAX];
+unsigned short LSNs[SESSION_MAX];
+int lanas[SESSION_MAX];
+BOOL dead_sessions[SESSION_MAX];
 LANA_ENUM lana_list;
 
 /* for raw I/O */
@@ -172,6 +166,7 @@ afs_uint32 smb_NowTZ;
 char *smb_localNamep = NULL;
 
 smb_vc_t *smb_allVCsp;
+smb_vc_t *smb_deadVCsp;
 
 smb_username_t *usernamesp = NULL;
 
@@ -179,7 +174,7 @@ smb_waitingLockRequest_t *smb_allWaitingLocks;
 
 /* forward decl */
 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
-                                               NCB *ncbp, raw_write_cont_t *rwcp);
+                       NCB *ncbp, raw_write_cont_t *rwcp);
 void smb_NetbiosInit();
 #ifdef DJGPP
 #ifndef AFS_WIN95_ENV
@@ -211,6 +206,53 @@ 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 }};
 
+const char * ncb_error_string(int code)
+{
+    const char * s;
+    switch ( code ) {
+    case 0x01: s = "llegal buffer length";                     break; 
+    case 0x03: s = "illegal command";                          break; 
+    case 0x05: s = "command timed out";                        break; 
+    case 0x06: s = "message incomplete, issue another command"; break; 
+    case 0x07: s = "illegal buffer address";                   break; 
+    case 0x08: s = "session number out of range";              break; 
+    case 0x09: s = "no resource available";                    break; 
+    case 0x0a: s = "session closed";                           break; 
+    case 0x0b: s = "command cancelled";                        break; 
+    case 0x0d: s = "duplicate name";                           break; 
+    case 0x0e: s = "name table full";                          break; 
+    case 0x0f: s = "no deletions, name has active sessions";   break; 
+    case 0x11: s = "local session table full";                         break; 
+    case 0x12: s = "remote session table full";                break; 
+    case 0x13: s = "illegal name number";                      break; 
+    case 0x14: s = "no callname";                              break; 
+    case 0x15: s = "cannot put * in NCB_NAME";                         break; 
+    case 0x16: s = "name in use on remote adapter";            break; 
+    case 0x17: s = "name deleted";                             break; 
+    case 0x18: s = "session ended abnormally";                         break; 
+    case 0x19: s = "name conflict detected";                   break; 
+    case 0x21: s = "interface busy, IRET before retrying";     break; 
+    case 0x22: s = "too many commands outstanding, retry later";break;
+    case 0x23: s = "ncb_lana_num field invalid";               break; 
+    case 0x24: s = "command completed while cancel occurring "; break; 
+    case 0x26: s = "command not valid to cancel";              break; 
+    case 0x30: s = "name defined by anther local process";     break; 
+    case 0x34: s = "environment undefined. RESET required";    break; 
+    case 0x35: s = "required OS resources exhausted";          break; 
+    case 0x36: s = "max number of applications exceeded";      break; 
+    case 0x37: s = "no saps available for netbios";            break; 
+    case 0x38: s = "requested resources are not available";    break; 
+    case 0x39: s = "invalid ncb address or length > segment";  break; 
+    case 0x3B: s = "invalid NCB DDID";                                 break; 
+    case 0x3C: s = "lock of user area failed";                         break; 
+    case 0x3f: s = "NETBIOS not loaded";                       break; 
+    case 0x40: s = "system error";                             break;                 
+    default:   s = "unknown error";
+    }
+    return s;
+}
+
+
 char * myCrt_Dispatch(int i)
 {
     switch (i)
@@ -753,7 +795,7 @@ void smb_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
     struct tm localJunk;
     time_t t = unixTime;
 
-    ltp = localtime((time_t*) &t);
+    ltp = localtime(&t);
 
     /* if we fail, make up something */
     if (!ltp) {
@@ -793,7 +835,11 @@ void smb_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
 
 void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
 {
-    *dosUTimep = unixTime - smb_localZero;
+    time_t diff_t = unixTime - smb_localZero;
+#if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
+    osi_assert(diff_t < _UI32_MAX);
+#endif
+    *dosUTimep = (afs_uint32)diff_t;
 }
 
 void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
@@ -820,11 +866,13 @@ 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;
+       lock_ObtainWrite(&smb_globalLock);
+        vcp->vcID = ++numVCs;
+       lock_ReleaseWrite(&smb_globalLock);
+        vcp->refCount = 2;     /* smb_allVCsp and caller */
         vcp->tidCounter = 1;
         vcp->fidCounter = 1;
-        vcp->uidCounter = 1;  /* UID 0 is reserved for blank user */
+        vcp->uidCounter = 1;   /* UID 0 is reserved for blank user */
         vcp->nextp = smb_allVCsp;
         smb_allVCsp = vcp;
         lock_InitializeMutex(&vcp->mx, "vc_t mutex");
@@ -862,7 +910,9 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
             memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
 
         if (numVCs >= CM_SESSION_RESERVED) {
+           lock_ObtainWrite(&smb_globalLock);
             numVCs = 0;
+           lock_ReleaseWrite(&smb_globalLock);
             osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
         }
     }
@@ -877,30 +927,47 @@ int smb_IsStarMask(char *maskp)
         
     for(i=0; i<11; i++) {
         tc = *maskp++;
-        if (tc == '?' || tc == '*' || tc == '>') return 1;        
+        if (tc == '?' || tc == '*' || tc == '>')
+           return 1;
     }  
     return 0;
 }
 
-void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+void smb_ReleaseVCInternal(smb_vc_t *vcp)
 {
-    osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+    smb_vc_t **vcpp;
+
 #ifdef DEBUG
     osi_assert(vcp->refCount-- != 0);
 #else
     vcp->refCount--;
 #endif
+
+    if (vcp->refCount == 0) {
+       /* remove VCP from smb_deadVCsp */
+       for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+           if (*vcpp == vcp) {
+               *vcpp = vcp->nextp;
+               break;
+           }
+       } 
+       lock_FinalizeMutex(&vcp->mx);
+       memset(vcp,0,sizeof(smb_vc_t));
+       free(vcp);
+    }
+}
+
+void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+{
+    osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+    smb_ReleaseVCInternal(vcp);
 }       
 
 void smb_ReleaseVC(smb_vc_t *vcp)
 {
     lock_ObtainWrite(&smb_rctLock);
     osi_Log2(smb_logp,"smb_ReleaseVC       vcp %x ref %d",vcp, vcp->refCount);
-#ifdef DEBUG
-    osi_assert(vcp->refCount-- != 0);
-#else
-    vcp->refCount--;
-#endif
+    smb_ReleaseVCInternal(vcp);
     lock_ReleaseWrite(&smb_rctLock);
 }       
 
@@ -918,6 +985,92 @@ void smb_HoldVC(smb_vc_t *vcp)
     lock_ReleaseWrite(&smb_rctLock);
 }       
 
+void smb_CleanupDeadVC(smb_vc_t *vcp)
+{
+    smb_fid_t *fidpIter;
+    smb_fid_t *fidpNext;
+    unsigned short fid;
+    smb_tid_t *tidpIter;
+    smb_tid_t *tidpNext;
+    unsigned short tid;
+    smb_user_t *uidpIter;
+    smb_user_t *uidpNext;
+    smb_vc_t **vcpp;
+
+    osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
+
+    lock_ObtainWrite(&smb_rctLock);
+    for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
+        fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
+
+        if (fidpIter->delete)
+            continue;
+
+        fid = fidpIter->fid;
+       osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter);
+
+       smb_HoldFIDNoLock(fidpIter);
+        lock_ReleaseWrite(&smb_rctLock);
+
+        smb_CloseFID(vcp, fidpIter, NULL, 0);
+       smb_ReleaseFID(fidpIter);
+
+        lock_ObtainWrite(&smb_rctLock);
+       fidpNext = vcp->fidsp;
+    }
+
+    for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
+       tidpNext = tidpIter->nextp;
+       if (tidpIter->delete)
+           continue;
+       tidpIter->delete = 1;
+
+       tid = tidpIter->tid;
+       osi_Log2(smb_logp, "  Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
+
+       smb_HoldTIDNoLock(tidpIter);
+       lock_ReleaseWrite(&smb_rctLock);
+
+       smb_ReleaseTID(tidpIter);
+
+       lock_ObtainWrite(&smb_rctLock);
+       tidpNext = vcp->tidsp;
+    }
+
+    for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
+       uidpNext = uidpIter->nextp;
+       if (uidpIter->delete)
+           continue;
+       uidpIter->delete = 1;
+
+       /* do not add an additional reference count for the smb_user_t
+        * as the smb_vc_t already is holding a reference */
+       lock_ReleaseWrite(&smb_rctLock);
+
+       smb_ReleaseUID(uidpIter);
+
+       lock_ObtainWrite(&smb_rctLock);
+       uidpNext = vcp->usersp;
+    }
+
+    /* remove VCP from smb_allVCsp */
+    for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+       if (*vcpp == vcp) {
+           *vcpp = vcp->nextp;
+           vcp->nextp = smb_deadVCsp;
+           smb_deadVCsp = vcp;
+           /* We intentionally do not keep a reference to the 
+            * vcp once it is placed on the deadVCsp list.  This
+            * allows the refcount to reach 0 so we can delete
+            * it. */
+           smb_ReleaseVCNoLock(vcp);
+           break;
+       }
+    } 
+    lock_ReleaseWrite(&smb_rctLock);
+    osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
+}
+
 smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
 {
     smb_tid_t *tidp;
@@ -944,6 +1097,11 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
     return tidp;
 }              
 
+void smb_HoldTIDNoLock(smb_tid_t *tidp)
+{
+    tidp->refCount++;
+}
+
 void smb_ReleaseTID(smb_tid_t *tidp)
 {
     smb_tid_t *tp;
@@ -953,7 +1111,7 @@ void smb_ReleaseTID(smb_tid_t *tidp)
     userp = NULL;
     lock_ObtainWrite(&smb_rctLock);
     osi_assert(tidp->refCount-- > 0);
-    if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
+    if (tidp->refCount == 0 && (tidp->delete)) {
         ltpp = &tidp->vcp->tidsp;
         for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
             if (tp == tidp) 
@@ -965,7 +1123,7 @@ void smb_ReleaseTID(smb_tid_t *tidp)
         userp = tidp->userp;   /* remember to drop ref later */
         tidp->userp = NULL;
         smb_ReleaseVCNoLock(tidp->vcp);
-        tidp->vcp = 0;
+        tidp->vcp = NULL;
     }
     lock_ReleaseWrite(&smb_rctLock);
     if (userp)
@@ -980,9 +1138,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, 
-                          osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
+            osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%s]",
+                    vcp, uidp->userID, 
+                    osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
             break;
         }
     }
@@ -990,19 +1148,21 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
         uidp = malloc(sizeof(*uidp));
         memset(uidp, 0, sizeof(*uidp));
         uidp->nextp = vcp->usersp;
-        uidp->refCount = 1;
+        uidp->refCount = 2; /* one for the vcp and one for the caller */
         uidp->vcp = vcp;
         smb_HoldVCNoLock(vcp);
         vcp->usersp = uidp;
         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 : ""));
+        osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%s]",
+                vcp, uidp->userID, 
+                osi_LogSaveString(smb_logp,uidp->unp ? uidp->unp->name : ""));
     }
     lock_ReleaseWrite(&smb_rctLock);
     return uidp;
 }              
 
-smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags)
+smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
 {
     smb_username_t *unp= NULL;
 
@@ -1023,7 +1183,10 @@ smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags)
         unp->machine = strdup(machine);
         usernamesp = unp;
         lock_InitializeMutex(&unp->mx, "username_t mutex");
+       if (flags & SMB_FLAG_AFSLOGON)
+           unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
     }
+
     lock_ReleaseWrite(&smb_rctLock);
     return unp;
 }      
@@ -1038,7 +1201,8 @@ smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
             continue;
         if (stricmp(uidp->unp->name, usern) == 0) {
             uidp->refCount++;
-            osi_LogEvent("AFS smb_FindUserByNameThisSession",NULL,"VCP[%x] uid[%d] match-name[%s]",(int)vcp,uidp->userID,usern);
+            osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%s]",
+                    vcp,uidp->userID,osi_LogSaveString(smb_logp,usern));
             break;
         } else
             continue;
@@ -1046,16 +1210,53 @@ smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
     lock_ReleaseWrite(&smb_rctLock);
     return uidp;
 }       
+
+void smb_ReleaseUsername(smb_username_t *unp)
+{
+    smb_username_t *up;
+    smb_username_t **lupp;
+    cm_user_t *userp = NULL;
+    time_t     now = osi_Time();
+
+    lock_ObtainWrite(&smb_rctLock);
+    osi_assert(unp->refCount-- > 0);
+    if (unp->refCount == 0 && !(unp->flags & SMB_USERNAMEFLAG_AFSLOGON) &&
+       (unp->flags & SMB_USERNAMEFLAG_LOGOFF)) {
+        lupp = &usernamesp;
+        for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
+            if (up == unp) 
+                break;
+        }
+        osi_assert(up != NULL);
+        *lupp = up->nextp;
+       up->nextp = NULL;                       /* do not remove this */
+        lock_FinalizeMutex(&unp->mx);
+       userp = unp->userp;
+       free(unp->name);
+       free(unp->machine);
+       free(unp);
+    }          
+    lock_ReleaseWrite(&smb_rctLock);
+
+    if (userp) {
+        cm_ReleaseUser(userp);
+    }  
+}      
+
+void smb_HoldUIDNoLock(smb_user_t *uidp)
+{
+    uidp->refCount++;
+}
+
 void smb_ReleaseUID(smb_user_t *uidp)
 {
     smb_user_t *up;
     smb_user_t **lupp;
-    cm_user_t *userp;
+    smb_username_t *unp = NULL;
 
-    userp = NULL;
     lock_ObtainWrite(&smb_rctLock);
     osi_assert(uidp->refCount-- > 0);
-    if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
+    if (uidp->refCount == 0) {
         lupp = &uidp->vcp->usersp;
         for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
             if (up == uidp) 
@@ -1064,43 +1265,56 @@ void smb_ReleaseUID(smb_user_t *uidp)
         osi_assert(up != NULL);
         *lupp = up->nextp;
         lock_FinalizeMutex(&uidp->mx);
-        if (uidp->unp) {
-            userp = uidp->unp->userp;   /* avoid deadlock by releasing */
-            uidp->unp->userp = NULL;    /* after releasing the lock */
-        }       
+       unp = uidp->unp;
         smb_ReleaseVCNoLock(uidp->vcp);
-        uidp->vcp = NULL;
+       uidp->vcp = NULL;
+       free(uidp);
     }          
     lock_ReleaseWrite(&smb_rctLock);
-    if (userp) {
-        cm_ReleaseUserVCRef(userp);
-        cm_ReleaseUser(userp);
-    }  
+
+    if (unp) {
+       if (unp->userp)
+           cm_ReleaseUserVCRef(unp->userp);
+       smb_ReleaseUsername(unp);
+    }
 }      
 
+cm_user_t *smb_GetUserFromUID(smb_user_t *uidp)
+{
+    cm_user_t *up = NULL;
+
+    if (!uidp)
+       return NULL;
+    
+    lock_ObtainMutex(&uidp->mx);
+    if (uidp->unp) {
+       up = uidp->unp->userp;
+       cm_HoldUser(up);
+    }
+    lock_ReleaseMutex(&uidp->mx);
+
+    return up;
+}
+
 
 /* retrieve a held reference to a user structure corresponding to an incoming
  * request.
  * corresponding release function is cm_ReleaseUser.
  */
-cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp)
+cm_user_t *smb_GetUserFromVCP(smb_vc_t *vcp, smb_packet_t *inp)
 {
     smb_user_t *uidp;
-    cm_user_t *up;
+    cm_user_t *up = NULL;
     smb_t *smbp;
 
     smbp = (smb_t *) inp;
     uidp = smb_FindUID(vcp, smbp->uid, 0);
-    if ((!uidp) ||  (!uidp->unp))
-        return NULL;
-
-    lock_ObtainMutex(&uidp->mx);
-    up = uidp->unp->userp;
-    cm_HoldUser(up);
-    lock_ReleaseMutex(&uidp->mx);
+    if (!uidp)
+       return NULL;
+    
+    up = smb_GetUserFromUID(uidp);
 
     smb_ReleaseUID(uidp);
-
     return up;
 }
 
@@ -1170,8 +1384,11 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
         if (fid == fidp->fid) {
             if (newFid) {
                 fid++;
-                if (fid == 0) 
+                if (fid == 0xFFFF) {
+                    osi_Log1(smb_logp,
+                             "New FID number wraps on vcp 0x%x", vcp);
                     fid = 1;
+                }
                 goto retry;
             }
             fidp->refCount++;
@@ -1188,8 +1405,10 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
             osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
             thrd_CloseHandle(event);
             fid++;
-            if (fid == 0)
+            if (fid == 0xFFFF) {
+                osi_Log1(smb_logp, "New FID wraps around for vcp 0x%x", vcp);
                 fid = 1;
+            }
             goto retry;
         }
 
@@ -1205,34 +1424,43 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
         fidp->raw_write_event = event;
         if (newFid) {
             vcp->fidCounter = fid+1;
-            if (vcp->fidCounter == 0) 
+            if (vcp->fidCounter == 0xFFFF) {
+               osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x",
+                        vcp);
                 vcp->fidCounter = 1;
-        }
+           }
+       }
     }
 
     lock_ReleaseWrite(&smb_rctLock);
     return fidp;
 }
 
+void smb_HoldFIDNoLock(smb_fid_t *fidp)
+{
+    fidp->refCount++;
+}
+
 void smb_ReleaseFID(smb_fid_t *fidp)
 {
-    cm_scache_t *scp;
+    cm_scache_t *scp = NULL;
+    cm_user_t *userp = NULL;
     smb_vc_t *vcp = NULL;
     smb_ioctl_t *ioctlp;
 
-    if (!fidp)
-        return;
-
-    scp = NULL;
     lock_ObtainWrite(&smb_rctLock);
     osi_assert(fidp->refCount-- > 0);
-    if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->refCount == 0 && (fidp->delete)) {
         vcp = fidp->vcp;
-        fidp->vcp = 0;
+        fidp->vcp = NULL;
         scp = fidp->scp;    /* release after lock is released */
-        fidp->scp = 0;
+        fidp->scp = NULL;
+        userp = fidp->userp;
+        fidp->userp = NULL;
 
-        osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
+       if (vcp->fidsp) 
+           osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
         thrd_CloseHandle(fidp->raw_write_event);
 
         /* and see if there is ioctl stuff to free */
@@ -1246,16 +1474,23 @@ void smb_ReleaseFID(smb_fid_t *fidp)
                 free(ioctlp->outAllocp);
             free(ioctlp);
         }       
-
+       lock_ReleaseMutex(&fidp->mx);
+       lock_FinalizeMutex(&fidp->mx);
         free(fidp);
 
-        smb_ReleaseVCNoLock(vcp);
+       if (vcp)
+           smb_ReleaseVCNoLock(vcp);
+    } else {
+       lock_ReleaseMutex(&fidp->mx);
     }
     lock_ReleaseWrite(&smb_rctLock);
 
     /* now release the scache structure */
     if (scp) 
         cm_ReleaseSCache(scp);
+
+    if (userp)
+        cm_ReleaseUser(userp);
 }       
 
 /*
@@ -1733,7 +1968,9 @@ void smb_GCDirSearches(int isV3)
          */
         if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
             /* hold and delete */
+           lock_ObtainMutex(&tp->mx);
             tp->flags |= SMB_DIRSEARCH_DELETE;
+           lock_ReleaseMutex(&tp->mx);
             victimsp[victimCount++] = tp;
             tp->refCount++;
         }
@@ -1877,9 +2114,9 @@ smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
     smb_packet_t *tbp;
     tbp = GetPacket();
     memcpy(tbp, pkt, sizeof(smb_packet_t));
-    tbp->wctp = tbp->data + ((unsigned int)pkt->wctp - (unsigned int)pkt->data);
-       if (tbp->vcp)
-               smb_HoldVC(tbp->vcp);
+    tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
+    if (tbp->vcp)
+       smb_HoldVC(tbp->vcp);
     return tbp;
 }
 
@@ -2012,22 +2249,16 @@ 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];
-        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);
-#endif
-        osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
+       char s[100];
+
+       sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
+                parm, parmCount, smbp->ncb_length);
+       osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
                  parm, parmCount, smbp->ncb_length);
+#ifndef DJGPP
+       LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM, 
+                __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
+#endif /* !DJGPP */
         osi_panic(s, __FILE__, __LINE__);
     }
     parmDatap = smbp->wctp + (2*parm) + 1;
@@ -2045,19 +2276,13 @@ unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
 
     if (parm * 2 + offset >= parmCount * 2) {
         char s[100];
-#ifndef DJGPP
-        HANDLE h;
-        char *ptbuf[1];
-        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);
 #ifndef DJGPP
-        ptbuf[0] = s;
-        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
-                    1, smbp->ncb_length, ptbuf, smbp);
-        DeregisterEventSource(h);
-#endif
+       LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM_WITH_OFFSET, 
+                __FILE__, __LINE__, parm, offset, parmCount, smbp->ncb_length);
+#endif /* !DJGPP */
         osi_Log4(smb_logp, "Bad SMB param %d offset %d out of %d, ncb len %d",
                 parm, offset, parmCount, smbp->ncb_length);
         osi_panic(s, __FILE__, __LINE__);
@@ -2238,7 +2463,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
     extra = 2 * (*inp->wctp);  /* space used by parms, in bytes */
     tp = inp->wctp + 1+ extra; /* points to count of data bytes */
     extra += tp[0] + (tp[1]<<8);
-    extra += ((unsigned int)inp->wctp - (unsigned int)inp->data);      /* distance to last wct field */
+    extra += (unsigned int)(inp->wctp - inp->data);    /* distance to last wct field */
     extra += 3;                        /* wct and length fields */
         
     ncbp->ncb_length = extra;  /* bytes to send */
@@ -2258,49 +2483,22 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
 #endif /* !DJGPP */
         
     if (code != 0) {
-        char * s;
-        switch ( code ) {
-        case 0x01: s = "llegal buffer length                     "; break; 
-        case 0x03: s = "illegal command                          "; break; 
-        case 0x05: s = "command timed out                        "; break; 
-        case 0x06: s = "message incomplete, issue another command"; break; 
-        case 0x07: s = "illegal buffer address                   "; break; 
-        case 0x08: s = "session number out of range              "; break; 
-        case 0x09: s = "no resource available                    "; break; 
-        case 0x0a: s = "session closed                           "; break; 
-        case 0x0b: s = "command cancelled                        "; break; 
-        case 0x0d: s = "duplicate name                           "; break; 
-        case 0x0e: s = "name table full                          "; break; 
-        case 0x0f: s = "no deletions, name has active sessions   "; break; 
-        case 0x11: s = "local session table full                 "; break; 
-        case 0x12: s = "remote session table full                "; break; 
-        case 0x13: s = "illegal name number                      "; break; 
-        case 0x14: s = "no callname                              "; break; 
-        case 0x15: s = "cannot put * in NCB_NAME                 "; break; 
-        case 0x16: s = "name in use on remote adapter            "; break; 
-        case 0x17: s = "name deleted                             "; break; 
-        case 0x18: s = "session ended abnormally                 "; break; 
-        case 0x19: s = "name conflict detected                   "; break; 
-        case 0x21: s = "interface busy, IRET before retrying     "; break; 
-        case 0x22: s = "too many commands outstanding, retry later"; break;
-        case 0x23: s = "ncb_lana_num field invalid               "; break; 
-        case 0x24: s = "command completed while cancel occurring "; break; 
-        case 0x26: s = "command not valid to cancel              "; break; 
-        case 0x30: s = "name defined by anther local process     "; break; 
-        case 0x34: s = "environment undefined. RESET required    "; break; 
-        case 0x35: s = "required OS resources exhausted          "; break; 
-        case 0x36: s = "max number of applications exceeded      "; break; 
-        case 0x37: s = "no saps available for netbios            "; break; 
-        case 0x38: s = "requested resources are not available    "; break; 
-        case 0x39: s = "invalid ncb address or length > segment  "; break; 
-        case 0x3B: s = "invalid NCB DDID                         "; break; 
-        case 0x3C: s = "lock of user area failed                 "; break; 
-        case 0x3f: s = "NETBIOS not loaded                       "; break; 
-        case 0x40: s = "system error                             "; break;                 
-        default:
-            s = "unknown error";
-        }
+       const char * s = ncb_error_string(code);
         osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
+#ifndef DJGPP
+       LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_SEND_PACKET_FAILURE, s);
+#endif /* !DJGPP */
+
+       osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+                vcp, vcp->usersp);
+
+       lock_ObtainMutex(&vcp->mx);
+       vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+       lock_ReleaseMutex(&vcp->mx);
+       lock_ObtainWrite(&smb_globalLock);
+       dead_sessions[vcp->session] = TRUE;
+       lock_ReleaseWrite(&smb_globalLock);
+       smb_CleanupDeadVC(vcp);
     }
 
     if (localNCB)
@@ -2739,8 +2937,10 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     if (!rawBuf)
         goto send1a;
 
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL)
     {
+       lock_ReleaseMutex(&fidp->mx);
 #ifndef DJGPP
         rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
 #else
@@ -2762,8 +2962,9 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         smb_ReleaseFID(fidp);
         return rc;
     }
-        
-    userp = smb_GetUser(vcp, inp);
+    lock_ReleaseMutex(&fidp->mx);
+
+    userp = smb_GetUserFromVCP(vcp, inp);
 
 #ifndef DJGPP
     code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
@@ -2853,26 +3054,6 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     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(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;
-            }
-        }
-    }
-
-    inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
 
     namep = smb_GetSMBData(inp, &dbytes);
     namex = 0;
@@ -2899,7 +3080,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         }
 
         /* compute size of protocol entry */
-        entryLength = strlen(namep+1);
+        entryLength = (int)strlen(namep+1);
         entryLength += 2;      /* 0x02 bytes and null termination */
 
         /* advance over this protocol entry */
@@ -2908,6 +3089,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         tcounter++;            /* which proto entry we're looking at */
     }
 
+    lock_ObtainMutex(&vcp->mx);
     if (NTProtoIndex != -1) {
         protoIndex = NTProtoIndex;
         vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
@@ -2921,6 +3103,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         vcp->flags |= SMB_VCFLAG_USECORE;
     }  
     else protoIndex = -1;
+    lock_ReleaseMutex(&vcp->mx);
 
     if (protoIndex == -1)
         return CM_ERROR_INVAL;
@@ -3063,9 +3246,53 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     return 0;
 }
 
+void smb_CheckVCs(void)
+{
+    smb_vc_t * vcp, *nextp;
+    smb_packet_t * outp = GetPacket();
+    smb_t *smbp;
+            
+    lock_ObtainWrite(&smb_rctLock);
+    for ( vcp=smb_allVCsp, nextp=NULL; vcp; vcp = nextp ) 
+    {
+       nextp = vcp->nextp;
+
+       if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
+           continue;
+
+       smb_HoldVCNoLock(vcp);
+       if (nextp)
+           smb_HoldVCNoLock(nextp);
+       smb_FormatResponsePacket(vcp, NULL, outp);
+        smbp = (smb_t *)outp;
+       outp->inCom = smbp->com = 0x2b /* Echo */;
+        smbp->tid = 0xFFFF;
+        smbp->pid = 0;
+        smbp->uid = 0;
+        smbp->mid = 0;
+        smbp->res[0] = 0;
+        smbp->res[1] = 0;
+
+       smb_SetSMBParm(outp, 0, 0);
+       smb_SetSMBDataLength(outp, 0);
+       lock_ReleaseWrite(&smb_rctLock);
+
+       smb_SendPacket(vcp, outp);
+
+       lock_ObtainWrite(&smb_rctLock);
+       smb_ReleaseVCNoLock(vcp);
+       if (nextp)
+           smb_ReleaseVCNoLock(nextp);
+    }
+    lock_ReleaseWrite(&smb_rctLock);
+    smb_FreePacket(outp);
+}
+
 void smb_Daemon(void *parmp)
 {
     afs_uint32 count = 0;
+    smb_username_t    **unpp;
+    time_t             now;
 
     while(smbShutdownFlag == 0) {
         count++;
@@ -3095,7 +3322,49 @@ void smb_Daemon(void *parmp)
             if ( smb_localZero != old_localZero )
                 cm_noteLocalMountPointChange();
 #endif
-        }
+
+           smb_CheckVCs();
+       }
+
+       /* GC smb_username_t objects that will no longer be used */
+       now = osi_Time();
+       lock_ObtainWrite(&smb_rctLock);
+       for ( unpp=&usernamesp; *unpp; ) {
+           int delete = 0;
+           smb_username_t *unp;
+
+           lock_ObtainMutex(&(*unpp)->mx);
+           if ( (*unpp)->refCount > 0 || 
+                ((*unpp)->flags & SMB_USERNAMEFLAG_AFSLOGON) || 
+                !((*unpp)->flags & SMB_USERNAMEFLAG_LOGOFF))
+               ;
+           else if (!smb_LogoffTokenTransfer ||
+                    ((*unpp)->last_logoff_t + smb_LogoffTransferTimeout < now))
+               delete = 1;
+           lock_ReleaseMutex(&(*unpp)->mx);
+
+           if (delete) {
+               cm_user_t * userp;
+
+               unp = *unpp;    
+               *unpp = unp->nextp;
+               unp->nextp = NULL;
+               lock_FinalizeMutex(&unp->mx);
+               userp = unp->userp;
+               free(unp->name);
+               free(unp->machine);
+               free(unp);
+               if (userp) {
+                   lock_ReleaseWrite(&smb_rctLock);
+                   cm_ReleaseUser(userp);
+                   lock_ObtainWrite(&smb_rctLock);
+               }
+           } else {
+               unpp = &(*unpp)->nextp;
+           }
+       }
+       lock_ReleaseWrite(&smb_rctLock);
+
         /* XXX GC dir search entries */
     }
 }
@@ -3114,11 +3383,13 @@ void smb_WaitingLocksDaemon()
         lock_ObtainWrite(&smb_globalLock);
         nwlRequest = smb_allWaitingLocks;
         if (nwlRequest == NULL) {
-            osi_SleepW((long)&smb_allWaitingLocks, &smb_globalLock);
+            osi_SleepW((LONG_PTR)&smb_allWaitingLocks, &smb_globalLock);
             thrd_Sleep(1000);
             continue;
-        } else 
+        } else {
             first = 1;
+            osi_Log0(smb_logp, "smb_WaitingLocksDaemon starting wait lock check");
+        }
 
         do {
             if (first)
@@ -3126,6 +3397,8 @@ void smb_WaitingLocksDaemon()
             else
                 lock_ObtainWrite(&smb_globalLock);
 
+            osi_Log1(smb_logp, "    Checking waiting lock request %p", nwlRequest);
+
             wlRequest = nwlRequest;
             nwlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q);
             lock_ReleaseWrite(&smb_globalLock);
@@ -3135,6 +3408,8 @@ void smb_WaitingLocksDaemon()
             for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
                 if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
                     continue;
+
+                osi_assert(wl->state != SMB_WAITINGLOCKSTATE_ERROR);
                 
                 /* wl->state is either _DONE or _WAITING.  _ERROR
                    would no longer be on the queue. */
@@ -3165,6 +3440,9 @@ void smb_WaitingLocksDaemon()
                 cm_scache_t * scp;
                 cm_req_t req;
 
+                osi_Log1(smb_logp, "smb_WaitingLocksDaemon discarding lock req %p",
+                         wlRequest);
+
                 scp = wlRequest->scp;
 
                 cm_InitReq(&req);
@@ -3185,6 +3463,10 @@ void smb_WaitingLocksDaemon()
                 lock_ReleaseMutex(&scp->mx);
 
             } else {
+
+                osi_Log1(smb_logp, "smb_WaitingLocksDaemon granting lock req %p",
+                         wlRequest);
+
                 for (wl = wlRequest->locks; wl; wl = wlNext) {
                     wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
                     osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
@@ -3265,14 +3547,13 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         return CM_ERROR_BADSMB;
     strcpy(shareName, tp+1);
 
-    userp = smb_GetUser(vcp, inp);
-
     lock_ObtainMutex(&vcp->mx);
     newTid = vcp->tidCounter++;
     lock_ReleaseMutex(&vcp->mx);
 
     tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
     uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+    userp = smb_GetUserFromUID(uidp);
     shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
     if (uidp)
         smb_ReleaseUID(uidp);
@@ -3691,7 +3972,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     osi_Log3(smb_logp, "SMB search dir cookie 0x%x, connection %d, attr 0x%x",
              nextCookie, dsp->cookie, attribute);
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     /* try to get the vnode for the path name next */
     lock_ObtainMutex(&dsp->mx);
@@ -3846,7 +4127,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                      LargeIntegerGreaterThanOrEqualTo(thyper, 
                                                       scp->bulkStatProgress)) {
                     /* Don't bulk stat if risking timeout */
-                    int now = GetCurrentTime();
+                    int now = GetTickCount();
                     if (now - req.startTime > 5000) {
                         scp->bulkStatProgress = thyper;
                         scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
@@ -3981,10 +4262,10 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
             *op++ = resByte;
             memcpy(op, mask, 11); op += 11;
             *op++ = (char) dsp->cookie;        /* they say it must be non-zero */
-            *op++ = nextEntryCookie & 0xff;
-            *op++ = (nextEntryCookie>>8) & 0xff;
-            *op++ = (nextEntryCookie>>16) & 0xff;
-            *op++ = (nextEntryCookie>>24) & 0xff;
+            *op++ = (char)(nextEntryCookie & 0xff);
+            *op++ = (char)((nextEntryCookie>>8) & 0xff);
+            *op++ = (char)((nextEntryCookie>>16) & 0xff);
+            *op++ = (char)((nextEntryCookie>>24) & 0xff);
             memcpy(op, &clientCookie, 4); op += 4;
 
             /* now we emit the attribute.  This is sort of tricky,
@@ -4085,8 +4366,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
      */
     temp -= 3;         /* deduct vbl block info */
     osi_assert(temp == (43 * returnedNames));
-    origOp[1] = temp & 0xff;
-    origOp[2] = (temp>>8) & 0xff;
+    origOp[1] = (char)(temp & 0xff);
+    origOp[2] = (char)((temp>>8) & 0xff);
     if (returnedNames == 0) 
         smb_DeleteDirSearch(dsp);
     smb_ReleaseDirSearch(dsp);
@@ -4123,7 +4404,7 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         
     rootScp = cm_data.rootSCachep;
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -4207,7 +4488,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 
     rootScp = cm_data.rootSCachep;
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -4320,7 +4601,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 
     rootScp = cm_data.rootSCachep;
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     /* we shouldn't need this for V3 requests, but we seem to */
     caseFold = CM_FLAG_CASEFOLD;
@@ -4456,9 +4737,9 @@ long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_
     /* find the tree and free it */
     tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
     if (tidp) {
-        lock_ObtainMutex(&tidp->mx);
-        tidp->flags |= SMB_TIDFLAG_DELETE;
-        lock_ReleaseMutex(&tidp->mx);
+       lock_ObtainWrite(&smb_rctLock);
+        tidp->delete = 1;
+        lock_ReleaseWrite(&smb_rctLock);
         smb_ReleaseTID(tidp);
     }
 
@@ -4524,7 +4805,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         return 0;
     }
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -4574,13 +4855,18 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     /* save a pointer to the vnode */
     fidp->scp = scp;
+    /* and the user */
+    cm_HoldUser(userp);
+    fidp->userp = userp;
 
+    lock_ObtainMutex(&fidp->mx);
     if ((share & 0xf) == 0)
         fidp->flags |= SMB_FID_OPENREAD;
     else if ((share & 0xf) == 1)
         fidp->flags |= SMB_FID_OPENWRITE;
     else 
         fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
+    lock_ReleaseMutex(&fidp->mx);
 
     lock_ObtainMutex(&scp->mx);
     smb_SetSMBParm(outp, 0, fidp->fid);
@@ -4692,7 +4978,7 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
 
@@ -4831,7 +5117,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     DWORD filter;
     cm_req_t req;
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
     if (code) {
         cm_ReleaseUser(userp);
@@ -5009,7 +5295,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
     DWORD filter;
     cm_req_t req;
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
     if (code) {
@@ -5239,7 +5525,7 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -5316,13 +5602,18 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     fid = smb_ChainFID(fid, inp);
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
-        if (fidp)
-            smb_ReleaseFID(fidp);
+    if (!fidp)
+       return CM_ERROR_BADFD;
+    
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_IOCTL) {
+       lock_ReleaseMutex(&fidp->mx);
+       smb_ReleaseFID(fidp);
         return CM_ERROR_BADFD;
     }
+    lock_ReleaseMutex(&fidp->mx);
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_OPENWRITE)
@@ -5385,32 +5676,41 @@ void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp,
         *newPathp = strdup(pathp);
 }
 
-long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
-{
-    unsigned short fid;
-    smb_fid_t *fidp;
-    cm_user_t *userp;
-    afs_uint32 dosTime;
+long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
+                  afs_uint32 dosTime) {
     long code = 0;
     cm_req_t req;
+    cm_scache_t *dscp = fidp->NTopen_dscp;
+    char *pathp = fidp->NTopen_pathp;
+
+    osi_Log3(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d vcp=0x%x)",
+             fidp, fidp->fid, vcp);
+
+    if (!userp) {
+       lock_ObtainMutex(&fidp->mx);
+        if (!fidp->userp && !(fidp->flags & SMB_FID_IOCTL)) {
+           lock_ReleaseMutex(&fidp->mx);
+            osi_Log0(smb_logp, "  No user specified.  Not closing fid");
+           return CM_ERROR_BADFD;
+       }
+        
+        userp = fidp->userp;    /* no hold required since fidp is held
+                                   throughout the function */
+       lock_ReleaseMutex(&fidp->mx);
+    }
 
     cm_InitReq(&req);
 
-    fid = smb_GetSMBParm(inp, 0);
-    dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
-
-    osi_Log1(smb_logp, "SMB close fid %d", fid);
-
-    fid = smb_ChainFID(fid, inp);
-    fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp) {
-        return CM_ERROR_BADFD;
+    lock_ObtainWrite(&smb_rctLock);
+    if (fidp->delete) {
+       osi_Log0(smb_logp, "  Fid already closed.");
+       lock_ReleaseWrite(&smb_rctLock);
+       return CM_ERROR_BADFD;
     }
-        
-    userp = smb_GetUser(vcp, inp);
+    fidp->delete = 1;
+    lock_ReleaseWrite(&smb_rctLock);
 
     lock_ObtainMutex(&fidp->mx);
-
     /* Don't jump the gun on an async raw write */
     while (fidp->raw_writers) {
         lock_ReleaseMutex(&fidp->mx);
@@ -5418,8 +5718,6 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         lock_ObtainMutex(&fidp->mx);
     }
 
-    fidp->flags |= SMB_FID_DELETE;
-        
     /* watch for ioctl closes, and read-only opens */
     if (fidp->scp != NULL &&
         (fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
@@ -5439,12 +5737,12 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (!(fidp->flags & SMB_FID_IOCTL) && fidp->scp &&
         fidp->scp->fileType == CM_SCACHETYPE_FILE) {
         cm_key_t key;
-        unsigned pid;
         cm_scache_t * scp;
         long tcode;
 
-        pid = ((smb_t *) inp)->pid;
-        key = cm_GenerateKey(vcp->vcID, pid, fid);
+        /* CM_UNLOCK_BY_FID doesn't look at the process ID.  We pass
+           in zero. */
+        key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
         scp = fidp->scp;
         cm_HoldSCache(scp);
         lock_ObtainMutex(&scp->mx);
@@ -5455,7 +5753,8 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                           | CM_SCACHESYNC_LOCK);
 
         if (tcode) {
-            osi_Log1(smb_logp, "smb CoreClose SyncOp failure code 0x%x", tcode);
+            osi_Log1(smb_logp,
+                     "smb CoreClose SyncOp failure code 0x%x", tcode);
             goto post_syncopdone;
         }
 
@@ -5470,8 +5769,6 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     }
 
     if (fidp->flags & SMB_FID_DELONCLOSE) {
-        cm_scache_t *dscp = fidp->NTopen_dscp;
-        char *pathp = fidp->NTopen_pathp;
         char *fullPathp;
 
         smb_FullName(dscp, fidp->scp, pathp, &fullPathp, userp, &req);
@@ -5481,9 +5778,7 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 smb_NotifyChange(FILE_ACTION_REMOVED,
                                  FILE_NOTIFY_CHANGE_DIR_NAME,
                                  dscp, fullPathp, NULL, TRUE);
-        }
-        else 
-        {
+        } else {
             code = cm_Unlink(dscp, fullPathp, userp, &req);
             if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                 smb_NotifyChange(FILE_ACTION_REMOVED,
@@ -5491,15 +5786,51 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                                  dscp, fullPathp, NULL, TRUE);
         }
         free(fullPathp);
+       fidp->flags &= ~SMB_FID_DELONCLOSE;
     }
-    lock_ReleaseMutex(&fidp->mx);
 
     if (fidp->flags & SMB_FID_NTOPEN) {
-        cm_ReleaseSCache(fidp->NTopen_dscp);
-        free(fidp->NTopen_pathp);
+       fidp->NTopen_dscp = NULL;
+        fidp->NTopen_pathp = NULL;
+       fidp->flags &= ~SMB_FID_NTOPEN;
     }
-    if (fidp->NTopen_wholepathp)
+    if (fidp->NTopen_wholepathp) {
         free(fidp->NTopen_wholepathp);
+        fidp->NTopen_wholepathp = NULL;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+
+    if (dscp)
+       cm_ReleaseSCache(dscp);
+
+    if (pathp)
+       free(pathp);
+
+    return code;
+}
+
+long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+    unsigned short fid;
+    smb_fid_t *fidp;
+    cm_user_t *userp;
+    long code = 0;
+    afs_uint32 dosTime;
+
+    fid = smb_GetSMBParm(inp, 0);
+    dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
+
+    osi_Log1(smb_logp, "SMB ReceiveCoreClose fid %d", fid);
+
+    fid = smb_ChainFID(fid, inp);
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp) {
+        return CM_ERROR_BADFD;
+    }
+        
+    userp = smb_GetUserFromVCP(vcp, inp);
+
+    code = smb_CloseFID(vcp, fidp, userp, dosTime);
     
     smb_ReleaseFID(fidp);
     cm_ReleaseUser(userp);
@@ -5713,6 +6044,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
         
     /* make sure we have a writable FD */
     if (!(fidp->flags & SMB_FID_OPENWRITE)) {
+       lock_ReleaseMutex(&fidp->mx);
         code = CM_ERROR_BADFDOP;
         goto done;
     }
@@ -5759,7 +6091,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
         /* handle over quota or out of space */
         if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) {
             *writtenp = written;
-            code = CM_ERROR_QUOTA;
+            code = (scp->flags & CM_SCACHEFLAG_OVERQUOTA) ? CM_ERROR_QUOTA : CM_ERROR_SPACE;
             break;
         }
 
@@ -5877,7 +6209,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
   done:
     lock_ReleaseMutex(&scp->mx);
-    lock_ReleaseMutex(&fidp->mx);
+
     if (bufferp) {
         lock_ReleaseMutex(&bufferp->mx);
         buf_Release(bufferp);
@@ -5889,6 +6221,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                           fidp->NTopen_dscp, fidp->NTopen_pathp,
                           NULL, TRUE);
     }       
+    lock_ReleaseMutex(&fidp->mx);
 
     if (code == 0 && doWriteBack) {
         long code2;
@@ -5934,14 +6267,18 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
-    if (!fidp) {
+    if (!fidp)
         return CM_ERROR_BADFD;
-    }
-        
-    if (fidp->flags & SMB_FID_IOCTL)
-        return smb_IoctlWrite(fidp, vcp, inp, outp);
         
-    userp = smb_GetUser(vcp, inp);
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_IOCTL) {
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_IoctlWrite(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     /* special case: 0 bytes transferred means truncate to this position */
     if (count == 0) {
@@ -5954,10 +6291,10 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         truncAttr.length.HighPart = 0;
         lock_ObtainMutex(&fidp->mx);
         code = cm_SetAttr(fidp->scp, &truncAttr, userp, &req);
+       fidp->flags |= SMB_FID_LENGTHSETDONE;
         lock_ReleaseMutex(&fidp->mx);
         smb_SetSMBParm(outp, 0, /* count */ 0);
         smb_SetSMBDataLength(outp, 0);
-        fidp->flags |= SMB_FID_LENGTHSETDONE;
         goto done;
     }
 
@@ -5992,10 +6329,12 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
      * and don't set client mod time if we think that would go against the
      * intention.
      */
+    lock_ObtainMutex(&fidp->mx);
     if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
         fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
         fidp->scp->clientModTime = time(NULL);
     }
+    lock_ReleaseMutex(&fidp->mx);
 
     code = 0;
     while ( code == 0 && count > 0 ) {
@@ -6046,7 +6385,7 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
     osi_Log2(smb_logp, "Completing Raw Write offset %x count %x",
              rwcp->offset.LowPart, rwcp->count);
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
 #ifndef DJGPP
     rawBuf = rwcp->buf;
@@ -6158,7 +6497,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         }
     }
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     /*
      * Work around bug in NT client
@@ -6170,10 +6509,12 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
      * and don't set client mod time if we think that would go against the
      * intention.
      */
+    lock_ObtainMutex(&fidp->mx);
     if ((fidp->flags & SMB_FID_LOOKSLIKECOPY) != SMB_FID_LOOKSLIKECOPY) {
         fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
         fidp->scp->clientModTime = time(NULL);
     }
+    lock_ReleaseMutex(&fidp->mx);
 
     code = 0;
     while ( code == 0 && count > 0 ) {
@@ -6267,13 +6608,17 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
-    if (!fidp) {
+    if (!fidp)
         return CM_ERROR_BADFD;
-    }
         
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL) {
-        return smb_IoctlRead(fidp, vcp, inp, outp);
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_IoctlRead(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
     }
+    lock_ReleaseMutex(&fidp->mx);
 
     {
         LARGE_INTEGER LOffset, LLength;
@@ -6296,7 +6641,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         return code;
     }
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     /* remember this for final results */
     smb_SetSMBParm(outp, 0, count);
@@ -6370,7 +6715,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -6494,7 +6839,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -6615,19 +6960,24 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
        
-    /* save a pointer to the vnode */
-    fidp->scp = scp;
-        
+    cm_HoldUser(userp);
+
+    lock_ObtainMutex(&fidp->mx);
     /* always create it open for read/write */
     fidp->flags |= (SMB_FID_OPENREAD | SMB_FID_OPENWRITE);
 
-    smb_ReleaseFID(fidp);
-        
+    /* save a pointer to the vnode */
+    fidp->scp = scp;
+    /* and the user */
+    fidp->userp = userp;
+    lock_ReleaseMutex(&fidp->mx);
+
     smb_SetSMBParm(outp, 0, fidp->fid);
     smb_SetSMBDataLength(outp, 0);
 
     cm_Open(scp, 0, userp);
 
+    smb_ReleaseFID(fidp);
     cm_ReleaseUser(userp);
     /* leave scp held since we put it in fidp->scp */
     return 0;
@@ -6653,11 +7003,19 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* try to find the file descriptor */
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
-    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+
+    if (!fidp)
+       return CM_ERROR_BADFD;
+    
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_IOCTL) {
+       lock_ReleaseMutex(&fidp->mx);
+       smb_ReleaseFID(fidp);
         return CM_ERROR_BADFD;
     }
+    lock_ReleaseMutex(&fidp->mx);
        
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     lock_ObtainMutex(&fidp->mx);
     scp = fidp->scp;
@@ -6723,18 +7081,10 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
     if (ncbp->ncb_length < offsetof(struct smb, vdata)) {
         /* log it and discard it */
 #ifndef DJGPP
-        HANDLE h;
-        char *ptbuf[1];
-        char s[100];
-        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-        sprintf(s, "SMB message too short, len %d", ncbp->ncb_length);
-        ptbuf[0] = s;
-        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1007, NULL,
-                     1, ncbp->ncb_length, ptbuf, inp);
-        DeregisterEventSource(h);
-#else /* DJGPP */
-        osi_Log1(smb_logp, "SMB message too short, len %d", ncbp->ncb_length);
+       LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_TOO_SHORT, 
+                __FILE__, __LINE__, ncbp->ncb_length);
 #endif /* !DJGPP */
+       osi_Log1(smb_logp, "SMB message too short, len %d", ncbp->ncb_length);
         return;
     }
 
@@ -6748,7 +7098,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
 
     /* Remember session generation number and time */
     oldGen = sessionGen;
-    oldTime = GetCurrentTime();
+    oldTime = GetTickCount();
 
     while (inp->inCom != 0xff) {
         dp = &smb_dispatchTable[inp->inCom];
@@ -6792,14 +7142,11 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
 
             if (inp->inCom == 0x1d)
                 /* Raw Write */
-                code = smb_ReceiveCoreWriteRaw (vcp, inp, outp,
-                                                 rwcp);
+                code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, rwcp);
             else {
-                osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp 0x%x lana %d lsn %d",(int)vcp,vcp->lana,vcp->lsn);
-                osi_Log4(smb_logp,"Dispatch %s vcp 0x%x lana %d lsn %d",myCrt_Dispatch(inp->inCom),vcp,vcp->lana,vcp->lsn);
+                osi_Log4(smb_logp,"Dispatch %s vcp 0x%p 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 0x%x",(code==0)?0:code-CM_ERROR_BASE);
-                osi_Log4(smb_logp,"Dispatch return  code 0x%x vcp 0x%x lana %d lsn %d",(code==0)?0:code-CM_ERROR_BASE,vcp,vcp->lana,vcp->lsn);
+                osi_Log4(smb_logp,"Dispatch return  code 0x%x vcp 0x%p lana %d lsn %d",code,vcp,vcp->lana,vcp->lsn);
 #ifdef LOG_PACKET
                 if ( code == CM_ERROR_BADSMB ||
                      code == CM_ERROR_BADOP )
@@ -6808,21 +7155,13 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
             }   
 
             if (oldGen != sessionGen) {
+                newTime = GetTickCount();
 #ifndef DJGPP
-                HANDLE h;
-                char *ptbuf[1];
-                char s[100];
-                newTime = GetCurrentTime();
-                h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-                sprintf(s, "Pkt straddled session startup, took %d ms, ncb length %d",
-                         newTime - oldTime, ncbp->ncb_length);
-                ptbuf[0] = s;
-                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0,
-                             1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp);
-                DeregisterEventSource(h);
+               LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION, 
+                        newTime - oldTime, ncbp->ncb_length);
 #endif /* !DJGPP */
-                osi_Log1(smb_logp, "Pkt straddled session startup, "
-                          "ncb length %d", ncbp->ncb_length);
+               osi_Log2(smb_logp, "Pkt straddled session startup, "
+                          "took %d ms, ncb length %d", newTime - oldTime, ncbp->ncb_length);
             }
         }
         else {
@@ -6847,25 +7186,12 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
         /* catastrophic failure:  log as much as possible */
         if (code == CM_ERROR_BADSMB) {
 #ifndef DJGPP
-            HANDLE h;
-            char *ptbuf[1];
-            char s[100];
-
-            osi_Log1(smb_logp,
-                      "Invalid SMB, ncb_length %d",
-                      ncbp->ncb_length);
-
-            h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-            sprintf(s, "Invalid SMB message, length %d",
-                     ncbp->ncb_length);
-            ptbuf[0] = s;
-            ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1002, NULL,
-                         1, ncbp->ncb_length, ptbuf, smbp);
-            DeregisterEventSource(h);
+           LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_INVALID, 
+                    ncbp->ncb_length);
+#endif /* !DJGPP */
 #ifdef LOG_PACKET
             smb_LogPacket(inp);
 #endif /* LOG_PACKET */
-#endif /* !DJGPP */
             osi_Log1(smb_logp, "Invalid SMB message, length %d",
                      ncbp->ncb_length);
 
@@ -6954,7 +7280,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
         /* tp now points to the new output record; go back and patch the
          * second parameter (off2) to point to the new record.
          */
-        temp = (unsigned int)tp - ((unsigned int) outp->data);
+        temp = (unsigned int)(tp - outp->data);
         outWctp[3] = (unsigned char) (temp & 0xff);
         outWctp[4] = (unsigned char) ((temp >> 8) & 0xff);
         outWctp[2] = 0;        /* padding */
@@ -6965,18 +7291,6 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
         outWctp = tp;
     }  /* while loop over all requests in the packet */
 
-    /* done logging out, turn off logging-out flag */
-    if (!(inp->flags & SMB_PACKETFLAG_PROFILE_UPDATE_OK)) {
-        vcp->justLoggedOut = NULL;
-        if (loggedOut) {
-            loggedOut = 0;
-            free(loggedOutName);
-            loggedOutName = NULL;
-            smb_ReleaseUID(loggedOutUserp);
-            loggedOutUserp = NULL;
-        }
-    }
     /* now send the output packet, and return */
     if (!noSend)
         smb_SendPacket(vcp, outp);
@@ -6985,19 +7299,22 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
     if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
         if (active_vcp != vcp) {
             if (active_vcp) {
-                smb_ReleaseVC(active_vcp);
                 osi_Log2(smb_logp,
                       "Replacing active_vcp %x with %x", active_vcp, vcp);
+                smb_ReleaseVC(active_vcp);
             }
             smb_HoldVC(vcp);
+           lock_ObtainWrite(&smb_globalLock);
             active_vcp = vcp;
+           lock_ReleaseWrite(&smb_globalLock);
         }
-        last_msg_time = GetCurrentTime();
-    } else if (active_vcp == vcp) {
+        last_msg_time = GetTickCount();
+    } else if (active_vcp == vcp) {    /* the vcp is dead */
         smb_ReleaseVC(active_vcp);
+       lock_ObtainWrite(&smb_globalLock);
         active_vcp = NULL;
+       lock_ReleaseWrite(&smb_globalLock);
     }
-
     return;
 }
 
@@ -7189,7 +7506,7 @@ void smb_ServerWaiter(void *parmp)
  */
 void smb_Server(VOID *parmp)
 {
-    int myIdx = (int) parmp;
+    INT_PTR myIdx = (INT_PTR) parmp;
     NCB *ncbp;
     NCB *outncbp;
     smb_packet_t *bufp;
@@ -7210,6 +7527,10 @@ void smb_Server(VOID *parmp)
     outbufp->ncbp = outncbp;
 
     while (1) {
+       if (vcp) {
+           smb_ReleaseVC(vcp);
+           vcp = NULL;
+       }
         code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
                                                  FALSE, INFINITE);
 
@@ -7262,127 +7583,12 @@ void smb_Server(VOID *parmp)
         idx_session = NCBsessions[idx_NCB];
         rc = ncbp->ncb_retcode;
 
-        if (rc != NRC_PENDING && rc != NRC_GOODRET) {
-            switch (rc) {
-            case 0x01:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: illegal buffer length", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x03:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: illegal command", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x05:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: command timed out", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x06:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: message incomplete, issue another command", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x07:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: illegal buffer address", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x08:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: session number out of range", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x09:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: no resource available", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x0a:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: session closed", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x0b:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: command cancelled", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x0d:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: duplicate name", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x0e:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name table full", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x0f:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: no deletions, name has active lsn %d sessions", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x11:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: local session table full", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x12:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: remote session table full", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x13:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: illegal name number", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x14:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: no callname", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x15:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: cannot put * in NCB_NAME", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x16:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name in use on remote adapter", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x17:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name deleted", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x18:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: session ended abnormally", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x19:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name conflict detected", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x21:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: interface busy, IRET before retrying", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x22:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: too many commands outstanding, retry later", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x23:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: ncb_lana_num field invalid", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x24:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: command completed while cancel occurring", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x26:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: command not valid to cancel", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x30:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: name defined by anther local process", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x34:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: environment undefined. RESET required", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x35:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: required OS resources exhausted", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x36:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: max number of applications exceeded", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x37:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: no saps available for netbios", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x38:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: requested resources are not available", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x39:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: invalid ncb address or length > segment", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x3B:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: invalid NCB DDID", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x3C:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: lock of user area failed", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x3f:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: NETBIOS not loaded", ncbp->ncb_lsn, idx_session);
-                break;
-            case 0x40:
-                osi_Log2(smb_logp, "NCBRECV failure lsn %d session %d: system error", ncbp->ncb_lsn, idx_session);
-                break;
-            default:
-                osi_Log3(smb_logp, "NCBRECV failure lsn %d session %d code %d", ncbp->ncb_lsn, idx_session, rc);
-                break;
-            }
-        }
+        if (rc != NRC_PENDING && rc != NRC_GOODRET)
+           osi_Log3(smb_logp, "NCBRECV failure lsn %d session %d: %s", ncbp->ncb_lsn, idx_session, ncb_error_string(rc));
 
         switch (rc) {
         case NRC_GOODRET: 
+            vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
             break;
 
         case NRC_PENDING:
@@ -7390,93 +7596,86 @@ void smb_Server(VOID *parmp)
             osi_Log2(smb_logp, "NCBRECV pending lsn %d session %d", ncbp->ncb_lsn, idx_session);
             continue;
 
-        case NRC_SCLOSED:
         case NRC_SNUMOUT:
+       case NRC_SABORT:
+#ifndef DJGPP
+           LogEvent(EVENTLOG_WARNING_TYPE, MSG_UNEXPECTED_SMB_SESSION_CLOSE, ncb_error_string(rc));
+           /* fallthrough */
+#endif /* !DJGPP */
+       case NRC_SCLOSED:
             /* Client closed 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.  [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, 
-             * also cleanup after dead vcp 
-             */
             if (vcp) {
-                if (dead_vcp == vcp)
-                    osi_Log1(smb_logp, "dead_vcp already set, 0x%x", dead_vcp);
-                else if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
-                    osi_Log2(smb_logp, "setting dead_vcp 0x%x, user struct 0x%x",
+               lock_ObtainMutex(&vcp->mx);
+               if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+                    osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
                              vcp, vcp->usersp);
-                    smb_HoldVC(vcp);
-                    if (dead_vcp) {
-                        smb_ReleaseVC(dead_vcp);
-                        osi_Log1(smb_logp,
-                                  "Previous dead_vcp %x", dead_vcp);
-                    }
-                    dead_vcp = vcp;
                     vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
-                }
-                if (vcp->justLoggedOut) {
-                    loggedOut = 1;
-                    loggedOutTime = vcp->logoffTime;
-                    loggedOutName = strdup(vcp->justLoggedOut->unp->name);
-                    loggedOutUserp = vcp->justLoggedOut;
-                    lock_ObtainWrite(&smb_rctLock);
-                    loggedOutUserp->refCount++;
-                    lock_ReleaseWrite(&smb_rctLock);
-                }
+                   lock_ReleaseMutex(&vcp->mx);
+                   lock_ObtainWrite(&smb_globalLock);
+                   dead_sessions[vcp->session] = TRUE;
+                   lock_ReleaseWrite(&smb_globalLock);
+                   smb_CleanupDeadVC(vcp);
+                   smb_ReleaseVC(vcp);
+                   vcp = NULL;
+                } else {
+                   lock_ReleaseMutex(&vcp->mx);
+               }
             }
             goto doneWithNCB;
 
         case NRC_INCOMP:
             /* Treat as transient error */
-            {
 #ifndef DJGPP
-                EVENT_HANDLE h;
-                char *ptbuf[1];
-                char s[100];
-
-                h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-                sprintf(s, "SMB message incomplete, length %d",
-                         ncbp->ncb_length);
-                ptbuf[0] = s;
-                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0,
-                             1001, NULL, 1,
-                             ncbp->ncb_length, ptbuf,
-                             bufp);
-                DeregisterEventSource(h);
+           LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_INCOMPLETE, 
+                    ncbp->ncb_length);
 #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);
-
-                /*
-                 * We used to discard the packet.
-                 * Instead, try handling it normally.
-                 *
-                 continue;
-                 */
-                break;
-            }
+           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);
+
+           /*
+            * We used to discard the packet.
+            * Instead, try handling it normally.
+            *
+            continue;
+            */
+            vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
+           break;
 
         default:
-            /* A weird error code.  Log it, sleep, and
-            * continue. */
+            /* A weird error code.  Log it, sleep, and continue. */
+            vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
+           if (vcp) 
+               lock_ObtainMutex(&vcp->mx);
             if (vcp && vcp->errorCount++ > 3) {
                 osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
-                dead_sessions[idx_session] = TRUE;
+               if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+                   osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+                            vcp, vcp->usersp);
+                   vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+                   lock_ReleaseMutex(&vcp->mx);
+                   lock_ObtainWrite(&smb_globalLock);
+                   dead_sessions[vcp->session] = TRUE;
+                   lock_ReleaseWrite(&smb_globalLock);
+                   smb_CleanupDeadVC(vcp);
+                   smb_ReleaseVC(vcp);
+                   vcp = NULL;
+               } else {
+                   lock_ReleaseMutex(&vcp->mx);
+               }
+               goto doneWithNCB;
             }
             else {
+               if (vcp)
+                   lock_ReleaseMutex(&vcp->mx);
                 thrd_Sleep(1000);
-                thrd_SetEvent(SessionEvents[idx_session]);
+               thrd_SetEvent(SessionEvents[idx_session]);
             }
-            continue;
+           continue;
         }
 
         /* Success, so now dispatch on all the data in the packet */
@@ -7485,9 +7684,6 @@ 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)
          * then we are in big trouble. This means either :
@@ -7500,29 +7696,12 @@ void smb_Server(VOID *parmp)
          * Log, sleep and resume.
          */
         if (!vcp) {
-            HANDLE h;
-            char buf[1000];
-            char *ptbuf[1];
-
-            sprintf(buf,
-                     "Bad vcp!! : "
-                     "LSNs[idx_session]=[%d],"
-                     "lanas[idx_session]=[%d],"
-                     "ncbp->ncb_lsn=[%d],"
-                     "ncbp->ncb_lana_num=[%d]",
+           LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_VCP,
                      LSNs[idx_session],
                      lanas[idx_session],
                      ncbp->ncb_lsn,
                      ncbp->ncb_lana_num);
 
-            ptbuf[0] = buf;
-
-            h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
-            if (h) {
-                ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,sizeof(*ncbp),ptbuf,(void*)ncbp);
-                DeregisterEventSource(h);
-            }
-
             /* Also log in the trace log. */
             osi_Log4(smb_logp, "Server: BAD VCP!"
                       "LSNs[idx_session]=[%d],"
@@ -7540,7 +7719,6 @@ void smb_Server(VOID *parmp)
             continue;
         }
 
-
         vcp->errorCount = 0;
         bufp = (struct smb_packet *) ncbp->ncb_buffer;
 #ifdef DJGPP
@@ -7627,17 +7805,7 @@ DWORD smb_ServerExceptionFilter(void) {
      * we have a trace (assuming tracing was enabled). Otherwise, this should
      * throw a second exception.
      */
-    HANDLE h;
-    char *ptbuf[1];
-
-    ptbuf[0] = "Unhandled exception forcing trace";
-
-    h = RegisterEventSource(NULL,AFS_DAEMON_EVENT_NAME);
-    if(h) {
-        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1001, NULL,1,0,ptbuf,NULL);
-        DeregisterEventSource(h);
-    }
-
+    LogEvent(EVENTLOG_ERROR_TYPE, MSG_UNHANDLED_EXCEPTION);
     afsd_ForceTrace(TRUE);
     buf_ForceTrace(TRUE);
     return EXCEPTION_CONTINUE_SEARCH;
@@ -7687,8 +7855,9 @@ void smb_Listener(void *parmp)
     NCB *ncbp;
     long code = 0;
     long len;
-    long i, j;
-    smb_vc_t *vcp = 0;
+    long i;
+    int  session, thread;
+    smb_vc_t *vcp = NULL;
     int flags = 0;
     char rname[NCBNAMSZ+1];
     char cname[MAX_COMPUTERNAME_LENGTH+1];
@@ -7697,7 +7866,7 @@ void smb_Listener(void *parmp)
     dos_ptr dos_ncb;
     time_t now;
 #endif /* DJGPP */
-    int lana = (int) parmp;
+    INT_PTR lana = (INT_PTR) parmp;
 
     ncbp = GetNCB();
 #ifdef DJGPP
@@ -7717,14 +7886,14 @@ void smb_Listener(void *parmp)
         ncbp->ncb_sto = 0;     /* No send timeout */
 
         /* pad out with spaces instead of null termination */
-        len = strlen(smb_localNamep);
+        len = (long)strlen(smb_localNamep);
         strncpy(ncbp->ncb_name, smb_localNamep, NCBNAMSZ);
         for (i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
         
         strcpy(ncbp->ncb_callname, "*");
         for (i=1; i<NCBNAMSZ; i++) ncbp->ncb_callname[i] = ' ';
         
-        ncbp->ncb_lana_num = lana;
+        ncbp->ncb_lana_num = (UCHAR)lana;
 
 #ifndef DJGPP
         code = Netbios(ncbp);
@@ -7788,67 +7957,89 @@ void smb_Listener(void *parmp)
             if (strncmp(rname, cname, NCBNAMSZ) != 0)
                 flags |= SMB_VCFLAG_REMOTECONN;
 
-        osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
         /* lock */
         lock_ObtainMutex(&smb_ListenerLock);
 
-        /* New generation */
-        sessionGen++;
+        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);
 
-        /* Log session startup */
+        /* now ncbp->ncb_lsn is the connection ID */
+        vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num);
+       if (vcp->session == 0) {
+           /* New generation */
+           osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
+           sessionGen++;
+
+           /* Log session startup */
 #ifdef NOTSERVICE
-        fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host "
-                 "%s\n",
-                 ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
+           fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host %s\n",
+                   ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
 #endif /* NOTSERVICE */
-        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);
+           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) {
+           if (reportSessionStartups) {
 #ifndef DJGPP
-            HANDLE h;
-            char *ptbuf[1];
-            char s[100];
-
-            h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-            sprintf(s, "SMB session startup, %d ongoing ops", ongoingOps);
-            ptbuf[0] = s;
-            ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1004, NULL,
-                         1, 0, ptbuf, NULL);
-            DeregisterEventSource(h);
+               LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_SESSION_START, ongoingOps);
 #else /* DJGPP */
-            time(&now);
-            fprintf(stderr, "%s: New session %d starting from host %s\n",
-                    asctime(localtime(&now)), ncbp->ncb_lsn, rname);
-            fflush(stderr);
+               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);
+           }
+           
+           lock_ObtainMutex(&vcp->mx);
+           strcpy(vcp->rname, rname);
+           vcp->flags |= flags;
+           lock_ReleaseMutex(&vcp->mx);
+
+           /* Allocate slot in session arrays */
+           /* Re-use dead session if possible, otherwise add one more */
+           /* But don't look at session[0], it is reserved */
+           lock_ObtainWrite(&smb_globalLock);
+           for (session = 1; session < numSessions; session++) {
+               if (dead_sessions[session]) {
+                   osi_Log1(smb_logp, "connecting to dead session [ %d ]", session);
+                   dead_sessions[session] = FALSE;
+                   break;
+               }
+           }
+           lock_ReleaseWrite(&smb_globalLock);
+       } else {
+           /* We are re-using an existing VC because the lsn and lana 
+            * were re-used */
+           session = vcp->session;
+
+           osi_Log1(smb_logp, "Re-using session lsn %d", ncbp->ncb_lsn);
+
+           /* Log session startup */
+#ifdef NOTSERVICE
+           fprintf(stderr, "Re-using session(ncb_lsn,ncb_lana_num) %d,%d starting from host %s\n",
+                   ncbp->ncb_lsn,ncbp->ncb_lana_num, rname);
+#endif /* NOTSERVICE */
+           osi_Log4(smb_logp, "Re-using 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);
 
-        /* now ncbp->ncb_lsn is the connection ID */
-        vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num);
-        vcp->flags |= flags;
-        strcpy(vcp->rname, rname);
-
-        /* Allocate slot in session arrays */
-        /* Re-use dead session if possible, otherwise add one more */
-        /* But don't look at session[0], it is reserved */
-        for (i = 1; i < numSessions; i++) {
-            if (dead_sessions[i]) {
-                osi_Log1(smb_logp, "connecting to dead session [ %d ]", i);
-                dead_sessions[i] = FALSE;
-                break;
-            }
-        }
+           if (reportSessionStartups) {
+#ifndef DJGPP
+               LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_SESSION_START, ongoingOps);
+#else /* DJGPP */
+               time(&now);
+               fprintf(stderr, "%s: Re-using session %d starting from host %s\n",
+                       asctime(localtime(&now)), ncbp->ncb_lsn, rname);
+               fflush(stderr);
+#endif /* !DJGPP */
+           }
+       }
 
-        if (i >= Sessionmax - 1  || numNCBs >= NCBmax - 1) {
+        if (session >= SESSION_MAX - 1  || numNCBs >= NCB_MAX - 1) {
             unsigned long code = CM_ERROR_ALLBUSY;
             smb_packet_t * outp = GetPacket();
             unsigned char *outWctp;
             smb_t *smbp;
             
+           smb_FormatResponsePacket(vcp, NULL, outp);
             outp->ncbp = ncbp;
 
             if (vcp->flags & SMB_VCFLAG_STATUS32) {
@@ -7879,42 +8070,55 @@ void smb_Listener(void *parmp)
             }
             smb_SendPacket(vcp, outp);
             smb_FreePacket(outp);
+
+           lock_ObtainMutex(&vcp->mx);
+           vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+           lock_ReleaseMutex(&vcp->mx);
+           smb_CleanupDeadVC(vcp);
         } else {
             /* assert that we do not exceed the maximum number of sessions or NCBs.
-            * we should probably want to wait for a session to be freed in case
-            * we run out.
-            */
-            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;
+             * we should probably want to wait for a session to be freed in case
+             * we run out.
+             */
+            osi_assert(session < SESSION_MAX - 1);
+            osi_assert(numNCBs < NCB_MAX - 1);   /* if we pass this test we can allocate one more */
+
+           lock_ObtainMutex(&vcp->mx);
+           vcp->session   = session;
+           lock_ReleaseMutex(&vcp->mx);
+           lock_ObtainWrite(&smb_globalLock);
+            LSNs[session]  = ncbp->ncb_lsn;
+            lanas[session] = ncbp->ncb_lana_num;
+           lock_ReleaseWrite(&smb_globalLock);
                
-            if (i == numSessions) {
+            if (session == numSessions) {
                 /* Add new NCB for new session */
                 char eventName[MAX_PATH];
 
                 osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
 
                 InitNCBslot(numNCBs);
+               lock_ObtainWrite(&smb_globalLock);
                 numNCBs++;
+               lock_ReleaseWrite(&smb_globalLock);
                 thrd_SetEvent(NCBavails[0]);
                 thrd_SetEvent(NCBevents[0]);
-                for (j = 0; j < smb_NumServerThreads; j++)
-                    thrd_SetEvent(NCBreturns[j][0]);
+                for (thread = 0; thread < smb_NumServerThreads; thread++)
+                    thrd_SetEvent(NCBreturns[thread][0]);
                 /* Also add new session event */
-                sprintf(eventName, "SessionEvents[%d]", i);
-                SessionEvents[i] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
+                sprintf(eventName, "SessionEvents[%d]", session);
+                SessionEvents[session] = 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));
+               lock_ObtainWrite(&smb_globalLock);
                 numSessions++;
+               lock_ReleaseWrite(&smb_globalLock);
                 osi_Log2(smb_logp, "increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
                 thrd_SetEvent(SessionEvents[0]);
             } else {
-                thrd_SetEvent(SessionEvents[i]);
+                thrd_SetEvent(SessionEvents[session]);
             }
         }
-        
         smb_ReleaseVC(vcp);
 
         /* unlock */
@@ -8099,7 +8303,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
 {
     thread_t phandle;
     int lpid;
-    int i;
+    INT_PTR i;
     int len;
     struct tm myTime;
 #ifdef DJGPP
@@ -8139,7 +8343,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     smb_logp = logp;
         
     /* remember the name */
-    len = strlen(snamep);
+    len = (int)strlen(snamep);
     smb_localNamep = malloc(len+1);
     strcpy(smb_localNamep, snamep);
     afsi_log("smb_localNamep is >%s<", smb_localNamep);
@@ -8225,7 +8429,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
         afsi_log("Event Object Already Exists: %s", eventName);
     for (i = 0; i < smb_NumServerThreads; i++) {
-        NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE));
+        NCBreturns[i] = malloc(NCB_MAX * sizeof(EVENT_HANDLE));
         NCBreturns[i][0] = retHandle;
     }
 
@@ -8235,7 +8439,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
         smb_ServerShutdown[i] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
         if ( GetLastError() == ERROR_ALREADY_EXISTS )
             afsi_log("Event Object Already Exists: %s", eventName);
-        InitNCBslot(i+1);
+        InitNCBslot((int)(i+1));
     }
     numNCBs = smb_NumServerThreads + 1;
 
@@ -8354,7 +8558,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
         LSA_OPERATIONAL_MODE dummy; /*junk*/
 
         afsProcessName.Buffer = "OpenAFSClientDaemon";
-        afsProcessName.Length = strlen(afsProcessName.Buffer);
+        afsProcessName.Length = (USHORT)strlen(afsProcessName.Buffer);
         afsProcessName.MaximumLength = afsProcessName.Length + 1;
 
         nts = LsaRegisterLogonProcess(&afsProcessName, &smb_lsaHandle, &dummy);
@@ -8363,7 +8567,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
             LSA_STRING packageName;
             /* we are registered. Find out the security package id */
             packageName.Buffer = MSV1_0_PACKAGE_NAME;
-            packageName.Length = strlen(packageName.Buffer);
+            packageName.Length = (USHORT)strlen(packageName.Buffer);
             packageName.MaximumLength = packageName.Length + 1;
             nts = LsaLookupAuthenticationPackage(smb_lsaHandle, &packageName , &smb_lsaSecPackage);
             if (nts == STATUS_SUCCESS) {
@@ -8406,10 +8610,10 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
                 /* END - code from Larry */
 
                 smb_lsaLogonOrigin.Buffer = "OpenAFS";
-                smb_lsaLogonOrigin.Length = strlen(smb_lsaLogonOrigin.Buffer);
+                smb_lsaLogonOrigin.Length = (USHORT)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);
+                afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%lX]",nts);
 
                 /* 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
@@ -8418,7 +8622,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
                 smb_authType = SMB_AUTH_NONE;
             }
         } else {
-            afsi_log("Can't register logon process!! NTSTATUS=[%l]",nts);
+            afsi_log("Can't register logon process!! NTSTATUS=[%lX]",nts);
 
             /* 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
@@ -8540,7 +8744,7 @@ void smb_Shutdown(void)
         /*fprintf(stderr, "NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
         ncbp->ncb_command = NCBHANGUP;
         ncbp->ncb_lana_num = lanas[i];  /*smb_LANadapter;*/
-        ncbp->ncb_lsn = LSNs[i];
+        ncbp->ncb_lsn = (UCHAR)LSNs[i];
 #ifndef DJGPP
         code = Netbios(ncbp);
 #else
@@ -8703,7 +8907,7 @@ void smb_LogPacket(smb_packet_t *packet)
 
         *cp = 0;
 
-        osi_Log0( smb_logp, osi_LogSaveString(smb_logp, buf));
+        osi_Log1( smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
     }
 
     osi_Log0(smb_logp, "*** End SMB packet dump ***");
@@ -8722,34 +8926,94 @@ int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
         lock_ObtainRead(&smb_rctLock);
   
     sprintf(output, "begin dumping smb_vc_t\n");
-    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
 
     for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) 
     {
         smb_fid_t *fidp;
       
-        sprintf(output, "%s vcp=0x%08X, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\n",
+        sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\n",
                  cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
-        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
       
         sprintf(output, "begin dumping smb_fid_t\n");
-        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
 
         for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
         {
-            sprintf(output, "%s -- smb_fidp=0x%08X, refCount=%d, fid=%d, vcp=0x%08X, scp=0x%08X, ioctlp=0x%08X, NTopen_pathp=%s, NTopen_wholepathp=%s\n", 
+            sprintf(output, "%s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, ioctlp=0x%p, NTopen_pathp=%s, NTopen_wholepathp=%s\n", 
                      cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
                      fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL", 
                      fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
-            WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
         }
       
         sprintf(output, "done dumping smb_fid_t\n");
-        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
     }
 
     sprintf(output, "done dumping smb_vc_t\n");
-    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+  
+    sprintf(output, "begin dumping DEAD smb_vc_t\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+    for (vcp = smb_deadVCsp; vcp; vcp=vcp->nextp) 
+    {
+        smb_fid_t *fidp;
+      
+        sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\n",
+                 cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+      
+        sprintf(output, "begin dumping smb_fid_t\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+        for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
+        {
+            sprintf(output, "%s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, ioctlp=0x%p, NTopen_pathp=%s, NTopen_wholepathp=%s\n", 
+                     cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
+                     fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL", 
+                     fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+      
+        sprintf(output, "done dumping smb_fid_t\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+    }
+
+    sprintf(output, "done dumping DEAD smb_vc_t\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+  
+    sprintf(output, "begin dumping DEAD smb_vc_t\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+    for (vcp = smb_deadVCsp; vcp; vcp=vcp->nextp) 
+    {
+        smb_fid_t *fidp;
+      
+        sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\n",
+                 cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+      
+        sprintf(output, "begin dumping smb_fid_t\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+        for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
+        {
+            sprintf(output, "%s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, ioctlp=0x%p, NTopen_pathp=%s, NTopen_wholepathp=%s\n", 
+                     cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
+                     fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL", 
+                     fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+      
+        sprintf(output, "done dumping smb_fid_t\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+    }
+
+    sprintf(output, "done dumping DEAD smb_vc_t\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
   
     if (lock)
         lock_ReleaseRead(&smb_rctLock);