windows-misc-fix-20061004
[openafs.git] / src / WINNT / afsd / smb.c
index 365ca1b..8bada6f 100644 (file)
@@ -7,18 +7,11 @@
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
-//#define NOTSERVICE 1
-#define LOG_PACKET 1
-
 #include <afs/param.h>
 #include <afs/stds.h>
 
-#ifndef DJGPP
 #include <windows.h>
-#else
-#include <sys/timeb.h>
-#include <tzfile.h>
-#endif /* !DJGPP */
+#include <ntstatus.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <malloc.h>
 #include <stdio.h>
 #include <time.h>
 
-#include <osi.h>
-#include <ntstatus.h>
-
 #include "afsd.h"
+#include <osi.h>
+#include <rx\rx.h>
+#include <rx/rx_prototypes.h>
+#include <WINNT\afsreg.h>
 
 #include "smb.h"
 #include "lanahelper.h"
 
 /* These characters are illegal in Windows filenames */
 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,30 +79,25 @@ 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 */
 osi_mutex_t smb_RawBufLock;
-#ifdef DJGPP
-#define SMB_RAW_BUFS 4
-dos_ptr smb_RawBufs;
-int smb_RawBufSel[SMB_RAW_BUFS];
-#else
 char *smb_RawBufs;
-#endif /* DJGPP */
 
 #define SMB_MASKFLAG_TILDE 1
 #define SMB_MASKFLAG_CASEFOLD 2
@@ -129,11 +109,7 @@ typedef struct raw_write_cont {
        long code;
        osi_hyper_t offset;
        long count;
-#ifndef DJGPP
        char *buf;
-#else
-       dos_ptr buf;
-#endif /* DJGPP */
        int writeMode;
        long alreadyWritten;
 } raw_write_cont_t;
@@ -149,12 +125,9 @@ int smb_hideDotFiles;
 /* global state about V3 protocols */
 int smb_useV3;         /* try to negotiate V3 */
 
-#ifndef DJGPP
-static showErrors = 1;
+static showErrors = 0;
 /* MessageBox or something like it */
 int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
-extern HANDLE WaitToTerminate;
-#endif /* DJGPP */
 
 /* GMT time info:
  * Time in Unix format of midnight, 1/1/1970 local time.
@@ -162,41 +135,32 @@ extern HANDLE WaitToTerminate;
  */
 time_t smb_localZero = 0;
 
+#define USE_NUMERIC_TIME_CONV 1
+
+#ifndef USE_NUMERIC_TIME_CONV
 /* Time difference for converting to kludge-GMT */
-int smb_NowTZ;
+afs_uint32 smb_NowTZ;
+#endif /* USE_NUMERIC_TIME_CONV */
 
 char *smb_localNamep = NULL;
 
 smb_vc_t *smb_allVCsp;
+smb_vc_t *smb_deadVCsp;
 
 smb_username_t *usernamesp = NULL;
 
-smb_waitingLock_t *smb_allWaitingLocks;
+smb_waitingLockRequest_t *smb_allWaitingLocks;
+
+DWORD smb_TlsRequestSlot = -1;
 
 /* 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
-DWORD smb_ServerExceptionFilter(void);
-#endif
-
-extern char cm_HostName[];
-extern char cm_confDir[];
-#endif
-
-#ifdef DJGPP
-#define LPTSTR char *
-#define GetComputerName(str, sizep) \
-       strcpy((str), cm_HostName); \
-       *(sizep) = strlen(cm_HostName)
-#endif /* DJGPP */
 
 #ifdef LOG_PACKET
 void smb_LogPacket(smb_packet_t *packet);
 #endif /* LOG_PACKET */
-extern char AFSConfigKeyName[];
 
 char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
 int smb_ServerDomainNameLength = 0;
@@ -208,6 +172,89 @@ 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 }};
 
+void smb_ResetServerPriority()
+{
+    void * p = TlsGetValue(smb_TlsRequestSlot);
+    if (p) {
+       free(p);
+       TlsSetValue(smb_TlsRequestSlot, NULL);
+       SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+    }
+}
+
+void smb_SetRequestStartTime()
+{
+    time_t * tp = TlsGetValue(smb_TlsRequestSlot);
+    if (!tp)
+       tp = malloc(sizeof(time_t));
+    if (tp) {
+       *tp = osi_Time();
+
+       if (!TlsSetValue(smb_TlsRequestSlot, tp))
+           free(tp);
+    }  
+}
+
+void smb_UpdateServerPriority()
+{      
+    time_t *tp = TlsGetValue(smb_TlsRequestSlot);
+
+    if (tp) {
+       time_t now = osi_Time();
+
+       /* Give one priority boost for each 15 seconds */
+       SetThreadPriority(GetCurrentThread(), (now - *tp) / 15);
+    }
+}
+
+
+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)
@@ -272,6 +319,8 @@ char * myCrt_Dispatch(int i)
         return "(2d)ReceiveV3OpenX";
     case 0x2e:
         return "(2e)ReceiveV3ReadX";
+    case 0x2f:
+        return "(2f)ReceiveV3WriteX";
     case 0x32:
         return "(32)ReceiveV3Tran2A";
     case 0x33:
@@ -336,25 +385,25 @@ char * myCrt_2Dispatch(int i)
     default:
         return "unknown SMB op-2";
     case 0:
-        return "S(00)CreateFile";
+        return "S(00)CreateFile_ReceiveTran2Open";
     case 1:
-        return "S(01)FindFirst";
+        return "S(01)FindFirst_ReceiveTran2SearchDir";
     case 2:
-        return "S(02)FindNext";        /* FindNext */
+        return "S(02)FindNext_ReceiveTran2SearchDir";  /* FindNext */
     case 3:
         return "S(03)QueryFileSystem_ReceiveTran2QFSInfo";
     case 4:
-        return "S(04)??";
+        return "S(04)SetFileSystem_ReceiveTran2SetFSInfo";
     case 5:
-        return "S(05)QueryFileInfo_ReceiveTran2QPathInfo";
+        return "S(05)QueryPathInfo_ReceiveTran2QPathInfo";
     case 6:
-        return "S(06)SetFileInfo_ReceiveTran2SetPathInfo";
+        return "S(06)SetPathInfo_ReceiveTran2SetPathInfo";
     case 7:
-        return "S(07)SetInfoHandle_ReceiveTran2QFileInfo";
+        return "S(07)QueryFileInfo_ReceiveTran2QFileInfo";
     case 8:
-        return "S(08)??_ReceiveTran2SetFileInfo";
+        return "S(08)SetFileInfo_ReceiveTran2SetFileInfo";
     case 9:
-        return "S(09)??_ReceiveTran2FSCTL";
+        return "S(09)_ReceiveTran2FSCTL";
     case 10:
         return "S(0a)_ReceiveTran2IOCTL";
     case 11:
@@ -365,6 +414,8 @@ char * myCrt_2Dispatch(int i)
         return "S(0d)_ReceiveTran2CreateDirectory";
     case 14:
         return "S(0e)_ReceiveTran2SessionSetup";
+    case 15:
+       return "S(0f)_QueryFileSystemInformationFid";
     case 16:
         return "S(10)_ReceiveTran2GetDfsReferral";
     case 17:
@@ -395,12 +446,15 @@ unsigned int smb_Attributes(cm_scache_t *scp)
     unsigned int attrs;
 
     if ( scp->fileType == CM_SCACHETYPE_DIRECTORY ||
-         scp->fileType == CM_SCACHETYPE_MOUNTPOINT) 
+         scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+         scp->fileType == CM_SCACHETYPE_INVALID)
     {
         attrs = SMB_ATTR_DIRECTORY;
 #ifdef SPECIAL_FOLDERS
         attrs |= SMB_ATTR_SYSTEM;              /* FILE_ATTRIBUTE_SYSTEM */
 #endif /* SPECIAL_FOLDERS */
+    } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
     } else
         attrs = 0;
 
@@ -410,9 +464,11 @@ unsigned int smb_Attributes(cm_scache_t *scp)
      */
 #ifdef notdef
     if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+        attrs |= SMB_ATTR_READONLY;    /* turn on read-only flag */
+#else
+    if ((scp->unixModeBits & 0222) == 0)
+        attrs |= SMB_ATTR_READONLY;    /* turn on read-only flag */
 #endif
-       if ((scp->unixModeBits & 0222) == 0)
-            attrs |= SMB_ATTR_READONLY;        /* turn on read-only flag */
 
     return attrs;
 }
@@ -455,7 +511,6 @@ static int ExtractBits(WORD bits, short start, short len)
     return (int)num;
 }
 
-#ifndef DJGPP
 void ShowUnixTime(char *FuncName, time_t unixTime)
 {
     FILETIME ft;
@@ -481,9 +536,7 @@ void ShowUnixTime(char *FuncName, time_t unixTime)
         osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
     }
 }       
-#endif /* DJGPP */
 
-#ifndef DJGPP
 /* Determine if we are observing daylight savings time */
 void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
 {
@@ -526,21 +579,9 @@ void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
      */
     *pDST = localDST.wHour != local.wHour;
 }       
-#else
-/* Determine if we are observing daylight savings time */
-void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
-{
-    struct timeb t;
-
-    ftime(&t);
-    *pDST = t.dstflag;
-    *pDstBias = -60;    /* where can this be different? */
-    *pBias = t.timezone;
-}       
-#endif /* DJGPP */
  
 
-void CompensateForSmbClientLastWriteTimeBugs(long *pLastWriteTime)
+void CompensateForSmbClientLastWriteTimeBugs(afs_uint32 *pLastWriteTime)
 {
     BOOL dst;       /* Will be TRUE if observing DST */
     LONG dstBias;   /* Offset from local time if observing DST */
@@ -576,6 +617,7 @@ void CompensateForSmbClientLastWriteTimeBugs(long *pLastWriteTime)
         *pLastWriteTime -= (-bias * 60);        /* Convert bias to seconds */
 }                      
 
+#ifndef USE_NUMERIC_TIME_CONV
 /*
  * Calculate the difference (in seconds) between local time and GMT.
  * This enables us to convert file times to kludge-GMT.
@@ -592,21 +634,25 @@ smb_CalculateNowTZ()
     local_tm = *(localtime(&t));
 
     days = local_tm.tm_yday - gmt_tm.tm_yday;
-    hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour
-#ifdef COMMENT
-        /* There is a problem with DST immediately after the time change
-        * which may continue to exist until the machine is rebooted
-         */
-        - (local_tm.tm_isdst ? 1 : 0)
-#endif /* COMMENT */
-            ;
+    hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour;
     minutes = 60 * hours + local_tm.tm_min - gmt_tm.tm_min; 
     seconds = 60 * minutes + local_tm.tm_sec - gmt_tm.tm_sec;
 
     smb_NowTZ = seconds;
 }
+#endif /* USE_NUMERIC_TIME_CONV */
+
+#ifdef USE_NUMERIC_TIME_CONV
+void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+{
+    // Note that LONGLONG is a 64-bit value
+    LONGLONG ll;
 
-#ifndef DJGPP
+    ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
+    largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
+    largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
+}
+#else
 void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
 {
     struct tm *ltp;
@@ -646,29 +692,24 @@ void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
 
     SystemTimeToFileTime(&stm, largeTimep);
 }
-#else /* DJGPP */
-void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+#endif /* USE_NUMERIC_TIME_CONV */
+
+#ifdef USE_NUMERIC_TIME_CONV
+void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
 {
-    /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
-    /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 ??? */
-    LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
-    LARGE_INTEGER ut;
-    int leap_years = 89;   /* leap years betw 1/1/1601 and 1/1/1970 */
-
-    /* set ft to number of 100ns intervals betw 1/1/1601 and 1/1/1970 GMT */
-    *ft = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years)
-                                     * 24 * 60);
-    *ft = LargeIntegerMultiplyByLong(*ft, 60);
-    *ft = LargeIntegerMultiplyByLong(*ft, 10000000);
-
-    /* add unix time */
-    ut = ConvertLongToLargeInteger(unixTime);
-    ut = LargeIntegerMultiplyByLong(ut, 10000000);
-    *ft = LargeIntegerAdd(*ft, ut);
-}       
-#endif /* !DJGPP */
+    // Note that LONGLONG is a 64-bit value
+    LONGLONG ll;
+
+    ll = largeTimep->dwHighDateTime;
+    ll <<= 32;
+    ll += largeTimep->dwLowDateTime;
 
-#ifndef DJGPP
+    ll -= 116444736000000000;
+    ll /= 10000000;
+
+    *unixTimep = (DWORD)ll;
+}
+#else /* USE_NUMERIC_TIME_CONV */
 void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
 {
     SYSTEMTIME stm;
@@ -691,29 +732,9 @@ void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
     *unixTimep = mktime(&lt);
     _timezone = save_timezone;
 }       
-#else /* DJGPP */
-void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
-{
-    /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
-    /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 GMT? */
-    LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
-    LARGE_INTEGER a;
-    int leap_years = 89;
-
-    /* set to number of 100ns intervals betw 1/1/1601 and 1/1/1970 */
-    a = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years) * 24 * 60);
-    a = LargeIntegerMultiplyByLong(a, 60);
-    a = LargeIntegerMultiplyByLong(a, 10000000);
-
-    /* subtract it from ft */
-    a = LargeIntegerSubtract(*ft, a);
-
-    /* divide down to seconds */
-    *unixTimep = LargeIntegerDivideByLong(a, 10000000);
-}       
-#endif /* !DJGPP */
+#endif /* USE_NUMERIC_TIME_CONV */
 
-void smb_SearchTimeFromUnixTime(time_t *dosTimep, time_t unixTime)
+void smb_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
 {
     struct tm *ltp;
     int dosDate;
@@ -721,7 +742,7 @@ void smb_SearchTimeFromUnixTime(time_t *dosTimep, 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) {
@@ -736,10 +757,10 @@ void smb_SearchTimeFromUnixTime(time_t *dosTimep, time_t unixTime)
 
     dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
     dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
-    *dosTimep = (dosDate<<16) | dosTime;
+    *searchTimep = (dosDate<<16) | dosTime;
 }      
 
-void smb_UnixTimeFromSearchTime(time_t *unixTimep, time_t searchTime)
+void smb_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
 {
     unsigned short dosDate;
     unsigned short dosTime;
@@ -759,19 +780,18 @@ void smb_UnixTimeFromSearchTime(time_t *unixTimep, time_t searchTime)
     *unixTimep = mktime(&localTm);
 }
 
-void smb_DosUTimeFromUnixTime(time_t *dosUTimep, time_t unixTime)
+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, time_t dosTime)
+void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
 {
-#ifndef DJGPP
     *unixTimep = dosTime + smb_localZero;
-#else /* DJGPP */
-    /* dosTime seems to be already adjusted for GMT */
-    *unixTimep = dosTime;
-#endif /* !DJGPP */
 }
 
 smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
@@ -780,7 +800,12 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
 
     lock_ObtainWrite(&smb_rctLock);
     for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
-        if (lsn == vcp->lsn && lana == vcp->lana) {
+       if (vcp->magic != SMB_VC_MAGIC)
+           osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", 
+                      __FILE__, __LINE__);
+
+        if (lsn == vcp->lsn && lana == vcp->lana &&
+           !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
             smb_HoldVCNoLock(vcp);
             break;
         }
@@ -788,11 +813,14 @@ 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->magic = SMB_VC_MAGIC;
+        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");
@@ -804,10 +832,10 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
             /* We must obtain a challenge for extended auth 
              * in case the client negotiates smb v3 
              */
-            NTSTATUS nts,ntsEx;
+            NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
             MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
             PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp;
-            ULONG lsaRespSize;
+            ULONG lsaRespSize = 0;
 
             lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
 
@@ -818,6 +846,9 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
                                                 &lsaResp,
                                                 &lsaRespSize,
                                                 &ntsEx);
+            if (nts != STATUS_SUCCESS)
+                osi_Log4(smb_logp,"MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize is %u needs %u",
+                         nts, ntsEx, sizeof(lsaReq), lsaRespSize);
             osi_assert(nts == STATUS_SUCCESS); /* this had better work! */
 
             memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
@@ -825,6 +856,13 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
         }
         else
             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");
+        }
     }
     lock_ReleaseWrite(&smb_rctLock);
     return vcp;
@@ -837,41 +875,194 @@ 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_ReleaseVCInternal(smb_vc_t *vcp)
+{
+    smb_vc_t **vcpp;
+    smb_vc_t * avcp;
+
+    vcp->refCount--;
+
+    if (vcp->refCount == 0) {
+      if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+       /* 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);
+      } else {
+       for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
+         if (avcp == vcp)
+           break;
+       }
+       osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
+                avcp?"not ":"",vcp, vcp->refCount);
+#ifdef DEBUG
+       GenerateMiniDump(NULL);
+#endif
+       /* This is a wrong.  However, I suspect that there is an undercount
+        * and I don't want to release 1.4.1 in a state that will allow
+        * smb_vc_t objects to be deallocated while still in the
+        * smb_allVCsp list.  The list is supposed to keep a reference
+        * to the smb_vc_t.  Put it back.
+        */
+       vcp->refCount++;
+      }
+    }
+}
+
 void smb_ReleaseVCNoLock(smb_vc_t *vcp)
 {
-    osi_assert(vcp->refCount-- > 0);
+    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_assert(vcp->refCount-- > 0);
+    osi_Log2(smb_logp,"smb_ReleaseVC       vcp %x ref %d",vcp, vcp->refCount);
+    smb_ReleaseVCInternal(vcp);
     lock_ReleaseWrite(&smb_rctLock);
 }       
 
 void smb_HoldVCNoLock(smb_vc_t *vcp)
 {
     vcp->refCount++;
+    osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
 }       
 
 void smb_HoldVC(smb_vc_t *vcp)
 {
     lock_ObtainWrite(&smb_rctLock);
     vcp->refCount++;
+    osi_Log2(smb_logp,"smb_HoldVC       vcp %x ref %d",vcp, vcp->refCount);
     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;
+
+
+    lock_ObtainMutex(&vcp->mx);
+    if (vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS) {
+       lock_ReleaseMutex(&vcp->mx);
+       osi_Log1(smb_logp, "Clean of dead vcp 0x%x in progress", vcp);
+       return;
+    }
+    vcp->flags |= SMB_VCFLAG_CLEAN_IN_PROGRESS;
+    lock_ReleaseMutex(&vcp->mx);
+    osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
+
+    lock_ObtainWrite(&smb_rctLock);
+    /* remove VCP from smb_allVCsp */
+    for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+       if ((*vcpp)->magic != SMB_VC_MAGIC)
+           osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", 
+                      __FILE__, __LINE__);
+        if (*vcpp == vcp) {
+            *vcpp = vcp->nextp;
+            vcp->nextp = smb_deadVCsp;
+            smb_deadVCsp = vcp;
+           /* Hold onto the reference until we are done with this function */
+            break;
+        }
+    }
+
+    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;
+    }
+
+    /* The vcp is now on the deadVCsp list.  We intentionally drop the
+     * reference so that the refcount can reach 0 and we can delete it */
+    smb_ReleaseVCNoLock(vcp);
+    
+    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;
 
     lock_ObtainWrite(&smb_rctLock);
+  retry:
     for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+       if (tidp->refCount == 0 && tidp->delete) {
+           tidp->refCount++;
+           lock_ReleaseWrite(&smb_rctLock);
+           smb_ReleaseTID(tidp);
+           lock_ObtainWrite(&smb_rctLock);
+           goto retry;
+       }
+
         if (tid == tidp->tid) {
             tidp->refCount++;
             break;
@@ -892,6 +1083,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;
@@ -901,9 +1097,9 @@ 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) {
+        for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
             if (tp == tidp) 
                 break;
         }
@@ -928,9 +1124,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;
         }
     }
@@ -938,19 +1134,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;
 
@@ -971,7 +1169,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;
 }      
@@ -986,7 +1187,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;
@@ -994,59 +1196,111 @@ 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) break;
+            if (up == uidp) 
+                break;
         }
         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;
 }
 
@@ -1063,7 +1317,7 @@ long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** treepath)
     if (!tidp) {
         *treepath = NULL;
     } else {
-        if(tidp->flags & SMB_TIDFLAG_IPC) {
+        if (tidp->flags & SMB_TIDFLAG_IPC) {
             code = CM_ERROR_TIDIPC;
             /* tidp->pathname would be NULL, but that's fine */
         }
@@ -1092,7 +1346,7 @@ int smb_SUser(cm_user_t *userp)
     return 1;
 }
 
-/* find a file ID.  If we pass in 0 we select an used File ID.
+/* find a file ID.  If we pass in 0 we select an unused File ID.
  * If the SMB_FLAG_CREATE flag is set, we allocate a new  
  * smb_fid_t data structure if desired File ID cannot be found.
  */
@@ -1112,18 +1366,29 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
     }
 
   retry:
-    for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+    for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+       if (fidp->refCount == 0 && fidp->delete) {
+           fidp->refCount++;
+           lock_ReleaseWrite(&smb_rctLock);
+           smb_ReleaseFID(fidp);
+           lock_ObtainWrite(&smb_rctLock);
+           goto retry;
+       }
         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++;
             break;
         }
     }
+
     if (!fidp && (flags & SMB_FLAG_CREATE)) {
         char eventName[MAX_PATH];
         EVENT_HANDLE event;
@@ -1133,8 +1398,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;
         }
 
@@ -1150,58 +1417,92 @@ 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;
+}
+
+smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
+{
+    smb_fid_t *fidp = NULL;
+    int newFid = 0;
+        
+    if (!scp)
+        return NULL;
+
+    lock_ObtainWrite(&smb_rctLock);
+    for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+        if (scp == fidp->scp) {
+            fidp->refCount++;
+            break;
         }
     }
     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_ObtainMutex(&fidp->mx);
     lock_ObtainWrite(&smb_rctLock);
     osi_assert(fidp->refCount-- > 0);
-    if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
+    if (fidp->refCount == 0 && (fidp->delete)) {
         vcp = fidp->vcp;
         fidp->vcp = NULL;
-        if (!(fidp->flags & SMB_FID_IOCTL)) {
-            scp = fidp->scp;
-            fidp->scp = NULL;
-        }
+        scp = fidp->scp;    /* release after lock is released */
+        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 */
         ioctlp = fidp->ioctlp;
         if (ioctlp) {
-            if (ioctlp->prefix) 
+            if (ioctlp->prefix)
                 cm_FreeSpace(ioctlp->prefix);
-            if (ioctlp->inAllocp) 
+            if (ioctlp->inAllocp)
                 free(ioctlp->inAllocp);
-            if (ioctlp->outAllocp) 
+            if (ioctlp->outAllocp)
                 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);
 }       
 
 /*
@@ -1239,71 +1540,6 @@ char VNLCUserName[] = "%LCUSERNAME%";
 char VNComputerName[] = "%COMPUTERNAME%";
 char VNLCComputerName[] = "%LCCOMPUTERNAME%";
 
-#ifdef DJGPP
-/* List available shares */
-int smb_ListShares()
-{
-    char sbmtpath[256];
-    char pathName[256];
-    char shareBuf[4096];
-    int num_shares=0;
-    char *this_share;
-    int len;
-    char *p;
-    int print_afs = 0;
-    int code;
-
-    /*strcpy(shareNameList[num_shares], "all");
-      strcpy(pathNameList[num_shares++], "/afs");*/
-    fprintf(stderr, "The following shares are available:\n");
-    fprintf(stderr, "Share Name (AFS Path)\n");
-    fprintf(stderr, "---------------------\n");
-    fprintf(stderr, "\\\\%s\\%-16s (%s)\n", smb_localNamep, "ALL", cm_mountRoot);
-
-#ifndef DJGPP
-    code = GetWindowsDirectory(sbmtpath, sizeof(sbmtpath));
-    if (code == 0 || code > sizeof(sbmtpath)) return -1;
-#else
-    strcpy(sbmtpath, cm_confDir);
-#endif /* !DJGPP */
-    strcat(sbmtpath, "/afsdsbmt.ini");
-    len = GetPrivateProfileString("AFS Submounts", NULL, NULL,
-                                   shareBuf, sizeof(shareBuf),
-                                   sbmtpath);
-    if (len == 0) {
-        return num_shares;
-    }
-
-    this_share = shareBuf;
-    do
-    {
-        print_afs = 0;
-        /*strcpy(shareNameList[num_shares], this_share);*/
-        len = GetPrivateProfileString("AFS Submounts", this_share,
-                                       NULL,
-                                       pathName, 256,
-                                       sbmtpath);
-        if (!len) 
-            return num_shares;
-        p = pathName;
-        if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) != 0)
-            print_afs = 1;
-        while (*p) {
-            if (*p == '\\') *p = '/';    /* change to / */
-            p++;
-        }
-
-        fprintf(stderr, "\\\\%s\\%-16s (%s%s)\n",
-                 smb_localNamep, this_share, (print_afs ? cm_mountRoot : "\0"),
-                 pathName);
-        num_shares++;
-        while (*this_share != 0) this_share++;  /* find next NUL */
-        this_share++;   /* skip past the NUL */
-    } while (*this_share != 0);  /* stop at final NUL */
-
-    return num_shares;
-}
-#endif /* DJGPP */
 
 typedef struct smb_findShare_rock {
     char * shareName;
@@ -1344,9 +1580,6 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
     char *var;
     char temp[1024];
     DWORD sizeTemp;
-#ifdef DJGPP
-    char sbmtpath[MAX_PATH];
-#endif
     char *p, *q;
     HKEY parmKey;
     DWORD code;
@@ -1357,7 +1590,7 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
      * This is to allow sites that want to restrict access to the 
      * world to do so.
      */
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         len = sizeof(allSubmount);
@@ -1390,8 +1623,7 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
         return 0;
     }
 
-#ifndef DJGPP
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\OpenAFS\\Client\\Submounts",
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
                          0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
         len = sizeof(pathName);
@@ -1403,12 +1635,6 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
     } else {
         len = 0;
     }   
-#else /* DJGPP */
-    strcpy(sbmtpath, cm_confDir);
-    strcat(sbmtpath, "/afsdsbmt.ini");
-    len = GetPrivateProfileString("AFS Submounts", shareName, "",
-                                   pathName, sizeof(pathName), sbmtpath);
-#endif /* !DJGPP */
     if (len != 0 && len != sizeof(pathName) - 1) {
         /* We can accept either unix or PC style AFS pathnames.  Convert
          * Unix-style to PC style here for internal use. 
@@ -1478,10 +1704,10 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
         vrock.match = NULL;
         vrock.matchType = 0;
 
-        cm_HoldSCache(cm_rootSCachep);
-        code = cm_ApplyDir(cm_rootSCachep, smb_FindShareProc, &vrock, &thyper,
+        cm_HoldSCache(cm_data.rootSCachep);
+        code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
             (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
-        cm_ReleaseSCache(cm_rootSCachep);
+        cm_ReleaseSCache(cm_data.rootSCachep);
 
         if (vrock.matchType) {
             sprintf(pathName,"/%s/",vrock.match);
@@ -1499,7 +1725,7 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
         /* Get the full name for this cell */
         code = cm_SearchCellFile(p, temp, 0, 0);
 #ifdef AFS_AFSDB_ENV
-               if (code && cm_dnsEnabled) {
+        if (code && cm_dnsEnabled) {
             int ttl;
             code = cm_SearchCellByDNS(p, temp, &ttl, 0, 0);
         }
@@ -1531,7 +1757,7 @@ int smb_FindShareCSCPolicy(char *shareName)
     int  retval = CSC_POLICY_MANUAL;
 
     RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
-                    "SOFTWARE\\OpenAFS\\Client\\CSCPolicy",
+                    AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
                     0, 
                     "AFS", 
                     REG_OPTION_NON_VOLATILE,
@@ -1574,8 +1800,7 @@ smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
             if (dsp != smb_firstDirSearchp) {
                 /* move to head of LRU queue, too, if we're not already there */
                 if (smb_lastDirSearchp == (smb_dirSearch_t *) &dsp->q)
-                    smb_lastDirSearchp = (smb_dirSearch_t *)
-                        osi_QPrev(&dsp->q);
+                    smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
                 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
                 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
                 if (!smb_lastDirSearchp)
@@ -1587,6 +1812,13 @@ smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
             break;
         }
     }
+
+    if (dsp == NULL) {
+        osi_Log1(smb_logp,"smb_FindDirSearch(%d) == NULL",cookie);
+        for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
+            osi_Log1(smb_logp,"... valid id: %d", dsp->cookie);
+        }
+    }
     return dsp;
 }       
 
@@ -1600,7 +1832,7 @@ void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
         if (dsp->flags & SMB_DIRSEARCH_BULKST) {
             dsp->flags &= ~SMB_DIRSEARCH_BULKST;
             dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
-            dsp->scp->bulkStatProgress = hones;
+            dsp->scp->bulkStatProgress = hzero;
         }      
         lock_ReleaseMutex(&dsp->scp->mx);
     }  
@@ -1611,9 +1843,7 @@ void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
 /* Must be called with the smb_globalLock held */
 void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
 {
-    cm_scache_t *scp;
-        
-    scp = NULL;
+    cm_scache_t *scp = NULL;
 
     lock_ObtainMutex(&dsp->mx);
     osi_assert(dsp->refCount-- > 0);
@@ -1629,7 +1859,8 @@ void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
         lock_ReleaseMutex(&dsp->mx);
     }
     /* do this now to avoid spurious locking hierarchy creation */
-    if (scp) cm_ReleaseSCache(scp);
+    if (scp) 
+        cm_ReleaseSCache(scp);
 }       
 
 void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
@@ -1674,7 +1905,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++;
         }
@@ -1701,12 +1934,18 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
     smb_dirSearch_t *dsp;
     int counter;
     int maxAllowed;
+    int start;
+    int wrapped = 0;
 
     lock_ObtainWrite(&smb_globalLock);
     counter = 0;
 
     /* what's the biggest ID allowed in this version of the protocol */
     maxAllowed = isV3 ? 65535 : 255;
+    if (smb_dirSearchCounter > maxAllowed)
+        smb_dirSearchCounter = 1;
+
+    start = smb_dirSearchCounter;
 
     while (1) {
         /* twice so we have enough tries to find guys we GC after one pass;
@@ -1717,8 +1956,12 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
 
         if (smb_dirSearchCounter > maxAllowed) {       
             smb_dirSearchCounter = 1;
-            smb_GCDirSearches(isV3);   /* GC some */
-        }      
+        }
+        if (smb_dirSearchCounter == start) {
+            if (wrapped)
+                smb_GCDirSearches(isV3);
+            wrapped++;
+        }
         dsp = smb_FindDirSearchNoLock(smb_dirSearchCounter);
         if (dsp) {
             /* don't need to watch for refcount zero and deleted, since
@@ -1733,14 +1976,14 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
 
         dsp = malloc(sizeof(*dsp));
         memset(dsp, 0, sizeof(*dsp));
-        osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
-        if (!smb_lastDirSearchp) 
-            smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
         dsp->cookie = smb_dirSearchCounter;
         ++smb_dirSearchCounter;
         dsp->refCount = 1;
         lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
         dsp->lastTime = osi_Time();
+        osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+        if (!smb_lastDirSearchp) 
+            smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
         break;
     }  
     lock_ReleaseWrite(&smb_globalLock);
@@ -1750,9 +1993,6 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
 static smb_packet_t *GetPacket(void)
 {
     smb_packet_t *tbp;
-#ifdef DJGPP
-    unsigned int npar, seg, tb_sel;
-#endif
 
     lock_ObtainWrite(&smb_globalLock);
     tbp = smb_packetFreeListp;
@@ -1760,11 +2000,7 @@ static smb_packet_t *GetPacket(void)
         smb_packetFreeListp = tbp->nextp;
     lock_ReleaseWrite(&smb_globalLock);
     if (!tbp) {
-#ifndef DJGPP
         tbp = calloc(65540,1);
-#else /* DJGPP */
-        tbp = malloc(sizeof(smb_packet_t));
-#endif /* !DJGPP */
         tbp->magic = SMB_PACKETMAGIC;
         tbp->ncbp = NULL;
         tbp->vcp = NULL;
@@ -1778,25 +2014,6 @@ static smb_packet_t *GetPacket(void)
         tbp->flags = 0;
         tbp->spacep = NULL;
         
-#ifdef DJGPP
-        npar = SMB_PACKETSIZE >> 4;  /* number of paragraphs */
-        {
-            signed int retval =
-                __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
-            if (retval == -1) {
-                osi_Log1(smb_logp, "Cannot allocate %d paragraphs of DOS memory",
-                          npar);
-                osi_panic("",__FILE__,__LINE__);
-            }
-            else {
-                osi_Log2(smb_logp, "Allocated %d paragraphs of DOS mem at 0x%X",
-                          npar, retval);
-                seg = retval;
-            }
-        }
-        tbp->dos_pkt = (seg * 16) + 0;  /* DOS physical address */
-        tbp->dos_pkt_sel = tb_sel;
-#endif /* DJGPP */
     }
     osi_assert(tbp->magic == SMB_PACKETMAGIC);
 
@@ -1808,7 +2025,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);
+    tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
+    if (tbp->vcp)
+       smb_HoldVC(tbp->vcp);
     return tbp;
 }
 
@@ -1816,9 +2035,6 @@ static NCB *GetNCB(void)
 {
     smb_ncb_t *tbp;
     NCB *ncbp;
-#ifdef DJGPP
-    unsigned int npar, seg, tb_sel;
-#endif /* DJGPP */
 
     lock_ObtainWrite(&smb_globalLock);
     tbp = smb_ncbFreeListp;
@@ -1826,27 +2042,7 @@ static NCB *GetNCB(void)
         smb_ncbFreeListp = tbp->nextp;
     lock_ReleaseWrite(&smb_globalLock);
     if (!tbp) {
-#ifndef DJGPP
         tbp = calloc(sizeof(*tbp),1);
-#else /* DJGPP */
-        tbp = malloc(sizeof(*tbp));
-        npar = (sizeof(NCB)+15) >> 4;  /* number of paragraphs */
-        {
-            signed int retval =
-                __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
-            if (retval == -1) {
-                osi_Log1(smb_logp, "Cannot allocate %d paragraphs of DOS mem in GetNCB",
-                          npar);
-                osi_panic("",__FILE__,__LINE__);
-            } else {
-                osi_Log2(smb_logp, "Allocated %d paragraphs of DOS mem at 0x%X in GetNCB",
-                          npar, retval);
-                seg = retval;
-            }
-        }
-        tbp->dos_ncb = (seg * 16) + 0;  /* DOS physical address */
-        tbp->dos_ncb_sel = tb_sel;
-#endif /* !DJGPP */
         tbp->magic = SMB_NCBMAGIC;
     }
         
@@ -1854,16 +2050,12 @@ static NCB *GetNCB(void)
 
     memset(&tbp->ncb, 0, sizeof(NCB));
     ncbp = &tbp->ncb;
-#ifdef DJGPP
-    dos_memset(tbp->dos_ncb, 0, sizeof(NCB));
-#endif /* DJGPP */
     return ncbp;
 }
 
 void smb_FreePacket(smb_packet_t *tbp)
 {
     smb_vc_t * vcp = NULL;
-
     osi_assert(tbp->magic == SMB_PACKETMAGIC);
         
     lock_ObtainWrite(&smb_globalLock);
@@ -1942,21 +2134,14 @@ 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",
+       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   
-        ptbuf[0] = s;
-        ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1006, NULL,
-                     1, smbp->ncb_length, ptbuf, smbp);
-        DeregisterEventSource(h);
-#endif
-        osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+       LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM, 
+                __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
         osi_panic(s, __FILE__, __LINE__);
     }
     parmDatap = smbp->wctp + (2*parm) + 1;
@@ -1965,6 +2150,30 @@ unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
 }
 
 /* return the parm'th parameter in the smbp packet */
+unsigned int smb_GetSMBParmLong(smb_packet_t *smbp, int parm)
+{
+    int parmCount;
+    unsigned char *parmDatap;
+
+    parmCount = *smbp->wctp;
+
+    if (parm + 1 >= parmCount) {
+       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);
+       LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM, 
+                __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
+        osi_panic(s, __FILE__, __LINE__);
+    }
+    parmDatap = smbp->wctp + (2*parm) + 1;
+        
+    return parmDatap[0] + (parmDatap[1] << 8) + (parmDatap[2] << 16) + (parmDatap[3] << 24);
+}
+
+/* return the parm'th parameter in the smbp packet */
 unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
 {
     int parmCount;
@@ -1974,20 +2183,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
-        osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+       LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM_WITH_OFFSET, 
+                __FILE__, __LINE__, parm, offset, parmCount, smbp->ncb_length);
+        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__);
     }
     parmDatap = smbp->wctp + (2*parm) + 1 + offset;
@@ -2020,7 +2222,7 @@ void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
     *parmDatap++ = parmValue & 0xff;
     *parmDatap++ = (parmValue>>8) & 0xff;
     *parmDatap++ = (parmValue>>16) & 0xff;
-    *parmDatap++ = (parmValue>>24) & 0xff;
+    *parmDatap   = (parmValue>>24) & 0xff;
 }
 
 void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
@@ -2131,7 +2333,7 @@ void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op
         outp->res[1] = inSmbp->res[1];
         op->inCom = inSmbp->com;
     }
-    outp->reb = 0x80;  /* SERVER_RESP */
+    outp->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
     outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
 
     /* copy fields in generic packet area */
@@ -2148,45 +2350,47 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
     long code = 0;
     unsigned char *tp;
     int localNCB = 0;
-#ifdef DJGPP
-    dos_ptr dos_ncb;
-#endif /* DJGPP */
         
     ncbp = inp->ncbp;
     if (ncbp == NULL) {
         ncbp = GetNCB();
         localNCB = 1;
     }
-#ifdef DJGPP
-    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
  
     memset((char *)ncbp, 0, sizeof(NCB));
 
     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 */
     ncbp->ncb_lsn = (unsigned char) vcp->lsn;  /* vc to use */
     ncbp->ncb_lana_num = vcp->lana;
     ncbp->ncb_command = NCBSEND;       /* op means send data */
-#ifndef DJGPP
     ncbp->ncb_buffer = (char *) inp;/* packet */
     code = Netbios(ncbp);
-#else /* DJGPP */
-    ncbp->ncb_buffer = inp->dos_pkt;/* packet */
-    ((smb_ncb_t*)ncbp)->orig_pkt = inp;
-
-    /* copy header information from virtual to DOS address space */
-    dosmemput((char*)inp, SMB_PACKETSIZE, inp->dos_pkt);
-    code = Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
         
-    if (code != 0)
-        osi_Log1(smb_logp, "SendPacket failure code %d", code);
+    if (code != 0) {
+       const char * s = ncb_error_string(code);
+        osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
+       LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_SEND_PACKET_FAILURE, s);
+
+       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);
+           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);
+       } else {
+           lock_ReleaseMutex(&vcp->mx);
+       }
+    }
 
     if (localNCB)
         FreeNCB(ncbp);
@@ -2205,7 +2409,11 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
         NTStatus = 0xC000000FL;        /* No such file */
     }
     else if (code == CM_ERROR_TIMEDOUT) {
+#ifdef COMMENT
         NTStatus = 0xC00000CFL;        /* Sharing Paused */
+#else
+        NTStatus = 0x00000102L; /* Timeout */
+#endif
     }
     else if (code == CM_ERROR_RETRY) {
         NTStatus = 0xC000022DL;        /* Retry */
@@ -2215,7 +2423,7 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     }
     else if (code == CM_ERROR_READONLY) {
         NTStatus = 0xC00000A2L;        /* Write protected */
-    }  
+    }
     else if (code == CM_ERROR_NOSUCHFILE) {
         NTStatus = 0xC000000FL;        /* No such file */
     }
@@ -2295,6 +2503,12 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     else if (code == CM_ERROR_WOULDBLOCK) {
         NTStatus = 0xC0000055L;        /* Lock not granted */
     }
+    else if (code == CM_ERROR_SHARING_VIOLATION) {
+        NTStatus = 0xC0000043L; /* Sharing violation */
+    }
+    else if (code == CM_ERROR_LOCK_CONFLICT) {
+        NTStatus = 0xC0000054L; /* Lock conflict */
+    }
     else if (code == CM_ERROR_PARTIALWRITE) {
         NTStatus = 0xC000007FL;        /* Disk full */
     }
@@ -2320,7 +2534,29 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
         NTStatus = 0xC0000022L; /* Access Denied */
 #endif
     }
-    else {
+    else if (code == CM_ERROR_PATH_NOT_COVERED) {
+        NTStatus = 0xC0000257L; /* Path Not Covered */
+    } 
+#ifdef COMMENT
+    else if (code == CM_ERROR_ALLBUSY) {
+        NTStatus = 0xC00000BFL; /* Network Busy */
+    } 
+    else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
+        NTStatus = 0xC0000350L; /* Remote Host Down */
+    } 
+#else
+    /* we do not want to be telling the SMB/CIFS client that
+     * the AFS Client Service is busy or down.  
+     */
+    else if (code == CM_ERROR_ALLBUSY || 
+             code == CM_ERROR_ALLOFFLINE ||
+            code == CM_ERROR_ALLDOWN) {
+        NTStatus = 0xC00000BEL; /* Bad Network Path */
+    }
+#endif
+    else if (code == RXKADUNKNOWNKEY) {
+       NTStatus = 0xC0000322L; /* Bad Kerberos key */
+    } else {
         NTStatus = 0xC0982001L;        /* SMB non-specific error */
     }
 
@@ -2463,6 +2699,14 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
         class = 1;
         error = 33;    /* lock conflict */
     }
+    else if (code == CM_ERROR_LOCK_CONFLICT) {
+        class = 1;
+        error = 33;     /* lock conflict */
+    }
+    else if (code == CM_ERROR_SHARING_VIOLATION) {
+        class = 1;
+        error = 33;     /* lock conflict */
+    }
     else if (code == CM_ERROR_NOFILES) {
         class = 1;
         error = 18;    /* no files in search */
@@ -2476,6 +2720,10 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
         class = 2;
         error = 2; /* bad password */
     }
+    else if (code == CM_ERROR_PATH_NOT_COVERED) {
+        class = 2;
+        error = 3;     /* bad path */
+    }
     else {
         class = 2;
         error = 1;
@@ -2517,17 +2765,13 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     osi_hyper_t offset;
     long count, minCount, finalCount;
     unsigned short fd;
+    unsigned pid;
     smb_fid_t *fidp;
     long code = 0;
     cm_user_t *userp = NULL;
     NCB *ncbp;
     int rc;
-#ifndef DJGPP
     char *rawBuf = NULL;
-#else
-    dos_ptr rawBuf = NULL;
-    dos_ptr dos_ncb;
-#endif /* DJGPP */
 
     rawBuf = NULL;
     finalCount = 0;
@@ -2535,45 +2779,76 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     fd = smb_GetSMBParm(inp, 0);
     count = smb_GetSMBParm(inp, 3);
     minCount = smb_GetSMBParm(inp, 4);
-    offset.HighPart = 0;       /* too bad */
     offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
 
-    osi_Log3(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
-             fd, offset.LowPart, count);
+    if (*inp->wctp == 10) {
+        /* we were sent a request with 64-bit file offsets */
+#ifdef AFS_LARGEFILES
+        offset.HighPart = smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16);
+
+        if (LargeIntegerLessThanZero(offset)) {
+            osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received negative 64-bit offset");
+            goto send1;
+        }
+#else
+        if ((smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16)) != 0) {
+            osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received 64-bit file offset.  Dropping request.");
+            goto send1;
+        } else {
+            offset.HighPart = 0;
+        }
+#endif
+    } else {
+        /* we were sent a request with 32-bit file offsets */
+        offset.HighPart = 0;
+    }
+
+    osi_Log4(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x:%08x, size 0x%x",
+             fd, offset.HighPart, offset.LowPart, count);
 
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp)
         goto send1;
 
+    pid = ((smb_t *) inp)->pid;
+    {
+        LARGE_INTEGER LOffset, LLength;
+        cm_key_t key;
+
+        key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+        LOffset.HighPart = offset.HighPart;
+        LOffset.LowPart = offset.LowPart;
+        LLength.HighPart = 0;
+        LLength.LowPart = count;
+
+        lock_ObtainMutex(&fidp->scp->mx);
+        code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
+        lock_ReleaseMutex(&fidp->scp->mx);
+    }    
+    if (code) {
+        goto send1a;
+    }
+
     lock_ObtainMutex(&smb_RawBufLock);
     if (smb_RawBufs) {
         /* Get a raw buf, from head of list */
         rawBuf = smb_RawBufs;
-#ifndef DJGPP
         smb_RawBufs = *(char **)smb_RawBufs;
-#else /* DJGPP */
-        smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
-#endif /* !DJGPP */
     }
     lock_ReleaseMutex(&smb_RawBufLock);
     if (!rawBuf)
         goto send1a;
 
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL)
     {
-#ifndef DJGPP
+       lock_ReleaseMutex(&fidp->mx);
         rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
-#else
-        rc = smb_IoctlReadRaw(fidp, vcp, inp, outp, rawBuf);
-#endif
         if (rawBuf) {
             /* Give back raw buffer */
             lock_ObtainMutex(&smb_RawBufLock);
-#ifndef DJGPP
             *((char **) rawBuf) = smb_RawBufs;
-#else /* DJGPP */
-            _farpokel(_dos_ds, rawBuf, smb_RawBufs);
-#endif /* !DJGPP */
             
             smb_RawBufs = rawBuf;
             lock_ReleaseMutex(&smb_RawBufLock);
@@ -2582,16 +2857,11 @@ 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);
-#else /* DJGPP */
-    /* have to give ReadData flag so it will treat buffer as DOS mem. */
-    code = smb_ReadData(fidp, &offset, count, (unsigned char *)rawBuf,
-                        userp, &finalCount, TRUE /* rawFlag */);
-#endif /* !DJGPP */
 
     if (code != 0)
         goto send;
@@ -2604,9 +2874,6 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
 
   send1:
     ncbp = outp->ncbp;
-#ifdef DJGPP
-    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
     memset((char *)ncbp, 0, sizeof(NCB));
 
     ncbp->ncb_length = (unsigned short) finalCount;
@@ -2615,22 +2882,14 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     ncbp->ncb_command = NCBSEND;
     ncbp->ncb_buffer = rawBuf;
 
-#ifndef DJGPP
     code = Netbios(ncbp);
-#else /* DJGPP */
-    code = Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
     if (code != 0)
         osi_Log1(smb_logp, "ReadRaw send failure code %d", code);
 
     if (rawBuf) {
         /* Give back raw buffer */
         lock_ObtainMutex(&smb_RawBufLock);
-#ifndef DJGPP
         *((char **) rawBuf) = smb_RawBufs;
-#else /* DJGPP */
-        _farpokel(_dos_ds, rawBuf, smb_RawBufs);
-#endif /* !DJGPP */
 
         smb_RawBufs = rawBuf;
         lock_ReleaseMutex(&smb_RawBufLock);
@@ -2660,6 +2919,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     int coreProtoIndex;
     int v3ProtoIndex;
     int NTProtoIndex;
+    int VistaProtoIndex;
     int protoIndex;                            /* index we're using */
     int namex;
     int dbytes;
@@ -2668,31 +2928,11 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     char protocol_array[10][1024];  /* protocol signature of the client */
     int caps;                       /* capabilities */
     time_t unixTime;
-    time_t dosTime;
+    afs_uint32 dosTime;
     TIME_ZONE_INFORMATION tzi;
 
     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;
@@ -2700,6 +2940,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     coreProtoIndex = -1;               /* not found */
     v3ProtoIndex = -1;
     NTProtoIndex = -1;
+    VistaProtoIndex = -1;
     while(namex < dbytes) {
         osi_Log1(smb_logp, "Protocol %s",
                   osi_LogSaveString(smb_logp, namep+1));
@@ -2717,9 +2958,12 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         else if (smb_useV3 && strcmp("NT LM 0.12", namep+1) == 0) {
             NTProtoIndex = tcounter;
         }
+        else if (smb_useV3 && strcmp("SMB 2.001", namep+1) == 0) {
+            VistaProtoIndex = tcounter;
+        }
 
         /* 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 */
@@ -2728,7 +2972,14 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         tcounter++;            /* which proto entry we're looking at */
     }
 
-    if (NTProtoIndex != -1) {
+    lock_ObtainMutex(&vcp->mx);
+#if 0
+    if (VistaProtoIndex != -1) {
+        protoIndex = VistaProtoIndex;
+        vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
+    } else 
+#endif 
+       if (NTProtoIndex != -1) {
         protoIndex = NTProtoIndex;
         vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
     }
@@ -2741,10 +2992,11 @@ 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;
-    else if (NTProtoIndex != -1) {
+    else if (VistaProtoIndex != 1 || NTProtoIndex != -1) {
         smb_SetSMBParm(outp, 0, protoIndex);
         if (smb_authType != SMB_AUTH_NONE) {
             smb_SetSMBParmByte(outp, 1,
@@ -2784,6 +3036,9 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 #ifdef DFS_SUPPORT
                NTNEGOTIATE_CAPABILITY_DFS |
 #endif
+#ifdef AFS_LARGEFILES
+               NTNEGOTIATE_CAPABILITY_LARGEFILES |
+#endif
                NTNEGOTIATE_CAPABILITY_NTFIND |
                NTNEGOTIATE_CAPABILITY_RAWMODE |
                NTNEGOTIATE_CAPABILITY_NTSMB;
@@ -2883,9 +3138,57 @@ 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 ) 
+    {
+       if (vcp->magic != SMB_VC_MAGIC)
+           osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", 
+                      __FILE__, __LINE__);
+
+       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++;
@@ -2908,56 +3211,168 @@ void smb_Daemon(void *parmp)
             myTime.tm_sec = 0;
             smb_localZero = mktime(&myTime);
 
+#ifndef USE_NUMERIC_TIME_CONV
             smb_CalculateNowTZ();
-
+#endif /* USE_NUMERIC_TIME_CONV */
 #ifdef AFS_FREELANCE
             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 */
     }
 }
 
 void smb_WaitingLocksDaemon()
 {
-    smb_waitingLock_t *wL, *nwL;
+    smb_waitingLockRequest_t *wlRequest, *nwlRequest;
+    smb_waitingLock_t *wl, *wlNext;
     int first;
     smb_vc_t *vcp;
     smb_packet_t *inp, *outp;
     NCB *ncbp;
     long code = 0;
 
-    while (1) {
+    while (smbShutdownFlag == 0) {
         lock_ObtainWrite(&smb_globalLock);
-        nwL = smb_allWaitingLocks;
-        if (nwL == NULL) {
-            osi_SleepW((long)&smb_allWaitingLocks, &smb_globalLock);
+        nwlRequest = smb_allWaitingLocks;
+        if (nwlRequest == NULL) {
+            osi_SleepW((LONG_PTR)&smb_allWaitingLocks, &smb_globalLock);
             thrd_Sleep(1000);
             continue;
+        } else {
+            first = 1;
+            osi_Log0(smb_logp, "smb_WaitingLocksDaemon starting wait lock check");
         }
-        else first = 1;
+
         do {
             if (first)
                 first = 0;
             else
                 lock_ObtainWrite(&smb_globalLock);
-            wL = nwL;
-            nwL = (smb_waitingLock_t *) osi_QNext(&wL->q);
+
+            osi_Log1(smb_logp, "    Checking waiting lock request %p", nwlRequest);
+
+            wlRequest = nwlRequest;
+            nwlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q);
             lock_ReleaseWrite(&smb_globalLock);
-            code = cm_RetryLock((cm_file_lock_t *) wL->lockp,
-                                 wL->vcp->flags & SMB_VCFLAG_ALREADYDEAD);
+
+            code = 0;
+
+            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. */
+                code = cm_RetryLock( wl->lockp,
+                                     !!(wlRequest->vcp->flags & SMB_VCFLAG_ALREADYDEAD) );
+
+                if (code == 0) {
+                    wl->state = SMB_WAITINGLOCKSTATE_DONE;
+                } else if (code != CM_ERROR_WOULDBLOCK) {
+                    wl->state = SMB_WAITINGLOCKSTATE_ERROR;
+                    break;
+                }
+            }
+
             if (code == CM_ERROR_WOULDBLOCK) {
+
                 /* no progress */
-                if (wL->timeRemaining != 0xffffffff
-                     && (wL->timeRemaining -= 1000) < 0)
+                if (wlRequest->timeRemaining != 0xffffffff
+                     && (wlRequest->timeRemaining -= 1000) < 0)
                     goto endWait;
+
                 continue;
             }
+
           endWait:
-            vcp = wL->vcp;
-            inp = wL->inp;
-            outp = wL->outp;
+
+            if (code != 0) {
+                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);
+
+                lock_ObtainMutex(&scp->mx);
+
+                for (wl = wlRequest->locks; wl; wl = wlNext) {
+                    wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
+                    
+                    cm_Unlock(scp, wlRequest->lockType, wl->LOffset, 
+                              wl->LLength, wl->key, NULL, &req);
+
+                    osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
+
+                    free(wl);
+                }
+                
+                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);
+                    free(wl);
+                }
+            }
+
+            vcp = wlRequest->vcp;
+            inp = wlRequest->inp;
+            outp = wlRequest->outp;
             ncbp = GetNCB();
             ncbp->ncb_length = inp->ncb_length;
             inp->spacep = cm_GetSpace();
@@ -2965,7 +3380,7 @@ void smb_WaitingLocksDaemon()
             /* Remove waitingLock from list */
             lock_ObtainWrite(&smb_globalLock);
             osi_QRemove((osi_queue_t **)&smb_allWaitingLocks,
-                         &wL->q);
+                         &wlRequest->q);
             lock_ReleaseWrite(&smb_globalLock);
 
             /* Resume packet processing */
@@ -2980,11 +3395,11 @@ void smb_WaitingLocksDaemon()
             cm_FreeSpace(inp->spacep);
             smb_FreePacket(inp);
             smb_FreePacket(outp);
-            if (vcp)
-                smb_ReleaseVC(vcp);
+            smb_ReleaseVC(vcp);
+            cm_ReleaseSCache(wlRequest->scp);
             FreeNCB(ncbp);
-            free(wL);
-        } while (nwL);
+            free(wlRequest);
+        } while (nwlRequest && smbShutdownFlag == 0);
         thrd_Sleep(1000);
     }
 }
@@ -3028,14 +3443,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);
@@ -3259,7 +3673,7 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
     long code = 0;
     cm_scache_t *scp;
     char *dptr;
-    time_t dosTime;
+    afs_uint32 dosTime;
     u_short shortTemp;
     char attr;
     smb_dirListPatch_t *patchp;
@@ -3287,6 +3701,8 @@ long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
             continue;
         }
 
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
         attr = smb_Attributes(scp);
         /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
         if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
@@ -3359,9 +3775,9 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     int returnedNames;
     long nextEntryCookie;
     int numDirChunks;          /* # of 32 byte dir chunks in this entry */
-    char resByte;                      /* reserved byte from the cookie */
+    char resByte;              /* reserved byte from the cookie */
     char *op;                  /* output data ptr */
-    char *origOp;                      /* original value of op */
+    char *origOp;              /* original value of op */
     cm_space_t *spacep;                /* for pathname buffer */
     int starPattern;
     int rootPath = 0;
@@ -3431,6 +3847,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         dsp = smb_FindDirSearch(inCookiep[12]);
         if (!dsp) {
             /* can't find dir search status; fatal error */
+            osi_Log3(smb_logp, "SMB receive search dir bad cookie: cookie %d nextCookie %u [%s]",
+                     inCookiep[12], nextCookie, osi_LogSaveString(smb_logp, pathp));
             return CM_ERROR_BADFD;
         }
         attribute = dsp->attribute;
@@ -3449,10 +3867,10 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         starPattern = 1;
     }
 
-    osi_Log3(smb_logp, "SMB dir search cookie 0x%x, connection %d, attr 0x%x",
+    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);
@@ -3460,8 +3878,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         scp = dsp->scp;
         cm_HoldSCache(scp);
         code = 0;
-    }
-    else {
+    } else {
         spacep = inp->spacep;
         smb_StripLastComponent(spacep->data, NULL, pathp);
         code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
@@ -3472,11 +3889,23 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
             smb_ReleaseDirSearch(dsp);
             return CM_ERROR_NOFILES;
         }
-        code = cm_NameI(cm_rootSCachep, spacep->data,
+        code = cm_NameI(cm_data.rootSCachep, spacep->data,
                         caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
         if (code == 0) {
-            if (dsp->scp != 0) 
-                cm_ReleaseSCache(dsp->scp);
+#ifdef DFS_SUPPORT
+            if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+                cm_ReleaseSCache(scp);
+                lock_ReleaseMutex(&dsp->mx);
+                cm_ReleaseUser(userp);
+                smb_DeleteDirSearch(dsp);
+                smb_ReleaseDirSearch(dsp);
+                if ( WANTS_DFS_PATHNAMES(inp) )
+                    return CM_ERROR_PATH_NOT_COVERED;
+                else
+                    return CM_ERROR_BADSHARENAME;
+            }
+#endif /* DFS_SUPPORT */
+
             dsp->scp = scp;
             /* we need one hold for the entry we just stored into,
              * and one for our own processing.  When we're done with this
@@ -3490,6 +3919,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                  && LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
                 scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
                 dsp->flags |= SMB_DIRSEARCH_BULKST;
+               dsp->scp->bulkStatProgress = hzero;
             }
             lock_ReleaseMutex(&scp->mx);
         }
@@ -3521,6 +3951,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         return code;
     }
         
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     dirLength = scp->length;
     bufferp = NULL;
     bufferOffset.LowPart = bufferOffset.HighPart = 0;
@@ -3559,8 +3991,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         /* check if we've returned all the names that will fit in the
          * response packet.
          */
-        if (returnedNames >= maxCount) 
+        if (returnedNames >= maxCount) {
+            osi_Log2(smb_logp, "SMB search dir returnedNames %d >= maxCount %d",
+                      returnedNames, maxCount);
             break;
+        }
                 
         /* check if we've passed the dir's EOF */
         if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) break;
@@ -3570,7 +4005,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
          * of the buffer we have.  If not, get the buffer.
          */
         thyper.HighPart = curOffset.HighPart;
-        thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+        thyper.LowPart = curOffset.LowPart & ~(cm_data.buf_blockSize-1);
         if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
             /* wrong buffer */
             if (bufferp) {
@@ -3593,20 +4028,23 @@ 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();
-                    if (now - req.startTime > 5000) {
+                    int now = GetTickCount();
+                    if (now - req.startTime > RDRtimeout) {
                         scp->bulkStatProgress = thyper;
                         scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
                         dsp->flags &= ~SMB_DIRSEARCH_BULKST;
+                       dsp->scp->bulkStatProgress = hzero;
                     } else
-                        cm_TryBulkStat(scp, &thyper, userp, &req);
+                        code = cm_TryBulkStat(scp, &thyper, userp, &req);
                 }
             } else {
                 lock_ObtainMutex(&scp->mx);
             }
             lock_ReleaseMutex(&dsp->mx);
-            if (code) 
+            if (code) {
+                osi_Log2(smb_logp, "SMB search dir buf_Get scp %x failed %d", scp, code);
                 break;
+            }
 
             bufferOffset = thyper;
 
@@ -3616,13 +4054,25 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                                  PRSFS_LOOKUP,
                                  CM_SCACHESYNC_NEEDCALLBACK |
                                  CM_SCACHESYNC_READ);
-                if (code) break;
+                if (code) {
+                    osi_Log2(smb_logp, "SMB search dir cm_SyncOp scp %x failed %d", scp, code);
+                    break;
+                }
                                 
-                if (cm_HaveBuffer(scp, bufferp, 0)) break;
+               cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
+                if (cm_HaveBuffer(scp, bufferp, 0)) {
+                    osi_Log2(smb_logp, "SMB search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
+                    break;
+                }
 
                 /* otherwise, load the buffer and try again */
                 code = cm_GetBuffer(scp, bufferp, NULL, userp, &req);
-                if (code) break;
+                if (code) {
+                    osi_Log3(smb_logp, "SMB search dir cm_GetBuffer failed scp %x bufferp %x code %d", 
+                              scp, bufferp, code);
+                    break;
+                }
             }
             if (code) {
                 buf_Release(bufferp);
@@ -3635,13 +4085,13 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
          * it out if it represents a non-deleted entry.
          */
         entryInDir = curOffset.LowPart & (2048-1);
-        entryInBuffer = curOffset.LowPart & (buf_bufferSize - 1);
+        entryInBuffer = curOffset.LowPart & (cm_data.buf_blockSize - 1);
 
         /* page header will help tell us which entries are free.  Page header
          * can change more often than once per buffer, since AFS 3 dir page size
          * may be less than (but not more than a buffer package buffer.
          */
-        temp = curOffset.LowPart & (buf_bufferSize - 1);  /* only look intra-buffer */
+        temp = curOffset.LowPart & (cm_data.buf_blockSize - 1);  /* only look intra-buffer */
         temp &= ~(2048 - 1);   /* turn off intra-page bits */
         pageHeaderp = (cm_pageHeader_t *) (bufferp->datap + temp);
 
@@ -3677,6 +4127,10 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
             actualName = shortName;
         }
 
+        osi_Log3(smb_logp, "SMB search dir vn %d name %s (%s)",
+                  dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
+                  osi_LogSaveString(smb_logp, actualName));
+
         if (dep->fid.vnode != 0 && smb_Match8Dot3Mask(actualName, mask)) {
             /* this is one of the entries to use: it is not deleted
              * and it matches the star pattern we're looking for.
@@ -3686,8 +4140,10 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
              * attributes */
 
             /* no hidden files */
-            if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && smb_IsDotFile(actualName))
+            if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && smb_IsDotFile(actualName)) {
+                osi_Log0(smb_logp, "SMB search dir skipping hidden");
                 goto nextEntry;
+            }
 
             if (!(dsp->attribute & SMB_ATTR_DIRECTORY))  /* no directories */
             {
@@ -3700,17 +4156,20 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                 osi_Log2(smb_logp, "smb_ReceiveCoreSearchDir: file %s "
                          "has filetype %d", osi_LogSaveString(smb_logp, dep->name),
                           fileType);
-                if (fileType == CM_SCACHETYPE_DIRECTORY)
-                    goto nextEntry;
+                if (fileType == CM_SCACHETYPE_DIRECTORY ||
+                    fileType == CM_SCACHETYPE_DFSLINK ||
+                    fileType == CM_SCACHETYPE_INVALID)
+                    osi_Log0(smb_logp, "SMB search dir skipping directory or bad link");
+                goto nextEntry;
             }
 
             *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,
@@ -3759,7 +4218,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                 CharToOem(op, op);
 
             /* Uppercase if requested by client */
-            if ((((smb_t *)inp)->flg2 & SMB_FLAGS2_KNOWS_LONG_NAMES) == 0)
+            if (!KNOWS_LONG_NAMES(inp))
                 _strupr(op);
 
             op += 13;
@@ -3777,7 +4236,10 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
     /* release the mutex */
     lock_ReleaseMutex(&scp->mx);
-    if (bufferp) buf_Release(bufferp);
+    if (bufferp) {
+       buf_Release(bufferp);
+       bufferp = NULL;
+    }
 
     /* apply and free last set of patches; if not doing a star match, this
      * will be empty, but better safe (and freeing everything) than sorry.
@@ -3811,8 +4273,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);
@@ -3847,9 +4309,9 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     osi_Log1(smb_logp, "SMB receive check path %s",
              osi_LogSaveString(smb_logp, pathp));
         
-    rootScp = cm_rootSCachep;
+    rootScp = cm_data.rootSCachep;
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -3866,21 +4328,36 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         cm_ReleaseUser(userp);
         return code;
     }
-        
+        
+#ifdef DFS_SUPPORT
+    if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(newScp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     /* now lock the vnode with a callback; returns with newScp locked */
     lock_ObtainMutex(&newScp->mx);
     code = cm_SyncOp(newScp, NULL, userp, &req, PRSFS_LOOKUP,
                      CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
-    if (code && code != CM_ERROR_NOACCESS) {
-        lock_ReleaseMutex(&newScp->mx);
-        cm_ReleaseSCache(newScp);
-        cm_ReleaseUser(userp);
-        return code;
+    if (code) {
+       if (code != CM_ERROR_NOACCESS) {
+           lock_ReleaseMutex(&newScp->mx);
+           cm_ReleaseSCache(newScp);
+           cm_ReleaseUser(userp);
+           return code;
+       }
+    } else {
+       cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     }
 
     attrs = smb_Attributes(newScp);
 
-    if (!(attrs & 0x10))
+    if (!(attrs & SMB_ATTR_DIRECTORY))
         code = CM_ERROR_NOTDIR;
 
     lock_ReleaseMutex(&newScp->mx);
@@ -3898,7 +4375,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     unsigned short attribute;
     cm_attr_t attr;
     cm_scache_t *newScp;
-    time_t dosTime;
+    afs_uint32 dosTime;
     cm_user_t *userp;
     int caseFold;
     char *tidPathp;
@@ -3920,9 +4397,9 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
              dosTime, attribute);
 
-    rootScp = cm_rootSCachep;
+    rootScp = cm_data.rootSCachep;
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
 
@@ -3938,7 +4415,18 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         cm_ReleaseUser(userp);
         return code;
     }
-       
+
+#ifdef DFS_SUPPORT
+    if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(newScp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     /* now lock the vnode with a callback; returns with newScp locked; we
      * need the current status to determine what the new status is, in some
      * cases.
@@ -3953,6 +4441,8 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         return code;
     }
 
+    cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     /* Check for RO volume */
     if (newScp->flags & CM_SCACHEFLAG_RO) {
         lock_ReleaseMutex(&newScp->mx);
@@ -3967,12 +4457,12 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
         smb_UnixTimeFromDosUTime(&attr.clientModTime, dosTime);
     }
-    if ((newScp->unixModeBits & 0222) && (attribute & 1) != 0) {
+    if ((newScp->unixModeBits & 0222) && (attribute & SMB_ATTR_READONLY) != 0) {
         /* we're told to make a writable file read-only */
         attr.unixModeBits = newScp->unixModeBits & ~0222;
         attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
     }
-    else if ((newScp->unixModeBits & 0222) == 0 && (attribute & 1) == 0) {
+    else if ((newScp->unixModeBits & 0222) == 0 && (attribute & SMB_ATTR_READONLY) == 0) {
         /* we're told to make a read-only file writable */
         attr.unixModeBits = newScp->unixModeBits | 0222;
         attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
@@ -3997,7 +4487,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     long code = 0;
     cm_scache_t *rootScp;
     cm_scache_t *newScp, *dscp;
-    time_t dosTime;
+    afs_uint32 dosTime;
     int attrs;
     cm_user_t *userp;
     int caseFold;
@@ -4022,9 +4512,9 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
              osi_LogSaveString(smb_logp, pathp));
 
-    rootScp = cm_rootSCachep;
+    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;
@@ -4060,14 +4550,22 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
                         caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
                         userp, tidPathp, &req, &dscp);
         if (code == 0) {
-            if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT &&
-                !dscp->mountRootFidp)
+#ifdef DFS_SUPPORT
+            if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                if ( WANTS_DFS_PATHNAMES(inp) )
+                    return CM_ERROR_PATH_NOT_COVERED;
+                else
+                    return CM_ERROR_BADSHARENAME;
+            } else
+#endif /* DFS_SUPPORT */
+            if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
                 code = CM_ERROR_NOSUCHFILE;
             else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
                 cm_buf_t *bp = buf_Find(dscp, &hzero);
-                if (bp)
+                if (bp) {
                     buf_Release(bp);
-                else
+                   bp = NULL;
+               } else
                     code = CM_ERROR_NOSUCHFILE;
             }
             cm_ReleaseSCache(dscp);
@@ -4086,6 +4584,17 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         return code;
     }
         
+#ifdef DFS_SUPPORT
+    if (newScp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(newScp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     /* now lock the vnode with a callback; returns with newScp locked */
     lock_ObtainMutex(&newScp->mx);
     code = cm_SyncOp(newScp, NULL, userp, &req, 0,
@@ -4097,12 +4606,15 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         return code;
     }
 
+    cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
 #ifdef undef
     /* use smb_Attributes instead.   Also the fact that a file is 
      * in a readonly volume doesn't mean it shojuld be marked as RO 
      */
     if (newScp->fileType == CM_SCACHETYPE_DIRECTORY ||
-        newScp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+        newScp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+       newScp->fileType == CM_SCACHETYPE_INVALID)
         attrs = SMB_ATTR_DIRECTORY;
     else
         attrs = 0;
@@ -4142,9 +4654,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);
     }
 
@@ -4161,7 +4673,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     long code = 0;
     cm_user_t *userp;
     cm_scache_t *scp;
-    time_t dosTime;
+    afs_uint32 dosTime;
     int caseFold;
     cm_space_t *spacep;
     char *tidPathp;
@@ -4210,7 +4722,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;
 
@@ -4219,7 +4731,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
+    code = cm_NameI(cm_data.rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp,
                     tidPathp, &req, &scp);
         
     if (code) {
@@ -4227,6 +4739,17 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         return code;
     }
 
+#ifdef DFS_SUPPORT
+    if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     code = cm_CheckOpen(scp, share & 0x7, 0, userp, &req);
     if (code) {
         cm_ReleaseSCache(scp);
@@ -4249,13 +4772,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);
@@ -4321,7 +4849,7 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
         code = cm_Unlink(dscp, dep->name, rockp->userp, rockp->reqp);
         if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
             smb_NotifyChange(FILE_ACTION_REMOVED,
-                             FILE_NOTIFY_CHANGE_FILE_NAME,
+                            FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
                              dscp, dep->name, NULL, TRUE);
         if (code == 0) {
             rockp->any = 1;
@@ -4367,7 +4895,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;
 
@@ -4376,14 +4904,24 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold, userp, tidPathp,
                     &req, &dscp);
-
     if (code) {
         cm_ReleaseUser(userp);
         return code;
     }
         
+#ifdef DFS_SUPPORT
+    if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(dscp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     /* otherwise, scp points to the parent directory. */
     if (!lastNamep) 
         lastNamep = pathp;
@@ -4496,7 +5034,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);
@@ -4507,28 +5045,27 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
 
-    /*
-     * Changed to use CASEFOLD always.  This enables us to rename Foo/baz when
-     * what actually exists is foo/baz.  I don't know why the code used to be
-     * the way it was.  1/29/96
-     *
-     *         caseFold = ((vcp->flags & SMB_VCFLAG_USEV3) ? 0: CM_FLAG_CASEFOLD);
-     *
-     * Changed to use CM_FLAG_FOLLOW.  7/24/96
-     *
-     * caseFold = CM_FLAG_CASEFOLD;
-     */
     caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
-    code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
                     userp, tidPathp, &req, &oldDscp);
-
     if (code) {
         cm_ReleaseUser(userp);
         return code;
     }
         
+#ifdef DFS_SUPPORT
+    if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(oldDscp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
-    code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
                     userp, tidPathp, &req, &newDscp);
 
     if (code) {
@@ -4536,7 +5073,20 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
         cm_ReleaseUser(userp);
         return code;
     }
-        
+
+#ifdef DFS_SUPPORT
+    if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(oldDscp);
+        cm_ReleaseSCache(newDscp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
+
     /* otherwise, oldDscp and newDscp point to the corresponding directories.
      * next, get the component names, and lower case them.
      */
@@ -4584,7 +5134,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
                 else 
                     code = CM_ERROR_EXISTS;
                 cm_ReleaseSCache(tmpscp2);
-                               tmpscp2 = NULL;
+                tmpscp2 = NULL;
             } else {
                 code = CM_ERROR_NOSUCHFILE;
             }
@@ -4607,6 +5157,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     thyper.HighPart = 0;
 
     code = cm_ApplyDir(oldDscp, smb_RenameProc, &rock, &thyper, userp, &req, NULL);
+    osi_Log1(smb_logp, "smb_RenameProc returns %ld", code);
 
     if (code == CM_ERROR_STOPNOW)
         code = 0;
@@ -4661,7 +5212,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) {
@@ -4676,15 +5227,26 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
     
-    code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
                     userp, tidPathp, &req, &oldDscp);
     if (code) {
         cm_ReleaseUser(userp);
         return code;
     }
         
+#ifdef DFS_SUPPORT
+    if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(oldDscp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
-    code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
                     userp, tidPathp, &req, &newDscp);
     if (code) {
         cm_ReleaseSCache(oldDscp);
@@ -4692,6 +5254,18 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
         return code;
     }
 
+#ifdef DFS_SUPPORT
+    if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(newDscp);
+        cm_ReleaseSCache(oldDscp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     /* Now, although we did two lookups for the two directories (because the same
      * directory can be referenced through different paths), we only allow hard links
      * within the same directory. */
@@ -4752,7 +5326,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
     /* now create the hardlink */
     osi_Log1(smb_logp,"  Attempting to create new link [%s]", osi_LogSaveString(smb_logp, newLastNamep));
     code = cm_Link(newDscp, newLastNamep, sscp, 0, userp, &req);
-    osi_Log1(smb_logp,"  Link returns %d", code);
+    osi_Log1(smb_logp,"  Link returns 0x%x", code);
 
     /* Handle Change Notification */
     if (code == 0) {
@@ -4833,7 +5407,7 @@ int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper
         code = cm_RemoveDir(dscp, dep->name, rockp->userp, rockp->reqp);
         if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
             smb_NotifyChange(FILE_ACTION_REMOVED,
-                             FILE_NOTIFY_CHANGE_DIR_NAME,
+                             FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
                              dscp, dep->name, NULL, TRUE);
         if (code == 0)
             rockp->any = 1;
@@ -4868,7 +5442,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;
 
@@ -4877,7 +5451,7 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
                     userp, tidPathp, &req, &dscp);
 
     if (code) {
@@ -4885,6 +5459,17 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         return code;
     }
         
+#ifdef DFS_SUPPORT
+    if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(dscp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     /* otherwise, scp points to the parent directory. */
     if (!lastNamep) 
         lastNamep = pathp;
@@ -4934,20 +5519,30 @@ 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)
-        code = cm_FSync(fidp->scp, userp, &req);
-    else 
+    if (fidp->flags & SMB_FID_OPENWRITE) {
+       cm_scache_t * scp = fidp->scp;
+       cm_HoldSCache(scp);
+       lock_ReleaseMutex(&fidp->mx);
+        code = cm_FSync(scp, userp, &req);
+       cm_ReleaseSCache(scp);
+    } else {
         code = 0;
-    lock_ReleaseMutex(&fidp->mx);
+       lock_ReleaseMutex(&fidp->mx);
+    }
         
     smb_ReleaseFID(fidp);
         
@@ -5003,32 +5598,44 @@ 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;
-    long 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;
+    cm_scache_t * scp = fidp->scp;
+    int deleted = 0;
+    int nullcreator = 0;
+
+    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);
@@ -5036,54 +5643,148 @@ 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 &&
+    if (scp != NULL &&
         (fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
          == SMB_FID_OPENWRITE) {
         if (dosTime != 0 && dosTime != -1) {
-            fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+            scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
             /* This fixes defect 10958 */
             CompensateForSmbClientLastWriteTimeBugs(&dosTime);
             smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
         }
-        code = cm_FSync(fidp->scp, userp, &req);
+       lock_ReleaseMutex(&fidp->mx);
+        code = cm_FSync(scp, userp, &req);
+       lock_ObtainMutex(&fidp->mx);
     }
     else 
         code = 0;
 
+    /* unlock any pending locks */
+    if (!(fidp->flags & SMB_FID_IOCTL) && scp &&
+        scp->fileType == CM_SCACHETYPE_FILE) {
+        cm_key_t key;
+        long tcode;
+
+       lock_ReleaseMutex(&fidp->mx);
+
+       /* CM_UNLOCK_BY_FID doesn't look at the process ID.  We pass
+           in zero. */
+        key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
+        lock_ObtainMutex(&scp->mx);
+
+        tcode = cm_SyncOp(scp, NULL, userp, &req, 0,
+                          CM_SCACHESYNC_NEEDCALLBACK
+                          | CM_SCACHESYNC_GETSTATUS
+                          | CM_SCACHESYNC_LOCK);
+
+        if (tcode) {
+            osi_Log1(smb_logp,
+                     "smb CoreClose SyncOp failure code 0x%x", tcode);
+            goto post_syncopdone;
+        }
+
+        cm_UnlockByKey(scp, key, CM_UNLOCK_BY_FID, userp, &req);
+
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+
+    post_syncopdone:
+
+        lock_ReleaseMutex(&scp->mx);
+       lock_ObtainMutex(&fidp->mx);
+    }
+
     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);
-        if (fidp->scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+       lock_ReleaseMutex(&fidp->mx);
+        smb_FullName(dscp, scp, pathp, &fullPathp, userp, &req);
+        if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
             code = cm_RemoveDir(dscp, fullPathp, userp, &req);
-            if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                smb_NotifyChange(FILE_ACTION_REMOVED,
-                                 FILE_NOTIFY_CHANGE_DIR_NAME,
-                                 dscp, fullPathp, NULL, TRUE);
-        }
-        else 
-        {
+           if (code == 0) {
+               deleted = 1;
+               if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+                   smb_NotifyChange(FILE_ACTION_REMOVED,
+                                     FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
+                                     dscp, fullPathp, NULL, TRUE);
+           }
+        } else {
             code = cm_Unlink(dscp, fullPathp, userp, &req);
-            if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                smb_NotifyChange(FILE_ACTION_REMOVED,
-                                 FILE_NOTIFY_CHANGE_FILE_NAME,
-                                 dscp, fullPathp, NULL, TRUE);
+           if (code == 0) {                            
+               deleted = 1;
+               if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+                   smb_NotifyChange(FILE_ACTION_REMOVED,
+                                     FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
+                                     dscp, fullPathp, NULL, TRUE);
+           }
         }
         free(fullPathp);
+       lock_ObtainMutex(&fidp->mx);
+       fidp->flags &= ~SMB_FID_DELONCLOSE;
+    }
+
+    /* if this was a newly created file, then clear the creator
+     * in the stat cache entry. */
+    if (fidp->flags & SMB_FID_CREATED) {
+       nullcreator = 1;
+       fidp->flags &= ~SMB_FID_CREATED;
     }
-    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;
+    }
+    fidp->scp = NULL;
+    lock_ReleaseMutex(&fidp->mx);
+
+    if (dscp)
+       cm_ReleaseSCache(dscp);
+
+    if (scp) {
+       if (deleted || nullcreator) {
+           lock_ObtainMutex(&scp->mx);
+           if (nullcreator && scp->creator == userp)
+               scp->creator = NULL;
+           if (deleted)
+               scp->flags |= CM_SCACHEFLAG_DELETED;
+           lock_ReleaseMutex(&scp->mx);
+       }
+       cm_ReleaseSCache(scp);
+    }
+
+    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);
@@ -5093,13 +5794,8 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 /*
  * smb_ReadData -- common code for Read, Read And X, and Raw Read
  */
-#ifndef DJGPP
 long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        cm_user_t *userp, long *readp)
-#else /* DJGPP */
-long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
-       cm_user_t *userp, long *readp, int dosflag)
-#endif /* !DJGPP */
 {
     osi_hyper_t offset;
     long code = 0;
@@ -5111,7 +5807,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     osi_hyper_t bufferOffset;
     long bufIndex, nbytes;
     int chunk;
-    int sequential = 0;
+    int sequential = (fidp->flags & SMB_FID_SEQUENTIAL);
     cm_req_t req;
 
     cm_InitReq(&req);
@@ -5129,14 +5825,18 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
             fidp->prev_chunk = fidp->curr_chunk;
             fidp->curr_chunk = chunk;
         }
-        if (fidp->curr_chunk == fidp->prev_chunk + 1)
+        if (!(fidp->flags & SMB_FID_RANDOM) && (fidp->curr_chunk == fidp->prev_chunk + 1))
             sequential = 1;
-    }       
+    }
+    lock_ReleaseMutex(&fidp->mx);
 
     /* start by looking up the file's end */
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-    if (code) goto done;
+    if (code) 
+       goto done;
+
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
     /* now we have the entry locked, look up the length */
     fileLength = scp->length;
@@ -5170,7 +5870,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
         /* otherwise, load up a buffer of data */
         thyper.HighPart = offset.HighPart;
-        thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
+        thyper.LowPart = offset.LowPart & ~(cm_data.buf_blockSize-1);
         if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
             /* wrong buffer */
             if (bufferp) {
@@ -5192,8 +5892,11 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                 code = cm_SyncOp(scp, bufferp, userp, &req, 0,
                                  CM_SCACHESYNC_NEEDCALLBACK |
                                  CM_SCACHESYNC_READ);
-                if (code) goto done;
-                                
+                if (code) 
+                   goto done;
+                    
+               cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
                 if (cm_HaveBuffer(scp, bufferp, 0)) break;
 
                 /* otherwise, load the buffer and try again */
@@ -5210,19 +5913,14 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
         /* now we have the right buffer loaded.  Copy out the
          * data from here to the user's buffer.
          */
-        bufIndex = offset.LowPart & (buf_bufferSize - 1);
+        bufIndex = offset.LowPart & (cm_data.buf_blockSize - 1);
 
         /* and figure out how many bytes we want from this buffer */
-        nbytes = buf_bufferSize - bufIndex;    /* what remains in buffer */
+        nbytes = cm_data.buf_blockSize - bufIndex;     /* what remains in buffer */
         if (nbytes > count) nbytes = count;    /* don't go past EOF */
 
         /* now copy the data */
-#ifdef DJGPP
-        if (dosflag)
-            dosmemput(bufferp->datap + bufIndex, nbytes, (dos_ptr)op);
-        else
-#endif /* DJGPP */
-            memcpy(op, bufferp->datap + bufIndex, nbytes);
+       memcpy(op, bufferp->datap + bufIndex, nbytes);
                 
         /* adjust counters, pointers, etc. */
         op += nbytes;
@@ -5234,8 +5932,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
   done:
     lock_ReleaseMutex(&scp->mx);
-    lock_ReleaseMutex(&fidp->mx);
-    if (bufferp) 
+    if (bufferp)
         buf_Release(bufferp);
 
     if (code == 0 && sequential)
@@ -5247,13 +5944,8 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 /*
  * smb_WriteData -- common code for Write and Raw Write
  */
-#ifndef DJGPP
 long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
        cm_user_t *userp, long *writtenp)
-#else /* DJGPP */
-long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
-       cm_user_t *userp, long *writtenp, int dosflag)
-#endif /* !DJGPP */
 {
     osi_hyper_t offset;
     long code = 0;
@@ -5284,26 +5976,29 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     offset = *offsetp;
 
     lock_ObtainMutex(&fidp->mx);
+    /* make sure we have a writable FD */
+    if (!(fidp->flags & SMB_FID_OPENWRITE)) {
+       osi_Log2(smb_logp, "smb_WriteData fid %d not OPENWRITE flags 0x%x",
+                 fidp->fid, fidp->flags);
+       lock_ReleaseMutex(&fidp->mx);
+        code = CM_ERROR_BADFDOP;
+        goto done;
+    }
+    
     scp = fidp->scp;
-    lock_ObtainMutex(&scp->mx);
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
 
+    lock_ObtainMutex(&scp->mx);
     /* start by looking up the file's end */
-    osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|SETSTATUS|GETSTATUS",
-              fidp->fid);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK
                       | CM_SCACHESYNC_SETSTATUS
                       | CM_SCACHESYNC_GETSTATUS);
-    osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|SETSTATUS|GETSTATUS returns %d",
-              fidp->fid,code);
     if (code) 
         goto done;
         
-    /* make sure we have a writable FD */
-    if (!(fidp->flags & SMB_FID_OPENWRITE)) {
-        code = CM_ERROR_BADFDOP;
-        goto done;
-    }
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_SETSTATUS | CM_SCACHESYNC_GETSTATUS);
 
     /* now we have the entry locked, look up the length */
     fileLength = scp->length;
@@ -5347,13 +6042,13 @@ 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;
         }
 
         /* otherwise, load up a buffer of data */
         thyper.HighPart = offset.HighPart;
-        thyper.LowPart = offset.LowPart & ~(buf_bufferSize-1);
+        thyper.LowPart = offset.LowPart & ~(cm_data.buf_blockSize-1);
         if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
             /* wrong buffer */
             if (bufferp) {
@@ -5375,17 +6070,18 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
             /* now get the data in the cache */
             while (1) {
-                osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|WRITE|BUFLOCKED",
-                          fidp->fid);
                 code = cm_SyncOp(scp, bufferp, userp, &req, 0,
                                   CM_SCACHESYNC_NEEDCALLBACK
                                   | CM_SCACHESYNC_WRITE
                                   | CM_SCACHESYNC_BUFLOCKED);
-                osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp NEEDCALLBACK|WRITE|BUFLOCKED returns %d",
-                          fidp->fid,code);
                 if (code) 
                     goto done;
 
+               cm_SyncOpDone(scp, bufferp, 
+                              CM_SCACHESYNC_NEEDCALLBACK 
+                              | CM_SCACHESYNC_WRITE 
+                              | CM_SCACHESYNC_BUFLOCKED);
+
                 /* If we're overwriting the entire buffer, or
                  * if we're writing at or past EOF, mark the
                  * buffer as current so we don't call
@@ -5401,14 +6097,14 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                  */
                 if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength)
                      || LargeIntegerEqualTo(offset, bufferp->offset)
-                     && (count >= buf_bufferSize
+                     && (count >= cm_data.buf_blockSize
                           || LargeIntegerGreaterThanOrEqualTo(LargeIntegerAdd(offset,
                                                                                ConvertLongToLargeInteger(count)),
                                                                minLength))) {
-                    if (count < buf_bufferSize
+                    if (count < cm_data.buf_blockSize
                          && bufferp->dataVersion == -1)
                         memset(bufferp->datap, 0,
-                                buf_bufferSize);
+                                cm_data.buf_blockSize);
                     bufferp->dataVersion = scp->dataVersion;
                 }
 
@@ -5434,20 +6130,15 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
         /* now we have the right buffer loaded.  Copy out the
          * data from here to the user's buffer.
          */
-        bufIndex = offset.LowPart & (buf_bufferSize - 1);
+        bufIndex = offset.LowPart & (cm_data.buf_blockSize - 1);
 
         /* and figure out how many bytes we want from this buffer */
-        nbytes = buf_bufferSize - bufIndex;    /* what remains in buffer */
+        nbytes = cm_data.buf_blockSize - bufIndex;     /* what remains in buffer */
         if (nbytes > count) 
             nbytes = count;    /* don't go past end of request */
 
         /* now copy the data */
-#ifdef DJGPP
-        if (dosflag)
-            dosmemget((dos_ptr)op, nbytes, bufferp->datap + bufIndex);
-        else
-#endif /* DJGPP */
-            memcpy(bufferp->datap + bufIndex, op, nbytes);
+       memcpy(bufferp->datap + bufIndex, op, nbytes);
         buf_SetDirty(bufferp);
 
         /* and record the last writer */
@@ -5469,18 +6160,20 @@ 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);
     }
 
+    lock_ObtainMutex(&fidp->mx);
     if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
          && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
         smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
                           fidp->NTopen_dscp, fidp->NTopen_pathp,
                           NULL, TRUE);
     }       
+    lock_ReleaseMutex(&fidp->mx);
 
     if (code == 0 && doWriteBack) {
         long code2;
@@ -5488,23 +6181,29 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
         osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
                   fidp->fid);
         code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
-        osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns %d",
-                  fidp->fid,code2);
+        osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns 0x%x",
+                  fidp->fid, code2);
         lock_ReleaseMutex(&scp->mx);
         cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
                             writeBackOffset.HighPart, cm_chunkSize, 0, userp);
+       /* cm_SyncOpDone is called at the completion of cm_BkgStore */
     }
 
-    osi_Log3(smb_logp, "smb_WriteData fid %d returns %d written %d",
+    cm_ReleaseSCache(scp);
+
+    osi_Log3(smb_logp, "smb_WriteData fid %d returns 0x%x written %d bytes",
               fidp->fid, code, *writtenp);
     return code;
 }
 
 long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    osi_hyper_t offset;
-    long count, written = 0, total_written = 0;
     unsigned short fd;
+    unsigned short count;
+    osi_hyper_t offset;
+    unsigned short hint;
+    long written = 0, total_written = 0;
+    unsigned pid;
     smb_fid_t *fidp;
     long code = 0;
     cm_user_t *userp;
@@ -5515,7 +6214,8 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fd = smb_GetSMBParm(inp, 0);
     count = smb_GetSMBParm(inp, 1);
     offset.HighPart = 0;       /* too bad */
-    offset.LowPart = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
+    offset.LowPart = smb_GetSMBParmLong(inp, 2);
+    hint = smb_GetSMBParm(inp, 4);
 
     op = smb_GetSMBData(inp, NULL);
     op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
@@ -5526,18 +6226,50 @@ 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) {
+       osi_Log0(smb_logp, "smb_ReceiveCoreWrite fid not found");
         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);
+       osi_Log1(smb_logp, "smb_ReceiveCoreWrite ioctl code 0x%x", code);
+       return code;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
-       /* special case: 0 bytes transferred means truncate to this position */
+    {
+        cm_key_t key;
+        LARGE_INTEGER LOffset;
+        LARGE_INTEGER LLength;
+
+        pid = ((smb_t *) inp)->pid;
+        key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+        LOffset.HighPart = offset.HighPart;
+        LOffset.LowPart = offset.LowPart;
+        LLength.HighPart = 0;
+        LLength.LowPart = count;
+
+        lock_ObtainMutex(&fidp->scp->mx);
+        code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
+        lock_ReleaseMutex(&fidp->scp->mx);
+
+        if (code) {
+           osi_Log1(smb_logp, "smb_ReceiveCoreWrite lock check failure 0x%x", code);
+            goto done;
+       }
+    }
+
+    /* special case: 0 bytes transferred means truncate to this position */
     if (count == 0) {
         cm_req_t req;
 
+       osi_Log1(smb_logp, "smb_ReceiveCoreWrite truncation to length 0x%x", offset.LowPart);
+        
         cm_InitReq(&req);
 
         truncAttr.mask = CM_ATTRMASK_LENGTH;
@@ -5545,11 +6277,11 @@ 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;
+       smb_SetSMBParm(outp, 0, 0 /* count */);
+       smb_SetSMBDataLength(outp, 0);
+       goto done;
     }
 
     /*
@@ -5562,31 +6294,35 @@ 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 ) {
-#ifndef DJGPP
        code = smb_WriteData(fidp, &offset, count, op, userp, &written);
-#else /* DJGPP */
-       code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
-#endif /* !DJGPP */
        if (code == 0 && written == 0)
             code = CM_ERROR_PARTIALWRITE;
 
-        offset.LowPart += written;
+        offset = LargeIntegerAdd(offset,
+                                 ConvertLongToLargeInteger(written));
         count -= written;
         total_written += written;
         written = 0;
     }
     
+    osi_Log2(smb_logp, "smb_ReceiveCoreWrite total written 0x%x code 0x%x",
+             total_written, code);
+        
     /* set the packet data length to 3 bytes for the data block header,
      * plus the size of the data.
      */
     smb_SetSMBParm(outp, 0, total_written);
+    smb_SetSMBParmLong(outp, 1, offset.LowPart);
+    smb_SetSMBParm(outp, 3, hint);
     smb_SetSMBDataLength(outp, 0);
 
   done:
@@ -5602,33 +6338,21 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
     unsigned short fd;
     smb_fid_t *fidp;
     cm_user_t *userp;
-#ifndef DJGPP
     char *rawBuf;
-#else /* DJGPP */
-    dos_ptr rawBuf;
-#endif /* !DJGPP */
     long written = 0;
     long code = 0;
 
     fd = smb_GetSMBParm(inp, 0);
     fidp = smb_FindFID(vcp, fd, 0);
 
-    osi_Log2(smb_logp, "Completing Raw Write offset %x count %x",
-             rwcp->offset.LowPart, rwcp->count);
+    osi_Log3(smb_logp, "Completing Raw Write offset 0x%x:%08x count %x",
+             rwcp->offset.HighPart, rwcp->offset.LowPart, rwcp->count);
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
-#ifndef DJGPP
     rawBuf = rwcp->buf;
     code = smb_WriteData(fidp, &rwcp->offset, rwcp->count, rawBuf, userp,
                                                 &written);
-#else /* DJGPP */
-    rawBuf = (dos_ptr) rwcp->buf;
-    code = smb_WriteData(fidp, &rwcp->offset, rwcp->count,
-                         (unsigned char *) rawBuf, userp,
-                         &written, TRUE);
-#endif /* !DJGPP */
-
     if (rwcp->writeMode & 0x1) {       /* synchronous */
         smb_t *op;
 
@@ -5650,11 +6374,7 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
 
     /* Give back raw buffer */
     lock_ObtainMutex(&smb_RawBufLock);
-#ifndef DJGPP
     *((char **)rawBuf) = smb_RawBufs;
-#else /* DJGPP */
-    _farpokel(_dos_ds, rawBuf, smb_RawBufs);
-#endif /* !DJGPP */
     smb_RawBufs = rawBuf;
     lock_ReleaseMutex(&smb_RawBufLock);
 
@@ -5678,33 +6398,80 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     cm_user_t *userp;
     char *op;
     unsigned short writeMode;
-#ifndef DJGPP
     char *rawBuf;
-#else /* DJGPP */
-    dos_ptr rawBuf;
-#endif /* !DJGPP */
-
     fd = smb_GetSMBParm(inp, 0);
     totalCount = smb_GetSMBParm(inp, 1);
     count = smb_GetSMBParm(inp, 10);
-    offset.HighPart = 0;       /* too bad */
-    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
     writeMode = smb_GetSMBParm(inp, 7);
 
     op = (char *) inp->data;
     op += smb_GetSMBParm(inp, 11);
 
+    offset.HighPart = 0;
+    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+
+    if (*inp->wctp == 14) {
+        /* we received a 64-bit file offset */
+#ifdef AFS_LARGEFILES
+        offset.HighPart = smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16);
+
+        if (LargeIntegerLessThanZero(offset)) {
+            osi_Log2(smb_logp,
+                     "smb_ReceiveCoreWriteRaw received negative file offset 0x%x:%08x",
+                     offset.HighPart, offset.LowPart);
+            return CM_ERROR_BADSMB;
+        }
+#else
+        if ((smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16)) != 0) {
+            osi_Log0(smb_logp,
+                     "smb_ReceiveCoreWriteRaw received 64-bit file offset, but we don't support large files");
+            return CM_ERROR_BADSMB;
+        }
+
+        offset.HighPart = 0;
+#endif
+    } else {
+        offset.HighPart = 0;    /* 32-bit file offset */
+    }
+    
     osi_Log4(smb_logp,
-             "smb_ReceiveCoreWriteRaw fd %d, off 0x%x, size 0x%x, WriteMode 0x%x",
-             fd, offset.LowPart, count, writeMode);
+             "smb_ReceiveCoreWriteRaw fd %d, off 0x%x:%08x, size 0x%x",
+             fd, offset.HighPart, offset.LowPart, count);
+    osi_Log1(smb_logp,
+             "               WriteRaw WriteMode 0x%x",
+             writeMode);
         
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp) {
         return CM_ERROR_BADFD;
     }
+
+    {
+        unsigned pid;
+        cm_key_t key;
+        LARGE_INTEGER LOffset;
+        LARGE_INTEGER LLength;
+
+        pid = ((smb_t *) inp)->pid;
+        key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+        LOffset.HighPart = offset.HighPart;
+        LOffset.LowPart = offset.LowPart;
+        LLength.HighPart = 0;
+        LLength.LowPart = count;
+
+        lock_ObtainMutex(&fidp->scp->mx);
+        code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
+        lock_ReleaseMutex(&fidp->scp->mx);
+
+        if (code) {
+            smb_ReleaseFID(fidp);
+            return code;
+        }
+    }
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     /*
      * Work around bug in NT client
@@ -5716,22 +6483,22 @@ 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 ) {
-#ifndef DJGPP
        code = smb_WriteData(fidp, &offset, count, op, userp, &written);
-#else /* DJGPP */
-       code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
-#endif /* !DJGPP */
        if (code == 0 && written == 0)
             code = CM_ERROR_PARTIALWRITE;
 
-        offset.LowPart += written;
+        offset = LargeIntegerAdd(offset,
+                                 ConvertLongToLargeInteger(written));
+
         count -= written;
         total_written += written;
         written = 0;
@@ -5744,11 +6511,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         if (smb_RawBufs) {
             /* Get a raw buf, from head of list */
             rawBuf = smb_RawBufs;
-#ifndef DJGPP
             smb_RawBufs = *(char **)smb_RawBufs;
-#else /* DJGPP */
-            smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
-#endif /* !DJGPP */
         }
         else
             code = CM_ERROR_USESTD;
@@ -5775,10 +6538,13 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         return code;
     }
 
+    offset = LargeIntegerAdd(offset,
+                             ConvertLongToLargeInteger(count));
+
     rwcp->code = 0;
     rwcp->buf = rawBuf;
-    rwcp->offset.HighPart = 0;
-    rwcp->offset.LowPart = offset.LowPart + count;
+    rwcp->offset.HighPart = offset.HighPart;
+    rwcp->offset.LowPart = offset.LowPart;
     rwcp->count = totalCount - count;
     rwcp->writeMode = writeMode;
     rwcp->alreadyWritten = total_written;
@@ -5797,6 +6563,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     osi_hyper_t offset;
     long count, finalCount;
     unsigned short fd;
+    unsigned pid;
     smb_fid_t *fidp;
     long code = 0;
     cm_user_t *userp;
@@ -5812,15 +6579,40 @@ 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) {
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_IoctlRead(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
     }
+    lock_ReleaseMutex(&fidp->mx);
+
+    {
+        LARGE_INTEGER LOffset, LLength;
+        cm_key_t key;
+
+        pid = ((smb_t *) inp)->pid;
+        key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+        LOffset.HighPart = 0;
+        LOffset.LowPart = offset.LowPart;
+        LLength.HighPart = 0;
+        LLength.LowPart = count;
         
-    if (fidp->flags & SMB_FID_IOCTL) {
-        return smb_IoctlRead(fidp, vcp, inp, outp);
+        lock_ObtainMutex(&fidp->scp->mx);
+        code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
+        lock_ReleaseMutex(&fidp->scp->mx);
+    }
+    if (code) {
+        smb_ReleaseFID(fidp);
+        return code;
     }
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     /* remember this for final results */
     smb_SetSMBParm(outp, 0, count);
@@ -5844,11 +6636,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     *op++ = (unsigned char) (count & 0xff);
     *op++ = (unsigned char) ((count >> 8) & 0xff);
                 
-#ifndef DJGPP
     code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
-#else /* DJGPP */
-    code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
-#endif /* !DJGPP */
 
     /* fix some things up */
     smb_SetSMBParm(outp, 0, finalCount);
@@ -5894,7 +6682,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;
 
@@ -5904,7 +6692,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         return CM_ERROR_NOSUCHPATH;
     }
 
-    code = cm_NameI(cm_rootSCachep, spacep->data,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data,
                     caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
                     userp, tidPathp, &req, &dscp);
 
@@ -5913,6 +6701,17 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         return code;
     }
         
+#ifdef DFS_SUPPORT
+    if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(dscp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     /* otherwise, scp points to the parent directory.  Do a lookup, and
      * fail if we find it.  Otherwise, we do the create.
      */
@@ -5983,9 +6782,10 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     int attributes;
     char *lastNamep;
     int caseFold;
-    long dosTime;
+    afs_uint32 dosTime;
     char *tidPathp;
     cm_req_t req;
+    int created = 0;                   /* the file was new */
 
     cm_InitReq(&req);
 
@@ -5997,7 +6797,8 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     /* compute initial mode bits based on read-only flag in attributes */
     initialModeBits = 0666;
-    if (attributes & 1) initialModeBits &= ~0222;
+    if (attributes & SMB_ATTR_READONLY) 
+       initialModeBits &= ~0222;
         
     tp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(tp, &tp);
@@ -6007,7 +6808,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;
 
@@ -6016,7 +6817,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
+    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
                     userp, tidPathp, &req, &dscp);
 
     if (code) {
@@ -6024,6 +6825,17 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         return code;
     }
         
+#ifdef DFS_SUPPORT
+    if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+        cm_ReleaseSCache(dscp);
+        cm_ReleaseUser(userp);
+        if ( WANTS_DFS_PATHNAMES(inp) )
+            return CM_ERROR_PATH_NOT_COVERED;
+        else
+            return CM_ERROR_BADSHARENAME;
+    }
+#endif /* DFS_SUPPORT */
+
     /* otherwise, scp points to the parent directory.  Do a lookup, and
      * truncate the file if we find it, otherwise we create the file.
      */
@@ -6074,11 +6886,13 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
         code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
                          &req);
-        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-            smb_NotifyChange(FILE_ACTION_ADDED,
-                             FILE_NOTIFY_CHANGE_FILE_NAME,
-                             dscp, lastNamep, NULL, TRUE);
-        if (!excl && code == CM_ERROR_EXISTS) {
+        if (code == 0) {
+           created = 1;
+           if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+               smb_NotifyChange(FILE_ACTION_ADDED,     
+                                FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
+                                dscp, lastNamep, NULL, TRUE);
+       } else if (!excl && code == CM_ERROR_EXISTS) {
             /* not an exclusive create, and someone else tried
              * creating it already, then we open it anyway.  We
              * don't bother retrying after this, since if this next
@@ -6117,19 +6931,28 @@ 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);
-        
+    /* remember that the file was newly created */
+    if (created)
+       fidp->flags |= SMB_FID_CREATED;
+
+    /* 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;
@@ -6138,6 +6961,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     long code = 0;
+    osi_hyper_t new_offset;
     long offset;
     int whence;
     unsigned short fd;
@@ -6155,34 +6979,50 @@ 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;
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
     lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code == 0) {
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         if (whence == 1) {
             /* offset from current offset */
-            offset += fidp->offset;
+            new_offset = LargeIntegerAdd(fidp->offset,
+                                         ConvertLongToLargeInteger(offset));
         }
         else if (whence == 2) {
             /* offset from current EOF */
-            offset += scp->length.LowPart;
+            new_offset = LargeIntegerAdd(scp->length,
+                                         ConvertLongToLargeInteger(offset));
+        } else {
+            new_offset = ConvertLongToLargeInteger(offset);
         }
-        fidp->offset = offset;
-        smb_SetSMBParm(outp, 0, offset & 0xffff);
-        smb_SetSMBParm(outp, 1, (offset>>16) & 0xffff);
+
+        fidp->offset = new_offset;
+        smb_SetSMBParm(outp, 0, new_offset.LowPart & 0xffff);
+        smb_SetSMBParm(outp, 1, (new_offset.LowPart>>16) & 0xffff);
         smb_SetSMBDataLength(outp, 0);
     }
     lock_ReleaseMutex(&scp->mx);
-    lock_ReleaseMutex(&fidp->mx);
     smb_ReleaseFID(fidp);
+    cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     return code;
 }
@@ -6224,19 +7064,9 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
     /* Sanity check */
     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);
-#endif /* !DJGPP */
+       LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_TOO_SHORT, 
+                __FILE__, __LINE__, ncbp->ncb_length);
+       osi_Log1(smb_logp, "SMB message too short, len %d", ncbp->ncb_length);
         return;
     }
 
@@ -6250,7 +7080,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];
@@ -6294,14 +7124,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[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
-                osi_Log4(smb_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn);
+                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[%d]",(code==0)?0:code-CM_ERROR_BASE);
-                osi_Log1(smb_logp,"Dispatch return  code[%d]",(code==0)?0:code-CM_ERROR_BASE);
+                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 )
@@ -6310,21 +7137,11 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
             }   
 
             if (oldGen != sessionGen) {
-#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);
-#endif /* !DJGPP */
-                osi_Log1(smb_logp, "Pkt straddled session startup, "
-                          "ncb length %d", ncbp->ncb_length);
+                newTime = GetTickCount();
+               LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION, 
+                        newTime - oldTime, ncbp->ncb_length);
+               osi_Log2(smb_logp, "Pkt straddled session startup, "
+                          "took %d ms, ncb length %d", newTime - oldTime, ncbp->ncb_length);
             }
         }
         else {
@@ -6334,7 +7151,6 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
             smb_LogPacket(inp);
 #endif  /* LOG_PACKET */
 
-#ifndef DJGPP
             if (showErrors) {
                 sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom);
                 code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again",
@@ -6342,32 +7158,16 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                 if (code == IDCANCEL) 
                     showErrors = 0;
             }
-#endif /* DJGPP */
             code = CM_ERROR_BADOP;
         }
 
         /* 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);
 #ifdef LOG_PACKET
             smb_LogPacket(inp);
 #endif /* LOG_PACKET */
-#endif /* !DJGPP */
             osi_Log1(smb_logp, "Invalid SMB message, length %d",
                      ncbp->ncb_length);
 
@@ -6403,7 +7203,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                 smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
                 smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
                 smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
-                smbp->flg2 |= SMB_FLAGS2_ERR_STATUS;
+                smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
                 break;
             }
             else {
@@ -6456,7 +7256,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 */
@@ -6467,42 +7267,14 @@ 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);
-       thrd_Decrement(&ongoingOps);
-
-       if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
-        if (active_vcp) {
-            smb_ReleaseVC(active_vcp);
-            osi_Log2(smb_logp,
-                      "Replacing active_vcp %x with %x", active_vcp, vcp);
-        }
-        smb_HoldVC(vcp);
-            active_vcp = vcp;
-            last_msg_time = GetCurrentTime();
-       }       
-       else if (active_vcp == vcp) {
-            smb_ReleaseVC(active_vcp);
-            active_vcp = NULL;
-    }
+    thrd_Decrement(&ongoingOps);
 
     return;
 }
 
-#ifndef DJGPP
 /* Wait for Netbios() calls to return, and make the results available to server
  * threads.  Note that server threads can't wait on the NCBevents array
  * themselves, because NCB events are manual-reset, and the servers would race
@@ -6513,15 +7285,11 @@ void smb_ClientWaiter(void *parmp)
     DWORD code;
     int   idx;
 
-    while (1) {
+    while (smbShutdownFlag == 0) {
         code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBevents,
                                                  FALSE, INFINITE);
-        if (code == WAIT_OBJECT_0) {
-            if (smbShutdownFlag == 1)
-                break;
-            else
-                continue;
-        }
+        if (code == WAIT_OBJECT_0)
+            continue;
 
         /* error checking */
         if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numNCBs))
@@ -6560,7 +7328,6 @@ void smb_ClientWaiter(void *parmp)
         thrd_SetEvent(NCBreturns[0][idx]);
     }
 }
-#endif /* !DJGPP */
 
 /*
  * Try to have one NCBRECV request waiting for every live session.  Not more
@@ -6571,20 +7338,13 @@ void smb_ServerWaiter(void *parmp)
     DWORD code;
     int idx_session, idx_NCB;
     NCB *ncbp;
-#ifdef DJGPP
-    dos_ptr dos_ncb;
-#endif /* DJGPP */
 
-    while (1) {
+    while (smbShutdownFlag == 0) {
         /* Get a session */
         code = thrd_WaitForMultipleObjects_Event(numSessions, SessionEvents,
                                                  FALSE, INFINITE);
-        if (code == WAIT_OBJECT_0) {
-            if ( smbShutdownFlag == 1 )
-                break;
-            else
-                continue;
-        }
+        if (code == WAIT_OBJECT_0)
+            continue;
 
         if (code >= WAIT_ABANDONED_0 && code < (WAIT_ABANDONED_0 + numSessions))
         {
@@ -6623,7 +7383,7 @@ void smb_ServerWaiter(void *parmp)
         code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBavails,
                                                  FALSE, INFINITE);
         if (code == WAIT_OBJECT_0) {
-            if ( smbShutdownFlag == 1 ) 
+            if (smbShutdownFlag == 1) 
                 break;
             else
                 goto NCBretry;
@@ -6670,19 +7430,10 @@ void smb_ServerWaiter(void *parmp)
         ncbp->ncb_lsn = (unsigned char) LSNs[idx_session];
         ncbp->ncb_command = NCBRECV | ASYNCH;
         ncbp->ncb_lana_num = lanas[idx_session];
-#ifndef DJGPP
         ncbp->ncb_buffer = (unsigned char *) bufs[idx_NCB];
         ncbp->ncb_event = NCBevents[idx_NCB];
         ncbp->ncb_length = SMB_PACKETSIZE;
         Netbios(ncbp);
-#else /* DJGPP */
-        ncbp->ncb_buffer = bufs[idx_NCB]->dos_pkt;
-        ((smb_ncb_t*)ncbp)->orig_pkt = bufs[idx_NCB];
-        ncbp->ncb_event = NCBreturns[0][idx_NCB];
-        ncbp->ncb_length = SMB_PACKETSIZE;
-        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-        Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
     }
 }
 
@@ -6698,7 +7449,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;
@@ -6708,15 +7459,21 @@ void smb_Server(VOID *parmp)
     UCHAR rc;
     smb_vc_t *vcp = NULL;
     smb_t *smbp;
-#ifdef DJGPP
-    dos_ptr dos_ncb;
-#endif /* DJGPP */
+
+    rx_StartClientThread();
 
     outncbp = GetNCB();
     outbufp = GetPacket();
     outbufp->ncbp = outncbp;
 
     while (1) {
+       if (vcp) {
+           smb_ReleaseVC(vcp);
+           vcp = NULL;
+       }
+
+       smb_ResetServerPriority();
+
         code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
                                                  FALSE, INFINITE);
 
@@ -6758,118 +7515,103 @@ void smb_Server(VOID *parmp)
         if (idx_NCB < 0 || idx_NCB > (sizeof(NCBs) / sizeof(NCBs[0])))
         {
             /* this is fatal - log as much as possible */
-            osi_Log1(smb_logp, "Fatal: idx_NCB [ %d ] out of range.\n", idx_NCB);
+            osi_Log1(smb_logp, "Fatal: idx_NCB %d out of range.\n", idx_NCB);
             osi_assert(0);
         }
 
         ncbp = NCBs[idx_NCB];
-#ifdef DJGPP
-        dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
         idx_session = NCBsessions[idx_NCB];
         rc = ncbp->ncb_retcode;
 
         if (rc != NRC_PENDING && rc != NRC_GOODRET)
-            osi_Log1(smb_logp, "NCBRECV failure code %d", rc);
+           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: break;
+        case NRC_GOODRET: 
+            vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
+            break;
 
         case NRC_PENDING:
-            /* Can this happen? Or is it just my
-             * UNIX paranoia? 
-             */
+            /* Can this happen? Or is it just my UNIX paranoia? */
+            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:
+           LogEvent(EVENTLOG_WARNING_TYPE, MSG_UNEXPECTED_SMB_SESSION_CLOSE, ncb_error_string(rc));
+           /* fallthrough */
+       case NRC_SCLOSED:
             /* Client closed session */
-            if (reportSessionStartups) 
-            {
-                osi_Log1(smb_logp, "session [ %d ] closed", idx_session);
-            }
-            dead_sessions[idx_session] = TRUE;
-            if (vcp)
-                smb_ReleaseVC(vcp);
             vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
-            /* Should also release vcp.  [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)
-                    osi_Log1(smb_logp,
-                             "dead_vcp already set, %x",
-                             dead_vcp);
-                if (!dead_vcp && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
-                    osi_Log2(smb_logp,
-                             "setting dead_vcp %x, user struct %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);
-                    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);
-#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;
-            }
+           LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_INCOMPLETE, 
+                    ncbp->ncb_length);
+           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 */
@@ -6878,14 +7620,13 @@ 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 :
          *   a) we have the wrong NCB.
          *   b) Netbios screwed up the call.
+        *   c) The VC was already marked dead before we were able to
+        *      process the call
          * Obviously this implies that 
          *   ( LSNs[idx_session] != ncbp->ncb_lsn ||
          *   lanas[idx_session] != ncbp->ncb_lana_num )
@@ -6893,31 +7634,14 @@ 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!"
+            osi_Log4(smb_logp, "Server: VCP does not exist!"
                       "LSNs[idx_session]=[%d],"
                       "lanas[idx_session]=[%d],"
                       "ncbp->ncb_lsn=[%d],"
@@ -6933,25 +7657,15 @@ void smb_Server(VOID *parmp)
             continue;
         }
 
+       smb_SetRequestStartTime();
 
         vcp->errorCount = 0;
         bufp = (struct smb_packet *) ncbp->ncb_buffer;
-#ifdef DJGPP
-        bufp = ((smb_ncb_t *) ncbp)->orig_pkt;
-        /* copy whole packet to virtual memory */
-        /*fprintf(stderr, "smb_Server: copying dos packet at 0x%x, "
-        "bufp=0x%x\n",
-        bufp->dos_pkt / 16, bufp);*/
-        fflush(stderr);
-        dosmemget(bufp->dos_pkt, ncbp->ncb_length, bufp->data);
-#endif /* DJGPP */
         smbp = (smb_t *)bufp->data;
         outbufp->flags = 0;
 
-#if !defined(DJGPP) && !defined(AFS_WIN32_ENV)
         __try
         {
-#endif
             if (smbp->com == 0x1d) {
                 /* Special handling for Write Raw */
                 raw_write_cont_t rwc;
@@ -6969,11 +7683,7 @@ void smb_Server(VOID *parmp)
                     ncbp->ncb_buffer = rwc.buf;
                     ncbp->ncb_length = 65535;
                     ncbp->ncb_event = rwevent;
-#ifndef DJGPP
                     Netbios(ncbp);
-#else
-                    Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
                     rcode = thrd_WaitForSingleObject_Event(rwevent, RAWTIMEOUT);
                     thrd_CloseHandle(rwevent);
                 }
@@ -6993,15 +7703,13 @@ void smb_Server(VOID *parmp)
                 /* TODO: what else needs to be serialized? */
                 smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
             }
-#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
         }
         __except( smb_ServerExceptionFilter() ) {
         }
-#endif
 
         smb_concurrentCalls--;
 
-doneWithNCB:
+      doneWithNCB:
         thrd_SetEvent(NCBavails[idx_NCB]);
     }
     if (vcp)
@@ -7014,28 +7722,16 @@ doneWithNCB:
  * force trace and give control to upstream exception handlers. Useful for
  * debugging.
  */
-#if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
 DWORD smb_ServerExceptionFilter(void) {
     /* While this is not the best time to do a trace, if it succeeds, then
      * 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;
 }       
-#endif
 
 /*
  * Create a new NCB and associated events, packet buffer, and "space" buffer.
@@ -7057,12 +7753,10 @@ void InitNCBslot(int idx)
     NCBavails[idx] = 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));
-#ifndef DJGPP
     sprintf(eventName,"NCBevents[%d]", idx);
     NCBevents[idx] = thrd_CreateEvent(NULL, TRUE, FALSE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
         osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
-#endif /* !DJGPP */
     sprintf(eventName,"NCBReturns[0<=i<smb_NumServerThreads][%d]", idx);
     retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
@@ -7080,22 +7774,16 @@ void smb_Listener(void *parmp)
     NCB *ncbp;
     long code = 0;
     long len;
-    long i, j;
-    smb_vc_t *vcp;
+    long i;
+    int  session, thread;
+    smb_vc_t *vcp = NULL;
     int flags = 0;
     char rname[NCBNAMSZ+1];
     char cname[MAX_COMPUTERNAME_LENGTH+1];
     int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
-#ifdef DJGPP
-    dos_ptr dos_ncb;
-    time_t now;
-#endif /* DJGPP */
-    int lana = (int) parmp;
+    INT_PTR lana = (INT_PTR) parmp;
 
     ncbp = GetNCB();
-#ifdef DJGPP
-    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
 
     /* retrieve computer name */
     GetComputerName(cname, &cnamelen);
@@ -7110,34 +7798,24 @@ 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);
-#else /* DJGPP */
-        code = Netbios(ncbp, dos_ncb);
-#endif
 
         if (code != 0)
         {
-#ifndef DJGPP
             char tbuffer[256];
-#endif
 
             /* terminate silently if shutdown flag is set */
             if (smbShutdownFlag == 1) {
-#ifndef DJGPP
                 ExitThread(1);
-#else
-                thrd_Exit(1);
-#endif
             }
 
             osi_Log2(smb_logp, 
@@ -7146,7 +7824,6 @@ void smb_Listener(void *parmp)
             osi_Log0(smb_logp, 
                      "Client exiting due to network failure. Please restart client.\n");
 
-#ifndef DJGPP
             sprintf(tbuffer, 
                      "Client exiting due to network failure.  Please restart client.\n"
                      "NCBLISTEN lana=%d failed with code %d",
@@ -7154,16 +7831,7 @@ void smb_Listener(void *parmp)
             if (showErrors)
                 code = (*smb_MBfunc)(NULL, tbuffer, "AFS Client Service: Fatal Error",
                                       MB_OK|MB_SERVICE_NOTIFICATION);
-            osi_assert(tbuffer);
-            ExitThread(1);
-#else
-            fprintf(stderr, "NCBLISTEN lana=%d failed with code %d\n",
-                     ncbp->ncb_lana_num, code);
-            fprintf(stderr, "\nClient exiting due to network failure "
-                     "(possibly due to power-saving mode)\n");
-            fprintf(stderr, "Please restart client.\n");
-            afs_exit(AFS_EXITCODE_NETWORK_FAILURE);
-#endif /* !DJGPP */
+            osi_panic(tbuffer, __FILE__, __LINE__);
         }
 
         /* check for remote conns */
@@ -7181,98 +7849,167 @@ 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++;
-
-        /* 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);
-#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);
-
-        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);
-#else /* DJGPP */
-            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);
+        osi_Log1(smb_logp, "SMB session startup, %d ongoing ops", ongoingOps);
 
         /* now ncbp->ncb_lsn is the connection ID */
         vcp = smb_FindVC(ncbp->ncb_lsn, SMB_FLAG_CREATE, ncbp->ncb_lana_num);
-        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 (vcp->session == 0) {
+           /* New generation */
+           osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
+           sessionGen++;
 
-        /* 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.
-         */
+           /* 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);
+#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);
+
+           if (reportSessionStartups) {
+               LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_SESSION_START, 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);
+
+           if (reportSessionStartups) {
+               LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_SESSION_START, ongoingOps);
+           }
+       }
+
+        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;
 
-        osi_assert(i < Sessionmax - 1);
-        osi_assert(numNCBs < NCBmax - 1);   /* if we pass this test we can allocate one more */
+            if (vcp->flags & SMB_VCFLAG_STATUS32) {
+                unsigned long NTStatus;
+                smb_MapNTError(code, &NTStatus);
+                outWctp = outp->wctp;
+                smbp = (smb_t *) &outp->data;
+                *outWctp++ = 0;
+                *outWctp++ = 0;
+                *outWctp++ = 0;
+                smbp->rcls = (unsigned char) (NTStatus & 0xff);
+                smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
+                smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
+                smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
+                smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
+            } else {
+                unsigned short errCode;
+                unsigned char errClass;
+                smb_MapCoreError(code, vcp, &errCode, &errClass);
+                outWctp = outp->wctp;
+                smbp = (smb_t *) &outp->data;
+                *outWctp++ = 0;
+                *outWctp++ = 0;
+                *outWctp++ = 0;
+                smbp->errLow = (unsigned char) (errCode & 0xff);
+                smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
+                smbp->rcls = errClass;
+            }
+            smb_SendPacket(vcp, outp);
+            smb_FreePacket(outp);
 
-        LSNs[i] = ncbp->ncb_lsn;
-        lanas[i] = ncbp->ncb_lana_num;
-               
-        if (i == numSessions) {
-            /* Add new NCB for new session */
-            char eventName[MAX_PATH];
-
-            osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
-
-            InitNCBslot(numNCBs);
-            numNCBs++;
-            thrd_SetEvent(NCBavails[0]);
-            thrd_SetEvent(NCBevents[0]);
-            for (j = 0; j < smb_NumServerThreads; j++)
-                thrd_SetEvent(NCBreturns[j][0]);
-            /* Also add new session event */
-            sprintf(eventName, "SessionEvents[%d]", i);
-            SessionEvents[i] = 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));
-            numSessions++;
-            osi_Log2(smb_logp, "increasing numNCBs [ %d ] numSessions [ %d ]", numNCBs, numSessions);
-            thrd_SetEvent(SessionEvents[0]);
+           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);
+               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);
+           } else {
+               lock_ReleaseMutex(&vcp->mx);
+           }
         } else {
-            thrd_SetEvent(SessionEvents[i]);
+            /* 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(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 (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 (thread = 0; thread < smb_NumServerThreads; thread++)
+                    thrd_SetEvent(NCBreturns[thread][0]);
+                /* Also add new session event */
+                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[session]);
+            }
         }
+        smb_ReleaseVC(vcp);
+
         /* unlock */
         lock_ReleaseMutex(&smb_ListenerLock);
-
     }  /* dispatch while loop */
 }
 
@@ -7280,9 +8017,6 @@ void smb_Listener(void *parmp)
 void smb_NetbiosInit()
 {
     NCB *ncbp;
-#ifdef DJGPP
-    dos_ptr dos_ncb;
-#endif /* DJGPP */
     int i, lana, code, l;
     char s[100];
     int delname_tried=0;
@@ -7290,10 +8024,6 @@ void smb_NetbiosInit()
     int lana_found = 0;
     OSVERSIONINFO Version;
 
-    /* AFAIK, this is the default for the ms loopback adapter.*/
-    unsigned char kWLA_MAC[6] = { 0x02, 0x00, 0x4c, 0x4f, 0x4f, 0x50 };
-    /*******************************************************************/
-
     /* Get the version of Windows */
     memset(&Version, 0x00, sizeof(Version));
     Version.dwOSVersionInfoSize = sizeof(Version);
@@ -7301,19 +8031,14 @@ void smb_NetbiosInit()
 
     /* setup the NCB system */
     ncbp = GetNCB();
-#ifdef DJGPP
-    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif /* DJGPP */
 
-#ifndef DJGPP
     if (smb_LANadapter == -1) {
         ncbp->ncb_command = NCBENUM;
         ncbp->ncb_buffer = (PUCHAR)&lana_list;
         ncbp->ncb_length = sizeof(lana_list);
         code = Netbios(ncbp);
         if (code != 0) {
-            sprintf(s, "Netbios NCBENUM error code %d", code);
-            osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+            afsi_log("Netbios NCBENUM error code %d", code);
             osi_panic(s, __FILE__, __LINE__);
         }
     }
@@ -7334,35 +8059,19 @@ void smb_NetbiosInit()
         if (code == 0) 
             code = ncbp->ncb_retcode;
         if (code != 0) {
-            sprintf(s, "Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
-            osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+            afsi_log("Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code);
             lana_list.lana[i] = 255;  /* invalid lana */
         } else {
-            sprintf(s, "Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
-            osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+            afsi_log("Netbios NCBRESET lana %d succeeded", lana_list.lana[i]);
         }
     }
-#else
-    /* for DJGPP, there is no NCBENUM and NCBRESET is a real reset.  so
-       we will just fake the LANA list */
-    if (smb_LANadapter == -1) {
-        for (i = 0; i < 8; i++)
-           lana_list.lana[i] = i;
-        lana_list.length = 8;
-    }
-    else {
-        lana_list.length = 1;
-        lana_list.lana[0] = smb_LANadapter;
-    }
-#endif /* !DJGPP */
 
     /* and declare our name so we can receive connections */
     memset(ncbp, 0, sizeof(*ncbp));
     len=lstrlen(smb_localNamep);
     memset(smb_sharename,' ',NCBNAMSZ);
     memcpy(smb_sharename,smb_localNamep,len);
-    sprintf(s, "lana_list.length %d", lana_list.length);
-    osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+    afsi_log("lana_list.length %d", lana_list.length);
 
     /* Keep the name so we can unregister it later */
     for (l = 0; l < lana_list.length; l++) {
@@ -7371,53 +8080,38 @@ void smb_NetbiosInit()
         ncbp->ncb_command = NCBADDNAME;
         ncbp->ncb_lana_num = lana;
         memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
-#ifndef DJGPP
         code = Netbios(ncbp);
-#else /* DJGPP */
-        code = Netbios(ncbp, dos_ncb);
-#endif /* !DJGPP */
           
-        osi_Log4(smb_logp, "Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
+        afsi_log("Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d",
                  lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
         {
             char name[NCBNAMSZ+1];
             name[NCBNAMSZ]=0;
             memcpy(name,ncbp->ncb_name,NCBNAMSZ);
-            osi_Log1(smb_logp, "Netbios NCBADDNAME added new name >%s<",osi_LogSaveString(smb_logp, name));
+            afsi_log("Netbios NCBADDNAME added new name >%s<",name);
         }
 
         if (code == 0) code = ncbp->ncb_retcode;
         if (code == 0) {
-            osi_Log1(smb_logp, "Netbios NCBADDNAME succeeded on lana %d\n", lana);
-#ifdef DJGPP
-            /* we only use one LANA with djgpp */
-            lana_list.lana[0] = lana;
-            lana_list.length = 1;
-#endif   
+            afsi_log("Netbios NCBADDNAME succeeded on lana %d\n", lana);
         }
         else {
-            sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
-            osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+            afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
             if (code == NRC_BRIDGE) {    /* invalid LANA num */
                 lana_list.lana[l] = 255;
                 continue;
             }
             else if (code == NRC_DUPNAME) {
-                osi_Log0(smb_logp, "Name already exists; try to delete it");
+                afsi_log("Name already exists; try to delete it");
                 memset(ncbp, 0, sizeof(*ncbp));
                 ncbp->ncb_command = NCBDELNAME;
                 memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
                 ncbp->ncb_lana_num = lana;
-#ifndef DJGPP
                 code = Netbios(ncbp);
-#else
-                code = Netbios(ncbp, dos_ncb);
-#endif /* DJGPP */
                 if (code == 0) 
                     code = ncbp->ncb_retcode;
                 else {
-                    sprintf(s, "Netbios NCBDELNAME lana %d error code %d\n", lana, code);
-                    osi_Log0(smb_logp, s);
+                    afsi_log("Netbios NCBDELNAME lana %d error code %d\n", lana, code);
                 }
                 if (code != 0 || delname_tried) {
                     lana_list.lana[l] = 255;
@@ -7431,24 +8125,19 @@ void smb_NetbiosInit()
                 }
             }
             else {
-                sprintf(s, "Netbios NCBADDNAME lana %d error code %d", lana, code);
-                osi_Log0(smb_logp, osi_LogSaveString(smb_logp, s));
+                afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code);
                 lana_list.lana[l] = 255;  /* invalid lana */
                 osi_panic(s, __FILE__, __LINE__);
             }
         }
         if (code == 0) {
             lana_found = 1;   /* at least one worked */
-#ifdef DJGPP
-            break;
-#endif
         }
     }
 
     osi_assert(lana_list.length >= 0);
     if (!lana_found) {
-        sprintf(s, "No valid LANA numbers found!");
-        osi_panic(s, __FILE__, __LINE__);
+        osi_panic("No valid LANA numbers found!", __FILE__, __LINE__);
     }
         
     /* we're done with the NCB now */
@@ -7457,27 +8146,21 @@ void smb_NetbiosInit()
 
 void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
               int nThreads
-#ifndef DJGPP
               , void *aMBfunc
-#endif
   )
 
 {
     thread_t phandle;
     int lpid;
-    int i;
+    INT_PTR i;
     int len;
     struct tm myTime;
-#ifdef DJGPP
-    int npar, seg, sel;
-    dos_ptr rawBuf;
-#endif /* DJGPP */
     EVENT_HANDLE retHandle;
     char eventName[MAX_PATH];
 
-#ifndef DJGPP
+    smb_TlsRequestSlot = TlsAlloc();
+
     smb_MBfunc = aMBfunc;
-#endif /* DJGPP */
 
     smb_useV3 = useV3;
     smb_LANadapter = LANadapt;
@@ -7492,9 +8175,10 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     myTime.tm_sec = 0;
     smb_localZero = mktime(&myTime);
 
+#ifndef USE_NUMERIC_TIME_CONV
     /* Initialize kludge-GMT */
     smb_CalculateNowTZ();
-
+#endif /* USE_NUMERIC_TIME_CONV */
 #ifdef AFS_FREELANCE_CLIENT
     /* Make sure the root.afs volume has the correct time */
     cm_noteLocalMountPointChange();
@@ -7504,7 +8188,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);
@@ -7519,7 +8203,6 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     lock_InitializeMutex(&smb_ListenerLock, "smb listener lock");
        
     /* 4 Raw I/O buffers */
-#ifndef DJGPP
     smb_RawBufs = calloc(65536,1);
     *((char **)smb_RawBufs) = NULL;
     for (i=0; i<3; i++) {
@@ -7527,39 +8210,6 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
         *((char **)rawBuf) = smb_RawBufs;
         smb_RawBufs = rawBuf;
     }
-#else /* DJGPP */
-    npar = 65536 >> 4;  /* number of paragraphs */
-    seg = __dpmi_allocate_dos_memory(npar, &smb_RawBufSel[0]);
-    if (seg == -1) {
-        afsi_log("Cannot allocate %d paragraphs of DOS memory",
-                  npar);
-        osi_panic("",__FILE__,__LINE__);
-    }
-    else {
-        afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
-                  npar, seg);
-    }
-    smb_RawBufs = (seg * 16) + 0;  /* DOS physical address */
-        
-    _farpokel(_dos_ds, smb_RawBufs, NULL);
-    for (i=0; i<SMB_RAW_BUFS-1; i++) {
-        npar = 65536 >> 4;  /* number of paragraphs */
-        seg = __dpmi_allocate_dos_memory(npar, &smb_RawBufSel[i+1]);
-        if (seg == -1) {
-            afsi_log("Cannot allocate %d paragraphs of DOS memory",
-                      npar);
-            osi_panic("",__FILE__,__LINE__);
-        }
-        else {
-            afsi_log("Allocated %d paragraphs of DOS mem at 0x%X",
-                      npar, seg);
-        }
-        rawBuf = (seg * 16) + 0;  /* DOS physical address */
-        /*_farpokel(_dos_ds, smb_RawBufs, smb_RawBufs);*/
-        _farpokel(_dos_ds, rawBuf, smb_RawBufs);
-        smb_RawBufs = rawBuf;
-    }
-#endif /* !DJGPP */
 
     /* global free lists */
     smb_ncbFreeListp = NULL;
@@ -7584,13 +8234,13 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     NCBevents[0] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
         afsi_log("Event Object Already Exists: %s", eventName);
-    NCBreturns = malloc(nThreads * sizeof(EVENT_HANDLE *));
+    NCBreturns = malloc(smb_NumServerThreads * sizeof(EVENT_HANDLE *));
     sprintf(eventName, "NCBreturns[0<=i<smb_NumServerThreads][0]");
     retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
     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;
     }
 
@@ -7600,11 +8250,9 @@ 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((int)(i+1));
     }
-
-    for (i = 1; i <= nThreads; i++)
-        InitNCBslot(i);
-    numNCBs = nThreads + 1;
+    numNCBs = smb_NumServerThreads + 1;
 
     /* Initialize dispatch table */
     memset(&smb_dispatchTable, 0, sizeof(smb_dispatchTable));
@@ -7652,6 +8300,8 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     smb_dispatchTable[0x2d].flags |= SMB_DISPATCHFLAG_CHAINED;
     smb_dispatchTable[0x2e].procp = smb_ReceiveV3ReadX;
     smb_dispatchTable[0x2e].flags |= SMB_DISPATCHFLAG_CHAINED;
+    smb_dispatchTable[0x2f].procp = smb_ReceiveV3WriteX;
+    smb_dispatchTable[0x2f].flags |= SMB_DISPATCHFLAG_CHAINED;
     smb_dispatchTable[0x32].procp = smb_ReceiveV3Tran2A;       /* both are same */
     smb_dispatchTable[0x32].flags |= SMB_DISPATCHFLAG_NORESPONSE;
     smb_dispatchTable[0x33].procp = smb_ReceiveV3Tran2A;
@@ -7702,6 +8352,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext;
     smb_tran2DispatchTable[13].procp = smb_ReceiveTran2CreateDirectory;
     smb_tran2DispatchTable[14].procp = smb_ReceiveTran2SessionSetup;
+    smb_tran2DispatchTable[15].procp = smb_ReceiveTran2QFSInfoFid;
     smb_tran2DispatchTable[16].procp = smb_ReceiveTran2GetDFSReferral;
     smb_tran2DispatchTable[17].procp = smb_ReceiveTran2ReportDFSInconsistency;
 
@@ -7716,12 +8367,12 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
 
     /* if we are doing SMB authentication we have register outselves as a logon process */
     if (smb_authType != SMB_AUTH_NONE) {
-        NTSTATUS nts;
+        NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
         LSA_STRING afsProcessName;
         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);
@@ -7730,27 +8381,70 @@ 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) {
+                /* BEGIN 
+                 * This code forces Windows to authenticate against the Logon Cache 
+                 * first instead of attempting to authenticate against the Domain 
+                 * Controller.  When the Windows logon cache is enabled this improves
+                 * performance by removing the network access and works around a bug
+                 * seen at sites which are using a MIT Kerberos principal to login
+                 * to machines joined to a non-root domain in a multi-domain forest.
+                 */
+                PVOID pResponse = NULL;
+                ULONG cbResponse = 0;
+                MSV1_0_SETPROCESSOPTION_REQUEST OptionsRequest;
+
+                RtlZeroMemory(&OptionsRequest, sizeof(OptionsRequest));
+                OptionsRequest.MessageType = (MSV1_0_PROTOCOL_MESSAGE_TYPE) MsV1_0SetProcessOption;
+                OptionsRequest.ProcessOptions = MSV1_0_OPTION_TRY_CACHE_FIRST; 
+                OptionsRequest.DisableOptions = FALSE;
+
+                nts = LsaCallAuthenticationPackage( smb_lsaHandle,
+                                                    smb_lsaSecPackage,
+                                                    &OptionsRequest,
+                                                    sizeof(OptionsRequest),
+                                                    &pResponse,
+                                                    &cbResponse,
+                                                    &ntsEx
+                                                    );
+
+                if (nts != STATUS_SUCCESS && ntsEx != STATUS_SUCCESS) {
+                    char message[256];
+                    sprintf(message,"MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x",
+                                       nts, ntsEx);
+                    OutputDebugString(message);
+                    afsi_log(message);
+                } else {
+                    OutputDebugString("MsV1_0SetProcessOption success");
+                    afsi_log("MsV1_0SetProcessOption success");
+                }
+                /* 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
+                or sec package id. */
+                afsi_log("Reverting to NO SMB AUTH");
+                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);
 
-        if (nts != STATUS_SUCCESS) {
             /* something went wrong. We report the error and revert back to no authentication
             because we can't perform any auth requests without a successful lsa handle
             or sec package id. */
             afsi_log("Reverting to NO SMB AUTH");
             smb_authType = SMB_AUTH_NONE;
-        } 
+        }
+
 #ifdef COMMENT
         /* Don't fallback to SMB_AUTH_NTLM.  Apparently, allowing SPNEGO to be used each
          * time prevents the failure of authentication when logged into Windows with an
@@ -7789,26 +8483,25 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     /* Start listeners, waiters, servers, and daemons */
 
     for (i = 0; i < lana_list.length; i++) {
-        if (lana_list.lana[i] == 255) continue;
+        if (lana_list.lana[i] == 255) 
+            continue;
         phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Listener,
                                (void*)lana_list.lana[i], 0, &lpid, "smb_Listener");
         osi_assert(phandle != NULL);
         thrd_CloseHandle(phandle);
     }
 
-#ifndef DJGPP
     phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ClientWaiter,
                           NULL, 0, &lpid, "smb_ClientWaiter");
     osi_assert(phandle != NULL);
     thrd_CloseHandle(phandle);
-#endif /* !DJGPP */
 
     phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_ServerWaiter,
                           NULL, 0, &lpid, "smb_ServerWaiter");
     osi_assert(phandle != NULL);
     thrd_CloseHandle(phandle);
 
-    for (i=0; i<nThreads; i++) {
+    for (i=0; i<smb_NumServerThreads; i++) {
         phandle = thrd_Create(NULL, 65536, (ThreadFunc) smb_Server,
                               (void *) i, 0, &lpid, "smb_Server");
         osi_assert(phandle != NULL);
@@ -7825,29 +8518,20 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     osi_assert(phandle != NULL);
     thrd_CloseHandle(phandle);
 
-#ifdef DJGPP
-    smb_ListShares();
-#endif
-
     return;
 }
 
 void smb_Shutdown(void)
 {
     NCB *ncbp;
-#ifdef DJGPP
-    dos_ptr dos_ncb;
-#endif
     long code = 0;
     int i;
+    smb_vc_t *vcp;
 
     /*fprintf(stderr, "Entering smb_Shutdown\n");*/
         
     /* setup the NCB system */
     ncbp = GetNCB();
-#ifdef DJGPP
-    dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
-#endif
 
     /* Block new sessions by setting shutdown flag */
     smbShutdownFlag = 1;
@@ -7862,12 +8546,8 @@ 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];
-#ifndef DJGPP
+        ncbp->ncb_lsn = (UCHAR)LSNs[i];
         code = Netbios(ncbp);
-#else
-        code = Netbios(ncbp, dos_ncb);
-#endif
         /*fprintf(stderr, "returned from NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
         if (code == 0) code = ncbp->ncb_retcode;
         if (code != 0) {
@@ -7876,6 +8556,24 @@ void smb_Shutdown(void)
         }
     }
 
+    /* Trigger the shutdown of all SMB threads */                                
+    for (i = 0; i < smb_NumServerThreads; i++)                                   
+        thrd_SetEvent(NCBreturns[i][0]);                                         
+                                                                                 
+    thrd_SetEvent(NCBevents[0]);                                                 
+    thrd_SetEvent(SessionEvents[0]);                                             
+    thrd_SetEvent(NCBavails[0]);                                                 
+                                                                                 
+    for (i = 0;i < smb_NumServerThreads; i++) {                                  
+        DWORD code = thrd_WaitForSingleObject_Event(smb_ServerShutdown[i], 500); 
+        if (code == WAIT_OBJECT_0) {                                             
+            continue;                                                            
+        } else {                                                                 
+            afsi_log("smb_Shutdown thread [%d] did not stop; retry ...",i);      
+            thrd_SetEvent(NCBreturns[i--][0]);                                   
+        }                                                                        
+    }                                                                            
+
     /* Delete Netbios name */
     memset((char *)ncbp, 0, sizeof(NCB));
     for (i = 0; i < lana_list.length; i++) {
@@ -7883,11 +8581,7 @@ void smb_Shutdown(void)
         ncbp->ncb_command = NCBDELNAME;
         ncbp->ncb_lana_num = lana_list.lana[i];
         memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
-#ifndef DJGPP
         code = Netbios(ncbp);
-#else
-        code = Netbios(ncbp, dos_ncb);
-#endif
         if (code == 0) 
             code = ncbp->ncb_retcode;
         if (code != 0) {
@@ -7897,22 +8591,47 @@ void smb_Shutdown(void)
         fflush(stderr);
     }
 
-    /* Trigger the shutdown of all SMB threads */
-    for (i = 0; i < smb_NumServerThreads; i++)
-        thrd_SetEvent(NCBreturns[i][0]);
+    /* Release the reference counts held by the VCs */
+    lock_ObtainWrite(&smb_rctLock);
+    for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) 
+    {
+        smb_fid_t *fidp;
+        smb_tid_t *tidp;
+     
+       if (vcp->magic != SMB_VC_MAGIC)
+           osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", 
+                      __FILE__, __LINE__);
 
-    thrd_SetEvent(NCBevents[0]);
-    thrd_SetEvent(SessionEvents[0]);
-    thrd_SetEvent(NCBavails[0]);
+       for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
+        {
+            if (fidp->scp != NULL) {
+                cm_scache_t * scp;
+
+                lock_ObtainMutex(&fidp->mx);
+                if (fidp->scp != NULL) {
+                    scp = fidp->scp;
+                    fidp->scp = NULL;
+                    cm_ReleaseSCache(scp);
+                }
+                lock_ReleaseMutex(&fidp->mx);
+            }
+        }
 
-    for (i = 0;i < smb_NumServerThreads; i++) {
-        DWORD code = thrd_WaitForSingleObject_Event(smb_ServerShutdown[i], INFINITE);
-        if (code == WAIT_OBJECT_0) {
-            continue;
-        } else {
-            afsi_log("smb_Shutdown[%d] wait error",i);
+        for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+            if (tidp->vcp)
+                smb_ReleaseVCNoLock(tidp->vcp);
+            if (tidp->userp) {
+                cm_user_t *userp = tidp->userp;
+                tidp->userp = NULL;
+                lock_ReleaseWrite(&smb_rctLock);
+                cm_ReleaseUser(userp);
+                lock_ObtainWrite(&smb_rctLock);
+            }
         }
     }
+    lock_ReleaseWrite(&smb_rctLock);
+
+    TlsFree(smb_TlsRequestSlot);
 }
 
 /* Get the UNC \\<servername>\<sharename> prefix. */
@@ -7988,7 +8707,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 ***");
@@ -7996,45 +8715,107 @@ void smb_LogPacket(smb_packet_t *packet)
 #endif /* LOG_PACKET */
 
 
-int smb_DumpVCP(FILE *outputFile, char *cookie)
+int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
 {
     int zilch;
     char output[1024];
   
     smb_vc_t *vcp;
   
-    lock_ObtainRead(&smb_rctLock);
+    if (lock)
+        lock_ObtainRead(&smb_rctLock);
+  
+    sprintf(output, "begin dumping smb_vc_t\n");
+    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%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 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);
   
-    sprintf(output, "begin dumping vcpsp\n");
-    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+    sprintf(output, "begin dumping DEAD smb_vc_t\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
 
-    for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) 
+    for (vcp = smb_deadVCsp; 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 fidsp\n");
-        WriteFile(outputFile, output, 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 -- 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 fidsp\n");
-        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+        sprintf(output, "done dumping smb_fid_t\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
     }
 
-    sprintf(output, "done dumping vcpsp\n");
-    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+    sprintf(output, "done dumping DEAD smb_vc_t\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
   
-    lock_ReleaseRead(&smb_rctLock);
+    if (lock)
+        lock_ReleaseRead(&smb_rctLock);
     return 0;
 }