Windows: Make default mode bits configurable
[openafs.git] / src / WINNT / afsd / smb.c
index 2b6e12e..a3fcd6e 100644 (file)
@@ -29,6 +29,7 @@
 #include <WINNT\afsreg.h>
 
 #include "smb.h"
+#include "msrpc.h"
 #include "lanahelper.h"
 
 #define STRSAFE_NO_DEPRECATE
@@ -133,6 +134,11 @@ long smb_dirSearchCounter = 1;
 smb_dirSearch_t *smb_firstDirSearchp;
 smb_dirSearch_t *smb_lastDirSearchp;
 
+/* Initial mode bits for files and directories.  Set to 0 to use
+   defaults. */
+int smb_unixModeDefaultFile = 0666;
+int smb_unixModeDefaultDir = 0777;
+
 /* hide dot files? */
 int smb_hideDotFiles;
 
@@ -153,13 +159,6 @@ int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT)
  */
 time_t smb_localZero = 0;
 
-#define USE_NUMERIC_TIME_CONV 1
-
-#ifndef USE_NUMERIC_TIME_CONV
-/* Time difference for converting to kludge-GMT */
-afs_uint32 smb_NowTZ;
-#endif /* USE_NUMERIC_TIME_CONV */
-
 char *smb_localNamep = NULL;
 
 smb_vc_t *smb_allVCsp;
@@ -169,8 +168,6 @@ smb_username_t *usernamesp = NULL;
 
 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);
@@ -190,83 +187,53 @@ int smb_ServerLanManagerLength = lengthof(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()
+void smb_InitReq(cm_req_t *reqp)
 {
-    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(), (int)((now - *tp) / 15));
-    }
+    cm_InitReq(reqp);
+    reqp->flags |= CM_REQ_SOURCE_SMB;
 }
 
-
 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;                 
+    case 0x01: s = "NRC_BUFLEN llegal buffer length";                  break; 
+    case 0x03: s = "NRC_ILLCMD illegal command";                       break; 
+    case 0x05: s = "NRC_CMDTMO command timed out";                     break; 
+    case 0x06: s = "NRC_INCOMP message incomplete, issue another command"; break; 
+    case 0x07: s = "NRC_BADDR  illegal buffer address";                break; 
+    case 0x08: s = "NRC_SNUMOUT session number out of range";          break; 
+    case 0x09: s = "NRC_NORES no resource available";                  break; 
+    case 0x0a: s = "NRC_SCLOSED asession closed";                      break; 
+    case 0x0b: s = "NRC_CMDCAN command cancelled";                     break; 
+    case 0x0d: s = "NRC_DUPNAME duplicate name";                       break; 
+    case 0x0e: s = "NRC_NAMTFUL name table full";                      break; 
+    case 0x0f: s = "NRC_ACTSES no deletions, name has active sessions"; break; 
+    case 0x11: s = "NRC_LOCTFUL local session table full";             break; 
+    case 0x12: s = "NRC_REMTFUL remote session table full";            break; 
+    case 0x13: s = "NRC_ILLNN illegal name number";                    break; 
+    case 0x14: s = "NRC_NOCALL no callname";                           break; 
+    case 0x15: s = "NRC_NOWILD cannot put * in NCB_NAME";              break; 
+    case 0x16: s = "NRC_INUSE name in use on remote adapter";          break; 
+    case 0x17: s = "NRC_NAMERR name deleted";                          break; 
+    case 0x18: s = "NRC_SABORT session ended abnormally";              break; 
+    case 0x19: s = "NRC_NAMCONF name conflict detected";               break; 
+    case 0x21: s = "NRC_IFBUSY interface busy, IRET before retrying";  break; 
+    case 0x22: s = "NRC_TOOMANY too many commands outstanding, retry later";break;
+    case 0x23: s = "NRC_BRIDGE ncb_lana_num field invalid";            break; 
+    case 0x24: s = "NRC_CANOCCR command completed while cancel occurring "; break; 
+    case 0x26: s = "NRC_CANCEL command not valid to cancel";           break; 
+    case 0x30: s = "NRC_DUPENV name defined by anther local process";  break; 
+    case 0x34: s = "NRC_ENVNOTDEF xenvironment undefined. RESET required";     break; 
+    case 0x35: s = "NRC_OSRESNOTAV required OS resources exhausted";   break; 
+    case 0x36: s = "NRC_MAXAPPS max number of applications exceeded";  break; 
+    case 0x37: s = "NRC_NOSAPS no saps available for netbios";                 break; 
+    case 0x38: s = "NRC_NORESOURCES requested resources are not available";    break; 
+    case 0x39: s = "NRC_INVADDRESS invalid ncb address or length > segment";   break; 
+    case 0x3B: s = "NRC_INVDDID invalid NCB DDID";                     break; 
+    case 0x3C: s = "NRC_LOCKFAILlock of user area failed";             break; 
+    case 0x3f: s = "NRC_OPENERR NETBIOS not loaded";                   break; 
+    case 0x40: s = "NRC_SYSTEM system error";                          break;                 
     default:   s = "unknown error";
     }
     return s;
@@ -456,7 +423,46 @@ char * myCrt_RapDispatch(int i)
     case 63:
         return "RAP(63)NetWkStaGetInfo";
     }
-}       
+}
+
+char * myCrt_NmpipeDispatch(int i)
+{
+    switch(i) {
+    case SMB_TRANS_SET_NMPIPE_STATE:
+       return "SET NMPIPE STATE";
+
+    case SMB_TRANS_RAW_READ_NMPIPE:
+       return "RAW READ NMPIPE";
+
+    case SMB_TRANS_QUERY_NMPIPE_STATE:
+       return "QUERY NMPIPE STATE";
+
+    case SMB_TRANS_QUERY_NMPIPE_INFO:
+       return "QUERY NMPIPE INFO";
+
+    case SMB_TRANS_PEEK_NMPIPE:
+       return "PEEK NMPIPE";
+
+    case SMB_TRANS_TRANSACT_NMPIPE:
+       return "TRANSACT NMPIPE";
+
+    case SMB_TRANS_RAW_WRITE_NMPIPE:
+       return "WRITE NMPIPE";
+
+    case SMB_TRANS_READ_NMPIPE:
+       return "READ NMPIPE";
+
+    case SMB_TRANS_WRITE_NMPIPE:
+       return "WRITE NMPIPE";
+
+    case SMB_TRANS_WAIT_NMPIPE:
+       return "WAIT NMPIPE";
+
+    case SMB_TRANS_CALL_NMPIPE:
+       return "CALL NMPIPE";
+    }
+    return "(Unknown)";
+}
 
 /* scache must be locked */
 unsigned int smb_Attributes(cm_scache_t *scp)
@@ -481,16 +487,34 @@ unsigned int smb_Attributes(cm_scache_t *scp)
      * turns out to be impolitic in NT.  See defect 10007.
      */
 #ifdef notdef
-    if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+    if ((scp->unixModeBits & 0200) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
         attrs |= SMB_ATTR_READONLY;    /* turn on read-only flag */
 #else
-    if ((scp->unixModeBits & 0222) == 0)
+    if ((scp->unixModeBits & 0200) == 0)
         attrs |= SMB_ATTR_READONLY;    /* turn on read-only flag */
 #endif
 
     return attrs;
 }
 
+void smb_SetInitialModeBitsForFile(int smb_attr, cm_attr_t * attr)
+{
+    if (smb_unixModeDefaultFile != 0) {
+        attr->mask |= CM_ATTRMASK_UNIXMODEBITS;
+        attr->unixModeBits = smb_unixModeDefaultFile;
+        if (smb_attr & SMB_ATTR_READONLY)
+            attr->unixModeBits &= ~0222;
+    }
+}
+
+void smb_SetInitialModeBitsForDir(int smb_attr, cm_attr_t * attr)
+{
+    if (smb_unixModeDefaultDir != 0) {
+        attr->mask |= CM_ATTRMASK_UNIXMODEBITS;
+        attr->unixModeBits = smb_unixModeDefaultDir;
+    }
+}
+
 /* Check if the named file/dir is a dotfile/dotdir */
 /* String pointed to by lastComp can have leading slashes, but otherwise should have
    no other patch components */
@@ -535,7 +559,7 @@ void ShowUnixTime(char *FuncName, time_t unixTime)
     FILETIME ft;
     WORD wDate, wTime;
 
-    smb_LargeSearchTimeFromUnixTime(&ft, unixTime);
+    cm_LargeSearchTimeFromUnixTime(&ft, unixTime);
 
     if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
         osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
@@ -636,184 +660,80 @@ void CompensateForSmbClientLastWriteTimeBugs(afs_uint32 *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.
- */
-static void
-smb_CalculateNowTZ()
+void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
 {
-    time_t t;
-    struct tm gmt_tm, local_tm;
-    int days, hours, minutes, seconds;
-
-    t = time(NULL);
-    gmt_tm = *(gmtime(&t));
-    local_tm = *(localtime(&t));
-
-    days = local_tm.tm_yday - gmt_tm.tm_yday;
-    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;
+    time_t diff_t = unixTime - smb_localZero;
+#if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
+    osi_assertx(diff_t < _UI32_MAX, "time_t > _UI32_MAX");
+#endif
+    *dosUTimep = (afs_uint32)diff_t;
 }
-#endif /* USE_NUMERIC_TIME_CONV */
 
-#ifdef USE_NUMERIC_TIME_CONV
-void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
 {
-    // Note that LONGLONG is a 64-bit value
-    LONGLONG ll;
-
-    ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
-    largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
-    largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
+    *unixTimep = dosTime + smb_localZero;
 }
-#else
-void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
+
+void smb_MarkAllVCsDead(smb_vc_t * exclude)
 {
-    struct tm *ltp;
-    SYSTEMTIME stm;
-    struct tm localJunk;
-    time_t ersatz_unixTime;
+    smb_vc_t *vcp;
+    smb_vc_t **vcp_to_cleanup = NULL;
+    int n_to_cleanup = 0;
+    int i;
 
-    /*
-     * Must use kludge-GMT instead of real GMT.
-     * kludge-GMT is computed by adding time zone difference to localtime.
-     *
-     * real GMT would be:
-     * ltp = gmtime(&unixTime);
-     */
-    ersatz_unixTime = unixTime - smb_NowTZ;
-    ltp = localtime(&ersatz_unixTime);
-
-    /* if we fail, make up something */
-    if (!ltp) {
-        ltp = &localJunk;
-        localJunk.tm_year = 89 - 20;
-        localJunk.tm_mon = 4;
-        localJunk.tm_mday = 12;
-        localJunk.tm_hour = 0;
-        localJunk.tm_min = 0;
-        localJunk.tm_sec = 0;
-    }
-
-    stm.wYear = ltp->tm_year + 1900;
-    stm.wMonth = ltp->tm_mon + 1;
-    stm.wDayOfWeek = ltp->tm_wday;
-    stm.wDay = ltp->tm_mday;
-    stm.wHour = ltp->tm_hour;
-    stm.wMinute = ltp->tm_min;
-    stm.wSecond = ltp->tm_sec;
-    stm.wMilliseconds = 0;
-
-    SystemTimeToFileTime(&stm, largeTimep);
-}
-#endif /* USE_NUMERIC_TIME_CONV */
+    osi_Log1(smb_logp, "Marking all VCs as dead excluding %p", exclude);
 
-#ifdef USE_NUMERIC_TIME_CONV
-void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
-{
-    // Note that LONGLONG is a 64-bit value
-    LONGLONG ll;
+    lock_ObtainWrite(&smb_globalLock); /* for dead_sessions[] */
+    lock_ObtainWrite(&smb_rctLock);
+    for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) {
 
-    ll = largeTimep->dwHighDateTime;
-    ll <<= 32;
-    ll += largeTimep->dwLowDateTime;
+       if (vcp->magic != SMB_VC_MAGIC)
+           osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", 
+                      __FILE__, __LINE__);
 
-    ll -= 116444736000000000;
-    ll /= 10000000;
+        if (vcp == exclude)
+            continue;
 
-    *unixTimep = (DWORD)ll;
-}
-#else /* USE_NUMERIC_TIME_CONV */
-void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
-{
-    SYSTEMTIME stm;
-    struct tm lt;
-    long save_timezone;
-
-    FileTimeToSystemTime(largeTimep, &stm);
-
-    lt.tm_year = stm.wYear - 1900;
-    lt.tm_mon = stm.wMonth - 1;
-    lt.tm_wday = stm.wDayOfWeek;
-    lt.tm_mday = stm.wDay;
-    lt.tm_hour = stm.wHour;
-    lt.tm_min = stm.wMinute;
-    lt.tm_sec = stm.wSecond;
-    lt.tm_isdst = -1;
-
-    save_timezone = _timezone;
-    _timezone += smb_NowTZ;
-    *unixTimep = mktime(&lt);
-    _timezone = save_timezone;
-}       
-#endif /* USE_NUMERIC_TIME_CONV */
-
-void smb_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
-{
-    struct tm *ltp;
-    int dosDate;
-    int dosTime;
-    struct tm localJunk;
-    time_t t = unixTime;
-
-    ltp = localtime(&t);
-
-    /* if we fail, make up something */
-    if (!ltp) {
-        ltp = &localJunk;
-        localJunk.tm_year = 89 - 20;
-        localJunk.tm_mon = 4;
-        localJunk.tm_mday = 12;
-        localJunk.tm_hour = 0;
-        localJunk.tm_min = 0;
-        localJunk.tm_sec = 0;
-    }  
+        lock_ObtainMutex(&vcp->mx);
+        if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+            vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+            lock_ReleaseMutex(&vcp->mx);
+            dead_sessions[vcp->session] = TRUE;
+        } else {
+            lock_ReleaseMutex(&vcp->mx);
+        }
+        n_to_cleanup ++;
+    }
 
-    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);
-    *searchTimep = (dosDate<<16) | dosTime;
-}      
+    vcp_to_cleanup = malloc(sizeof(vcp_to_cleanup[0]) * n_to_cleanup);
+    i = 0;
+    for (vcp = smb_allVCsp; vcp; vcp = vcp->nextp) {
+        if (vcp == exclude)
+            continue;
 
-void smb_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
-{
-    unsigned short dosDate;
-    unsigned short dosTime;
-    struct tm localTm;
-        
-    dosDate = (unsigned short) (searchTime & 0xffff);
-    dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
-
-    localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
-    localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1;       /* January is 0 in localTm */
-    localTm.tm_mday = (dosDate) & 0x1f;
-    localTm.tm_hour = (dosTime>>11) & 0x1f;
-    localTm.tm_min = (dosTime >> 5) & 0x3f;
-    localTm.tm_sec = (dosTime & 0x1f) * 2;
-    localTm.tm_isdst = -1;                             /* compute whether DST in effect */
-
-    *unixTimep = mktime(&localTm);
-}
+        vcp_to_cleanup[i++] = vcp;
+        smb_HoldVCNoLock(vcp);
+    }
 
-void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
-{
-    time_t diff_t = unixTime - smb_localZero;
-#if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
-    osi_assertx(diff_t < _UI32_MAX, "time_t > _UI32_MAX");
-#endif
-    *dosUTimep = (afs_uint32)diff_t;
-}
+    osi_assert(i == n_to_cleanup);
 
-void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
-{
-    *unixTimep = dosTime + smb_localZero;
+    lock_ReleaseWrite(&smb_rctLock);
+    lock_ReleaseWrite(&smb_globalLock);
+
+    for (i=0; i < n_to_cleanup; i++) {
+        smb_CleanupDeadVC(vcp_to_cleanup[i]);
+        smb_ReleaseVC(vcp_to_cleanup[i]);
+        vcp_to_cleanup[i] = 0;
+    }
+
+    free(vcp_to_cleanup);
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+smb_vc_t *smb_FindVCDbg(unsigned short lsn, int flags, int lana, char *file, long line)
+#else
 smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
+#endif
 {
     smb_vc_t *vcp;
 
@@ -824,11 +744,14 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
            osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", 
                       __FILE__, __LINE__);
 
+        lock_ObtainMutex(&vcp->mx);
         if (lsn == vcp->lsn && lana == vcp->lana &&
            !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+            lock_ReleaseMutex(&vcp->mx);
             smb_HoldVCNoLock(vcp);
             break;
         }
+        lock_ReleaseMutex(&vcp->mx);
     }
     if (!vcp && (flags & SMB_FLAG_CREATE)) {
         vcp = malloc(sizeof(*vcp));
@@ -841,7 +764,7 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
         vcp->uidCounter = 1;   /* UID 0 is reserved for blank user */
         vcp->nextp = smb_allVCsp;
         smb_allVCsp = vcp;
-        lock_InitializeMutex(&vcp->mx, "vc_t mutex");
+        lock_InitializeMutex(&vcp->mx, "vc_t mutex", LOCK_HIERARCHY_SMB_VC);
         vcp->lsn = lsn;
         vcp->lana = lana;
         vcp->secCtx = NULL;
@@ -874,7 +797,6 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
 
             if (ntsEx == STATUS_SUCCESS) {
                 memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
-                LsaFreeReturnBuffer(lsaResp);
             } else {
                 /* 
                  * This will cause the subsequent authentication to fail but
@@ -883,6 +805,8 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
                  */
                 memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
             }
+            if (lsaResp)
+                LsaFreeReturnBuffer(lsaResp);
         }
         else
             memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
@@ -892,12 +816,18 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
             osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
         }
     }
+#ifdef DEBUG_SMB_REFCOUNT
+    if (vcp) {
+        afsi_log("%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+    }
+#endif
     lock_ReleaseWrite(&smb_rctLock);
     lock_ReleaseWrite(&smb_globalLock);
     return vcp;
 }
 
-int smb_IsStarMask(clientchar_t *maskp)
+static int smb_Is8Dot3StarMask(clientchar_t *maskp)
 {
     int i;
     clientchar_t tc;
@@ -910,15 +840,37 @@ int smb_IsStarMask(clientchar_t *maskp)
     return 0;
 }
 
+static int smb_IsStarMask(clientchar_t *maskp)
+{
+    clientchar_t tc;
+        
+    while (*maskp) {
+        tc = *maskp++;
+        if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
+           return 1;
+    }
+    return 0;
+}
+
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCInternalDbg(smb_vc_t *vcp, char * file, long line)
+#define smb_ReleaseVCInternal(a) smb_ReleaseVCInternalDbg(a, file, line)
+#else
 void smb_ReleaseVCInternal(smb_vc_t *vcp)
+#endif
 {
     smb_vc_t **vcpp;
     smb_vc_t * avcp;
 
+    lock_AssertWrite(&smb_rctLock);
     vcp->refCount--;
 
     if (vcp->refCount == 0) {
         if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+#ifdef DEBUG_SMB_REFCOUNT
+            afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
+            osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
+#endif
             /* remove VCP from smb_deadVCsp */
             for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
                 if (*vcpp == vcp) {
@@ -930,45 +882,73 @@ void smb_ReleaseVCInternal(smb_vc_t *vcp)
             memset(vcp,0,sizeof(smb_vc_t));
             free(vcp);
         } else {
+#ifdef DEBUG_SMB_REFCOUNT
+            afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is alive ref %d", file, line, vcp, vcp->refCount);
+#endif
             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
+                      avcp?"":"not ",vcp, vcp->refCount);
+
             /* 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++;
+            if (avcp) {
+                vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+                afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
+                osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
+#endif
+            }
         }
     } else if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
         /* The reference count is non-zero but the VC is dead.
          * This implies that some FIDs, TIDs, etc on the VC have yet to 
-         * be cleaned up.  Add a reference that will be dropped by
+         * be cleaned up.  If we were not called by smb_CleanupDeadVC(),
+         * add a reference that will be dropped by
          * smb_CleanupDeadVC() and try to cleanup the VC again.
          * Eventually the refCount will drop to zero when all of the
          * active threads working with the VC end their task.
          */
-        vcp->refCount++;        /* put the refCount back */
-        lock_ReleaseWrite(&smb_rctLock);
-        smb_CleanupDeadVC(vcp);
-        lock_ObtainWrite(&smb_rctLock);
+        if (!(vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS)) {
+            vcp->refCount++;        /* put the refCount back */
+            lock_ReleaseWrite(&smb_rctLock);
+            smb_CleanupDeadVC(vcp);
+#ifdef DEBUG_SMB_REFCOUNT
+            afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
+            osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
+#endif
+            lock_ObtainWrite(&smb_rctLock);
+        }
+    } else {
+#ifdef DEBUG_SMB_REFCOUNT
+        afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+#endif
     }
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
+#else
 void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+#endif
 {
+    lock_AssertWrite(&smb_rctLock);
     osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
     smb_ReleaseVCInternal(vcp);
 }       
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCDbg(smb_vc_t *vcp, char * file, long line)
+#else
 void smb_ReleaseVC(smb_vc_t *vcp)
+#endif
 {
     lock_ObtainWrite(&smb_rctLock);
     osi_Log2(smb_logp,"smb_ReleaseVC       vcp %x ref %d",vcp, vcp->refCount);
@@ -976,17 +956,36 @@ void smb_ReleaseVC(smb_vc_t *vcp)
     lock_ReleaseWrite(&smb_rctLock);
 }       
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
+#else
 void smb_HoldVCNoLock(smb_vc_t *vcp)
+#endif
 {
+    lock_AssertWrite(&smb_rctLock);
     vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+    osi_Log4(smb_logp,"%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+#else
     osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+#endif
 }       
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldVCDbg(smb_vc_t *vcp, char * file, long line)
+#else
 void smb_HoldVC(smb_vc_t *vcp)
+#endif
 {
     lock_ObtainWrite(&smb_rctLock);
     vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_HoldVC       vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+    osi_Log4(smb_logp,"%s:%d smb_HoldVC       vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+#else
     osi_Log2(smb_logp,"smb_HoldVC       vcp %x ref %d",vcp, vcp->refCount);
+#endif
     lock_ReleaseWrite(&smb_rctLock);
 }       
 
@@ -1078,15 +1077,14 @@ void smb_CleanupDeadVC(smb_vc_t *vcp)
     }
 
     /* 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 */
-    refCount = vcp->refCount;
-    smb_ReleaseVCNoLock(vcp);
-
-    /* 
+     * reference so that the refcount can reach 0 and we can delete it 
+     *
      * If the refCount == 1 going into the ReleaseVCNoLock call 
      * the object will be freed and it won't be safe to clear 
      * the flag.
      */
+    refCount = vcp->refCount;
+    smb_ReleaseVCNoLock(vcp);
     if (refCount > 1) {
         lock_ObtainMutex(&vcp->mx);
         vcp->flags &= ~SMB_VCFLAG_CLEAN_IN_PROGRESS;
@@ -1097,7 +1095,11 @@ void smb_CleanupDeadVC(smb_vc_t *vcp)
     osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+smb_tid_t *smb_FindTIDDbg(smb_vc_t *vcp, unsigned short tid, int flags, char * file, long line)
+#else
 smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
+#endif
 {
     smb_tid_t *tidp;
 
@@ -1123,42 +1125,73 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
         tidp->vcp = vcp;
         smb_HoldVCNoLock(vcp);
         vcp->tidsp = tidp;
-        lock_InitializeMutex(&tidp->mx, "tid_t mutex");
+        lock_InitializeMutex(&tidp->mx, "tid_t mutex", LOCK_HIERARCHY_SMB_TID);
         tidp->tid = tid;
     }
+#ifdef DEBUG_SMB_REFCOUNT
+    if (tidp) {
+        afsi_log("%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+    }
+#endif
     lock_ReleaseWrite(&smb_rctLock);
     return tidp;
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldTIDNoLockDbg(smb_tid_t *tidp, char * file, long line)
+#else
 void smb_HoldTIDNoLock(smb_tid_t *tidp)
+#endif
 {
+    lock_AssertWrite(&smb_rctLock);
     tidp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+    osi_Log4(smb_logp,"%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+#endif
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseTIDDbg(smb_tid_t *tidp, afs_uint32 locked, char *file, long line)
+#else
 void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked)
+#endif
 {
     smb_tid_t *tp;
     smb_tid_t **ltpp;
-    cm_user_t *userp;
+    cm_user_t *userp = NULL;
+    smb_vc_t  *vcp = NULL;
 
-    userp = NULL;
     if (!locked)
         lock_ObtainWrite(&smb_rctLock);
+    else
+        lock_AssertWrite(&smb_rctLock);
+
     osi_assertx(tidp->refCount-- > 0, "smb_tid_t refCount 0");
-    if (tidp->refCount == 0 && (tidp->deleteOk)) {
-        ltpp = &tidp->vcp->tidsp;
-        for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
-            if (tp == tidp) 
-                break;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
+    osi_Log5(smb_logp,"%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
+#endif
+    if (tidp->refCount == 0) {
+        if (tidp->deleteOk) {
+            ltpp = &tidp->vcp->tidsp;
+            for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
+                if (tp == tidp) 
+                    break;
+            }
+            osi_assertx(tp != NULL, "null smb_tid_t");
+            *ltpp = tp->nextp;
+            lock_FinalizeMutex(&tidp->mx);
+            userp = tidp->userp;       /* remember to drop ref later */
+            tidp->userp = NULL;
+            vcp = tidp->vcp;
+            tidp->vcp = NULL;
+            free(tidp);
         }
-        osi_assertx(tp != NULL, "null smb_tid_t");
-        *ltpp = tp->nextp;
-        lock_FinalizeMutex(&tidp->mx);
-        userp = tidp->userp;   /* remember to drop ref later */
-        tidp->userp = NULL;
-        smb_ReleaseVCNoLock(tidp->vcp);
-        tidp->vcp = NULL;
     }
+    if (vcp)
+        smb_ReleaseVCNoLock(vcp);
     if (!locked)
         lock_ReleaseWrite(&smb_rctLock);
     if (userp)
@@ -1187,7 +1220,7 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
         uidp->vcp = vcp;
         smb_HoldVCNoLock(vcp);
         vcp->usersp = uidp;
-        lock_InitializeMutex(&uidp->mx, "user_t mutex");
+        lock_InitializeMutex(&uidp->mx, "user_t mutex", LOCK_HIERARCHY_SMB_UID);
         uidp->userID = uid;
         osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%S]",
                 vcp, uidp->userID,
@@ -1218,7 +1251,7 @@ smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine,
         unp->name = cm_ClientStrDup(usern);
         unp->machine = cm_ClientStrDup(machine);
         usernamesp = unp;
-        lock_InitializeMutex(&unp->mx, "username_t mutex");
+        lock_InitializeMutex(&unp->mx, "username_t mutex", LOCK_HIERARCHY_SMB_USERNAME);
        if (flags & SMB_FLAG_AFSLOGON)
            unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
     }
@@ -1279,6 +1312,7 @@ void smb_ReleaseUsername(smb_username_t *unp)
 
 void smb_HoldUIDNoLock(smb_user_t *uidp)
 {
+    lock_AssertWrite(&smb_rctLock);
     uidp->refCount++;
 }
 
@@ -1398,32 +1432,44 @@ int smb_SUser(cm_user_t *userp)
  * If the SMB_FLAG_CREATE flag is set, we allocate a new  
  * smb_fid_t data structure if desired File ID cannot be found.
  */
+#ifdef DEBUG_SMB_REFCOUNT
+smb_fid_t *smb_FindFIDDbg(smb_vc_t *vcp, unsigned short fid, int flags, char *file, long line)
+#else
 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
+#endif
 {
     smb_fid_t *fidp;
     int newFid = 0;
         
-    if (fid == 0 && !(flags & SMB_FLAG_CREATE))
-        return NULL;
-
-    lock_ObtainWrite(&smb_rctLock);
-    /* figure out if we need to allocate a new file ID */
     if (fid == 0) {
+        if (!(flags & SMB_FLAG_CREATE))
+            return NULL;
         newFid = 1;
-        fid = vcp->fidCounter;
     }
 
+    lock_ObtainWrite(&smb_rctLock);
+    if (newFid)
+        fid = vcp->fidCounter;
   retry:
+
     for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
        if (fidp->refCount == 0 && fidp->deleteOk) {
            fidp->refCount++;
            lock_ReleaseWrite(&smb_rctLock);
            smb_ReleaseFID(fidp);
            lock_ObtainWrite(&smb_rctLock);
+            /*
+             * We dropped the smb_rctLock so the fid value we are using
+             * may now be used by another thread.  Start over with the
+             * current vcp->fidCounter.
+             */
+            if (newFid)
+                fid = vcp->fidCounter;
            goto retry;
        }
         if (fid == fidp->fid) {
             if (newFid) {
+                osi_Log1(smb_logp, "smb_FindFID New Fid Requested.  fid %d found -- retrying ...", fid);
                 fid++;
                 if (fid == 0xFFFF) {
                     osi_Log1(smb_logp,
@@ -1440,6 +1486,12 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
     if (!fidp && (flags & SMB_FLAG_CREATE)) {
         char eventName[MAX_PATH];
         EVENT_HANDLE event;
+
+        if (!newFid)
+            osi_Log1(smb_logp, "smb_FindFID New Fid Not Requested, Fid %d Not Found and CREATE flag set.", fid);
+        else
+            osi_Log1(smb_logp, "smb_FindFID New Fid Requested.  Creating fid %d", fid);
+
         sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
         event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
         if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
@@ -1459,7 +1511,7 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
         fidp->refCount = 1;
         fidp->vcp = vcp;
         smb_HoldVCNoLock(vcp);
-        lock_InitializeMutex(&fidp->mx, "fid_t mutex");
+        lock_InitializeMutex(&fidp->mx, "fid_t mutex", LOCK_HIERARCHY_SMB_FID);
         fidp->fid = fid;
         fidp->curr_chunk = fidp->prev_chunk = -2;
         fidp->raw_write_event = event;
@@ -1473,38 +1525,103 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
        }
     }
 
+#ifdef DEBUG_SMB_REFCOUNT
+    if (fidp) {
+        afsi_log("%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+    }
+#endif
     lock_ReleaseWrite(&smb_rctLock);
     return fidp;
 }
 
+
+/* Must not be called with scp->rw held because smb_ReleaseFID might be called */
+#ifdef DEBUG_SMB_REFCOUNT
+smb_fid_t *smb_FindFIDByScacheDbg(smb_vc_t *vcp, cm_scache_t * scp, char *file, long line)
+#else
 smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
+#endif
 {
-    smb_fid_t *fidp = NULL;
-    int newFid = 0;
+    smb_fid_t *fidp = NULL, *nextp = NULL;
         
     if (!scp)
         return NULL;
 
+    /* 
+     * If the fidp->scp changes out from under us then
+     * we must not grab a refCount.  It means the *fidp
+     * was processed by smb_CloseFID() and the *fidp is 
+     * no longer valid for use.
+     */
     lock_ObtainWrite(&smb_rctLock);
-    for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
+       for(fidp = vcp->fidsp, (fidp ? fidp->refCount++ : 0); fidp; fidp = nextp, nextp = NULL) {
+        nextp = (smb_fid_t *) osi_QNext(&fidp->q);
+        if (nextp)
+            nextp->refCount++;
+
         if (scp == fidp->scp) {
-            fidp->refCount++;
-            break;
+            lock_ReleaseWrite(&smb_rctLock);
+            lock_ObtainMutex(&fidp->mx);
+            lock_ObtainWrite(&smb_rctLock);
+            if (scp == fidp->scp) {
+                lock_ReleaseMutex(&fidp->mx);
+                break;
+            }
+            lock_ReleaseMutex(&fidp->mx);
+        }
+
+        if (fidp->refCount > 1) {
+            fidp->refCount--;
+        } else {
+            lock_ReleaseWrite(&smb_rctLock);
+            smb_ReleaseFID(fidp);
+            lock_ObtainWrite(&smb_rctLock);
+        }
+    }
+
+    if (nextp) {
+        if (nextp->refCount > 1) {
+            nextp->refCount--;
+        } else {
+            lock_ReleaseWrite(&smb_rctLock);
+            smb_ReleaseFID(nextp);
+            lock_ObtainWrite(&smb_rctLock);
         }
     }
+
+#ifdef DEBUG_SMB_REFCOUNT
+    if (fidp) {
+        afsi_log("%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+      }
+#endif
     lock_ReleaseWrite(&smb_rctLock);
-    return fidp;
+    return (fidp);
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldFIDNoLockDbg(smb_fid_t *fidp, char *file, long line)
+#else
 void smb_HoldFIDNoLock(smb_fid_t *fidp)
+#endif
 {
+    lock_AssertWrite(&smb_rctLock);
     fidp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+    osi_Log4(smb_logp,"%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+#endif
 }
 
 
-/* smb_ReleaseFID cannot be called while an cm_scache_t mutex lock is held */
-/* the sm_fid_t->mx and smb_rctLock must not be held */
+/* smb_ReleaseFID cannot be called while a cm_scache_t rwlock is held */
+/* the smb_fid_t->mx and smb_rctLock must not be held */
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseFIDDbg(smb_fid_t *fidp, char *file, long line)
+#else
 void smb_ReleaseFID(smb_fid_t *fidp)
+#endif
 {
     cm_scache_t *scp = NULL;
     cm_user_t *userp = NULL;
@@ -1514,44 +1631,55 @@ void smb_ReleaseFID(smb_fid_t *fidp)
     lock_ObtainMutex(&fidp->mx);
     lock_ObtainWrite(&smb_rctLock);
     osi_assertx(fidp->refCount-- > 0, "smb_fid_t refCount 0");
-    if (fidp->refCount == 0 && (fidp->deleteOk)) {
-        vcp = fidp->vcp;
-        fidp->vcp = NULL;
-        scp = fidp->scp;    /* release after lock is released */
-       if (scp) {
-           lock_ObtainWrite(&scp->rw);
-           scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
-           lock_ReleaseWrite(&scp->rw);
-           osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
-           fidp->scp = NULL;
-       }
-        userp = fidp->userp;
-        fidp->userp = NULL;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
+    osi_Log5(smb_logp,"%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
+#endif
+    if (fidp->refCount == 0) {
+        if (fidp->deleteOk) {
+            vcp = fidp->vcp;
+            fidp->vcp = NULL;
+            scp = fidp->scp;    /* release after lock is released */
+            if (scp) {
+                lock_ObtainWrite(&scp->rw);
+                scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
+                lock_ReleaseWrite(&scp->rw);
+                osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
+                fidp->scp = NULL;
+            }
+            userp = fidp->userp;
+            fidp->userp = NULL;
 
-       if (vcp->fidsp) 
-           osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
-        thrd_CloseHandle(fidp->raw_write_event);
+            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)
+            /* and see if there is ioctl stuff to free */
+            ioctlp = fidp->ioctlp;
+            if (ioctlp) {
+                if (ioctlp->prefix)
                 cm_FreeSpace(ioctlp->prefix);
-            if (ioctlp->ioctl.inAllocp)
-                free(ioctlp->ioctl.inAllocp);
-            if (ioctlp->ioctl.outAllocp)
-                free(ioctlp->ioctl.outAllocp);
-            free(ioctlp);
-        }       
-       lock_ReleaseMutex(&fidp->mx);
-       lock_FinalizeMutex(&fidp->mx);
-        free(fidp);
+                if (ioctlp->ioctl.inAllocp)
+                    free(ioctlp->ioctl.inAllocp);
+                if (ioctlp->ioctl.outAllocp)
+                    free(ioctlp->ioctl.outAllocp);
+                free(ioctlp);
+            }
 
-       if (vcp)
-           smb_ReleaseVCNoLock(vcp);
-    } else {
-       lock_ReleaseMutex(&fidp->mx);
+           smb_CleanupRPCFid(fidp);
+
+            lock_ReleaseMutex(&fidp->mx);
+            lock_FinalizeMutex(&fidp->mx);
+            free(fidp);
+            fidp = NULL;
+
+            if (vcp)
+                smb_ReleaseVCNoLock(vcp);
+        }
     }
+    if (fidp)
+        lock_ReleaseMutex(&fidp->mx);
+
     lock_ReleaseWrite(&smb_rctLock);
 
     /* now release the scache structure */
@@ -1613,14 +1741,19 @@ long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
     smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
     normchar_t normName[MAX_PATH];
 
-    cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0]));
+    if (cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0])) == 0) {
+        osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+                 osi_LogSaveString(smb_logp, dep->name));
+        return 0;
+    }
 
     if (!cm_ClientStrCmpNI(normName, vrock->shareName, 12)) {
         if(!cm_ClientStrCmpI(normName, vrock->shareName))
             matchType = SMB_FINDSHARE_EXACT_MATCH;
         else
             matchType = SMB_FINDSHARE_PARTIAL_MATCH;
-        if(vrock->match) free(vrock->match);
+        if(vrock->match) 
+            free(vrock->match);
         vrock->match = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
         vrock->matchType = matchType;
 
@@ -1677,9 +1810,7 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
         return 1;
     }
 
-    if (cm_ClientStrCmpIA(shareName, _C("IPC$")) == 0 ||
-        cm_ClientStrCmpIA(shareName, _C("srvsvc")) == 0 ||
-        cm_ClientStrCmpIA(shareName, _C("wkssvc")) == 0 ||
+    if (MSRPC_IsWellKnownService(shareName) ||
         cm_ClientStrCmpIA(shareName, _C(SMB_IOCTL_FILENAME_NOSLASH)) == 0 ||
         cm_ClientStrCmpIA(shareName, _C("DESKTOP.INI")) == 0
         ) {
@@ -1741,7 +1872,7 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
 
         if (cm_ClientStrCmpN(p, cm_mountRootC, cm_mountRootCLen) == 0) {
             p += cm_mountRootCLen;  /* skip mount path */
-            cchlen -= (p - pathName);
+            cchlen -= (DWORD)(p - pathName);
         }
 
         q = p;
@@ -1801,11 +1932,13 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
         /*  attempt to locate a partial match in root.afs.  This is because
             when using the ANSI RAP calls, the share name is limited to 13 chars
             and hence is truncated. Of course we prefer exact matches. */
-        cm_InitReq(&req);
+        smb_InitReq(&req);
         thyper.HighPart = 0;
         thyper.LowPart = 0;
 
         vrock.shareName = cm_ClientStringToNormStringAlloc(shareName, -1, NULL);
+        if (vrock.shareName == NULL) 
+            return 0;
         vrock.match = NULL;
         vrock.matchType = 0;
 
@@ -1831,14 +1964,14 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
             rw = 1;
         }
         /* Get the full name for this cell */
-        cellname = cm_ClientStringToFsStringAlloc(p, cm_ClientStrLen(p), NULL);
-        code = cm_SearchCellFile(cellname, ftemp, 0, 0);
-#ifdef AFS_AFSDB_ENV
+        cellname = cm_ClientStringToFsStringAlloc(p, -1, NULL);
+        code = cm_SearchCellRegistry(1, cellname, ftemp, 0, 0, 0);
+        if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
+            code = cm_SearchCellFile(cellname, ftemp, 0, 0);
         if (code && cm_dnsEnabled) {
             int ttl;
             code = cm_SearchCellByDNS(cellname, ftemp, &ttl, 0, 0);
         }
-#endif
         if (cellname)
             free(cellname);
 
@@ -1846,13 +1979,14 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
         if (code == 0) {
             clientchar_t temp[1024];
 
-            cm_FsStringToClientString(ftemp, cm_FsStrLen(ftemp), temp, 1024);
-            cm_ClientStrPrintfN(pathName, lengthof(pathName),
+            if (cm_FsStringToClientString(ftemp, -1, temp, 1024) != 0) {
+            cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
                                 rw ? _C("/.%S/") : _C("/%S/"), temp);
             *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
             return 1;
         }
     }
+    }
     /* failure */
     *pathNamep = NULL;
     return 0;
@@ -1872,21 +2006,26 @@ int smb_FindShareCSCPolicy(clientchar_t *shareName)
     HKEY hkCSCPolicy;
     int  retval = CSC_POLICY_MANUAL;
 
-    RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
-                    AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
-                    0, 
-                    "AFS", 
-                    REG_OPTION_NON_VOLATILE,
-                    KEY_READ,
-                    NULL, 
-                    &hkCSCPolicy,
-                    NULL );
+    if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+                        AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
+                        0,
+                        "AFS",
+                        REG_OPTION_NON_VOLATILE,
+                        KEY_READ,
+                        NULL,
+                        &hkCSCPolicy,
+                        NULL ) != ERROR_SUCCESS)
+        retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
 
     len = sizeof(policy);
     if ( RegQueryValueExW( hkCSCPolicy, shareName, 0, &dwType, (LPBYTE) policy, &len ) ||
          len == 0) {
         retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
     }
+    else if (cm_ClientStrCmpIA(policy, _C("manual")) == 0)
+    {
+        retval = CSC_POLICY_MANUAL;
+    }
     else if (cm_ClientStrCmpIA(policy, _C("documents")) == 0)
     {
         retval = CSC_POLICY_DOCUMENTS;
@@ -1922,9 +2061,7 @@ smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
                 if (!smb_lastDirSearchp)
                     smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
             }
-            lock_ObtainMutex(&dsp->mx);
             dsp->refCount++;
-            lock_ReleaseMutex(&dsp->mx);
             break;
         }
     }
@@ -1940,7 +2077,6 @@ smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
 
 void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
 {
-    lock_ObtainWrite(&smb_globalLock);
     lock_ObtainMutex(&dsp->mx);
     osi_Log3(smb_logp,"smb_DeleteDirSearch cookie %d dsp 0x%p scp 0x%p", 
              dsp->cookie, dsp, dsp->scp);
@@ -1955,7 +2091,6 @@ void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
         lock_ReleaseWrite(&dsp->scp->rw);
     }  
     lock_ReleaseMutex(&dsp->mx);
-    lock_ReleaseWrite(&smb_globalLock);
 }               
 
 /* Must be called with the smb_globalLock held */
@@ -1963,20 +2098,22 @@ void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
 {
     cm_scache_t *scp = NULL;
 
-    lock_ObtainMutex(&dsp->mx);
     osi_assertx(dsp->refCount-- > 0, "cm_scache_t refCount 0");
-    if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
-        if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
-            smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
-        osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
-        lock_ReleaseMutex(&dsp->mx);
-        lock_FinalizeMutex(&dsp->mx);
-        scp = dsp->scp;
-       osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p", 
-                dsp->cookie, dsp, scp);
-        free(dsp);
-    } else {
-        lock_ReleaseMutex(&dsp->mx);
+    if (dsp->refCount == 0) {
+        lock_ObtainMutex(&dsp->mx);
+        if (dsp->flags & SMB_DIRSEARCH_DELETE) {
+            if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
+                smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
+            osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+            lock_ReleaseMutex(&dsp->mx);
+            lock_FinalizeMutex(&dsp->mx);
+            scp = dsp->scp;
+            osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p", 
+                     dsp->cookie, dsp, scp);
+            free(dsp);
+        } else {
+            lock_ReleaseMutex(&dsp->mx);
+        }
     }
     /* do this now to avoid spurious locking hierarchy creation */
     if (scp) 
@@ -2008,28 +2145,28 @@ smb_dirSearch_t *smb_FindDirSearch(long cookie)
 void smb_GCDirSearches(int isV3)
 {
     smb_dirSearch_t *prevp;
-    smb_dirSearch_t *tp;
+    smb_dirSearch_t *dsp;
     smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
     int victimCount;
     int i;
         
     victimCount = 0;   /* how many have we got so far */
-    for (tp = smb_lastDirSearchp; tp; tp=prevp) {
+    for (dsp = smb_lastDirSearchp; dsp; dsp=prevp) {
         /* we'll move tp from queue, so
          * do this early.
          */
-        prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q); 
+        prevp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);        
         /* if no one is using this guy, and we're either in the new protocol,
          * or we're in the old one and this is a small enough ID to be useful
          * to the old protocol, GC this guy.
          */
-        if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
+        if (dsp->refCount == 0 && (isV3 || dsp->cookie <= 255)) {
             /* hold and delete */
-           lock_ObtainMutex(&tp->mx);
-            tp->flags |= SMB_DIRSEARCH_DELETE;
-           lock_ReleaseMutex(&tp->mx);
-            victimsp[victimCount++] = tp;
-            tp->refCount++;
+           lock_ObtainMutex(&dsp->mx);
+            dsp->flags |= SMB_DIRSEARCH_DELETE;
+           lock_ReleaseMutex(&dsp->mx);
+            victimsp[victimCount++] = dsp;
+            dsp->refCount++;
         }
 
         /* don't do more than this */
@@ -2089,9 +2226,7 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
             /* don't need to watch for refcount zero and deleted, since
             * we haven't dropped the global lock.
             */
-            lock_ObtainMutex(&dsp->mx);
             dsp->refCount--;
-            lock_ReleaseMutex(&dsp->mx);
             ++smb_dirSearchCounter;
             continue;
         }      
@@ -2101,7 +2236,7 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
         dsp->cookie = smb_dirSearchCounter;
         ++smb_dirSearchCounter;
         dsp->refCount = 1;
-        lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
+        lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t", LOCK_HIERARCHY_SMB_DIRSEARCH);
         dsp->lastTime = osi_Time();
         osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
         if (!smb_lastDirSearchp) 
@@ -2115,7 +2250,7 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
     return dsp;
 }
 
-static smb_packet_t *GetPacket(void)
+static smb_packet_t *smb_GetPacket(void)
 {
     smb_packet_t *tbp;
 
@@ -2148,7 +2283,7 @@ static smb_packet_t *GetPacket(void)
 smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
 {
     smb_packet_t *tbp;
-    tbp = GetPacket();
+    tbp = smb_GetPacket();
     memcpy(tbp, pkt, sizeof(smb_packet_t));
     tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
     tbp->stringsp = NULL;
@@ -2157,7 +2292,7 @@ smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
     return tbp;
 }
 
-static NCB *GetNCB(void)
+static NCB *smb_GetNCB(void)
 {
     smb_ncb_t *tbp;
     NCB *ncbp;
@@ -2218,7 +2353,7 @@ void smb_FreePacket(smb_packet_t *tbp)
         smb_ReleaseVC(vcp);
 }
 
-static void FreeNCB(NCB *bufferp)
+static void smb_FreeNCB(NCB *bufferp)
 {
     smb_ncb_t *tbp;
         
@@ -2425,11 +2560,37 @@ void smb_StripLastComponent(clientchar_t *outPathp, clientchar_t **lastComponent
                             clientchar_t *inPathp)
 {
     clientchar_t *lastSlashp;
-        
+    clientchar_t *streamp = NULL;
+    clientchar_t *typep = NULL;
+
     lastSlashp = cm_ClientStrRChr(inPathp, '\\');
-    if (lastComponentp)
+    if (lastComponentp) {
         *lastComponentp = lastSlashp;
+    }
     if (lastSlashp) {
+        /*
+         * If the name contains a stream name and a type
+         * and the stream name is the nul-string and the
+         * type is $DATA, then strip "::$DATA" from the
+         * last component string that is returned.
+         *
+         * Otherwise, return the full path name and allow
+         * the file name to be rejected because it contains
+         * a colon.
+         */
+        typep = cm_ClientStrRChr(lastSlashp, L':');
+        if (typep && cm_ClientStrCmpI(typep, L":$DATA") == 0) {
+            *typep = '\0';
+            streamp = cm_ClientStrRChr(lastSlashp, L':');
+            if (streamp && cm_ClientStrCmpI(streamp, L":") == 0) {
+                *streamp = '\0';
+            } else
+                *typep = ':';
+            osi_Log2(smb_logp, "smb_StripLastComponent found stream [%S] type [%S]",
+                     osi_LogSaveClientString(smb_logp,streamp),
+                     osi_LogSaveClientString(smb_logp,typep));
+        }
+
         while (1) {
             if (inPathp == lastSlashp) 
                 break;
@@ -2446,22 +2607,42 @@ clientchar_t *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp,
                                   char **chainpp, int flags)
 {
     size_t cb;
+    afs_uint32 type = *inp++;
 
-    if (*inp++ != 0x4) 
-        return NULL;
+    /* 
+     * The first byte specifies the type of the input string.
+     * CIFS TR 1.0 3.2.10.  This function only parses null terminated
+     * strings.
+     */
+    switch (type) {
+    /* Length Counted */
+    case 0x1: /* Data Block */
+    case 0x5: /* Variable Block */
+        cb = *inp++ << 16 | *inp++;
+        break;
+
+    /* Null-terminated string */
+    case 0x4: /* ASCII */
+    case 0x3: /* Pathname */
+    case 0x2: /* Dialect */
+        cb = sizeof(pktp->data) - (inp - pktp->data);
+        if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
+#ifdef DEBUG_UNICODE
+            DebugBreak();
+#endif
+            cb = sizeof(pktp->data);
+        }
+        break;
+
+    default:
+        return NULL;            /* invalid input */
+    }
 
 #ifdef SMB_UNICODE
-    if (!WANTS_UNICODE(pktp))
+    if (type == 0x2 /* Dialect */ || !WANTS_UNICODE(pktp))
         flags |= SMB_STRF_FORCEASCII;
 #endif
 
-    cb = sizeof(pktp->data) - (inp - pktp->data);
-    if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
-#ifdef DEBUG_UNICODE
-        DebugBreak();
-#endif
-        cb = sizeof(pktp->data);
-    }
     return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
 }
 
@@ -2482,7 +2663,8 @@ clientchar_t *smb_ParseString(smb_packet_t * pktp, unsigned char * inp,
 #endif
         cb = sizeof(pktp->data);
     }
-    return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+    return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp,
+                              flags | SMB_STRF_SRCNULTERM);
 }
 
 clientchar_t *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
@@ -2578,7 +2760,8 @@ smb_ParseStringBuf(const unsigned char * bufbase,
         *stringspp = spacep;
 
         cchdest = lengthof(spacep->wdata);
-        cm_Utf8ToUtf16(inp, *pcb_max, spacep->wdata, cchdest);
+        cm_Utf8ToUtf16(inp, (int)((flags & SMB_STRF_SRCNULTERM)? -1 : *pcb_max),
+                       spacep->wdata, cchdest);
 
         return spacep->wdata;
 #ifdef SMB_UNICODE
@@ -2604,7 +2787,7 @@ unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
         if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
 
             StringCbLengthW(str, SMB_STRINGBUFSIZE * sizeof(wchar_t), plen);
-            if (!(flags & SMB_STRF_IGNORENULL))
+            if (!(flags & SMB_STRF_IGNORENUL))
                 *plen += sizeof(wchar_t);
 
             return (unsigned char *) 1; /* return TRUE if we are using unicode */
@@ -2614,14 +2797,14 @@ unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
         {
             /* Storing ANSI */
 
-            int cch_str;
-            int cch_dest;
+            size_t cch_str;
+            size_t cch_dest;
 
             cch_str = cm_ClientStrLen(str);
-            cch_dest = cm_ClientStringToUtf8(str, cch_str, NULL, 0);
+            cch_dest = cm_ClientStringToUtf8(str, (int)cch_str, NULL, 0);
 
             if (plen)
-                *plen = ((flags & SMB_STRF_IGNORENULL)? cch_dest: cch_dest+1);
+                *plen = ((flags & SMB_STRF_IGNORENUL)? cch_dest: cch_dest+1);
 
             return NULL;
         }
@@ -2639,11 +2822,11 @@ unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
 
     */
     if (outp >= pktp->data && outp < pktp->data + sizeof(pktp->data)) {
-        align = ((outp - pktp->data) % 2);
+        align = (int)((outp - pktp->data) % 2);
         buffersize = (pktp->data + sizeof(pktp->data)) - ((char *) outp);
     } else {
-        align = (((size_t) outp) % 2);
-        buffersize = sizeof(pktp->data);
+        align = (int)(((size_t) outp) % 2);
+        buffersize = (int)sizeof(pktp->data);
     }
 
 #ifdef SMB_UNICODE
@@ -2660,12 +2843,12 @@ unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
                 return NULL;
 
             *((wchar_t *) outp) = L'\0';
-            if (plen && !(flags & SMB_STRF_IGNORENULL))
+            if (plen && !(flags & SMB_STRF_IGNORENUL))
                 *plen += sizeof(wchar_t);
             return outp + sizeof(wchar_t);
         }
 
-        nchars = cm_ClientStringToUtf16(str, -1, (wchar_t *) outp, buffersize / sizeof(wchar_t));
+        nchars = cm_ClientStringToUtf16(str, -1, (wchar_t *) outp, (int)(buffersize / sizeof(wchar_t)));
         if (nchars == 0) {
             osi_Log2(smb_logp, "UnparseString: Can't convert string to Unicode [%S], GLE=%d",
                      osi_LogSaveClientString(smb_logp, str),
@@ -2674,7 +2857,7 @@ unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
         }
 
         if (plen)
-            *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENULL)? nchars - 1: nchars);
+            *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENUL)? nchars - 1: nchars);
 
         return outp + sizeof(wchar_t) * nchars;
     }
@@ -2684,10 +2867,10 @@ unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
         /* Storing ANSI */
         size_t cch_dest;
 
-        cch_dest = cm_ClientStringToUtf8(str, -1, outp, buffersize);
+        cch_dest = cm_ClientStringToUtf8(str, -1, outp, (int)buffersize);
 
         if (plen)
-            *plen += ((flags & SMB_STRF_IGNORENULL)? cch_dest - 1: cch_dest);
+            *plen += ((flags & SMB_STRF_IGNORENUL)? cch_dest - 1: cch_dest);
 
         return outp + cch_dest;
     }
@@ -2784,11 +2967,11 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
         
     ncbp = inp->ncbp;
     if (ncbp == NULL) {
-        ncbp = GetNCB();
+        ncbp = smb_GetNCB();
         localNCB = 1;
     }
  
-    memset((char *)ncbp, 0, sizeof(NCB));
+    memset(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 */
@@ -2824,7 +3007,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
     }
 
     if (localNCB)
-        FreeNCB(ncbp);
+        smb_FreeNCB(ncbp);
 }
 
 void smb_MapNTError(long code, unsigned long *NTStatusp)
@@ -2833,21 +3016,36 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
 
     /* map CM_ERROR_* errors to NT 32-bit status codes */
     /* NT Status codes are listed in ntstatus.h not winerror.h */
-    if (code == CM_ERROR_NOSUCHCELL) {
-        NTStatus = 0xC000000FL;        /* No such file */
+    if (code == 0) {
+        NTStatus = 0;
+    } 
+    else if (code == CM_ERROR_NOSUCHCELL) {
+        NTStatus = 0xC0000034L;        /* Name not found */
     }
     else if (code == CM_ERROR_NOSUCHVOLUME) {
-        NTStatus = 0xC000000FL;        /* No such file */
+        NTStatus = 0xC0000034L;        /* Name not found */
     }
     else if (code == CM_ERROR_TIMEDOUT) {
 #ifdef COMMENT
         NTStatus = 0xC00000CFL;        /* Sharing Paused */
-#else
+
+        /* Do not send Timeout to the SMB redirector.
+         * It causes the redirector to drop the connection */
         NTStatus = 0x00000102L; /* Timeout */
+        /* do not send Retry to the SMB redirector.
+         * It believes the error comes from the transport
+         * layer not from the SMB server. */
+        NTStatus = 0xC000022DL;        /* Retry */
+#else
+        NTStatus = 0xC00000B5L;        /* I/O Timeout */
 #endif
     }
     else if (code == CM_ERROR_RETRY) {
+#ifdef COMMENT
         NTStatus = 0xC000022DL;        /* Retry */
+#else
+        NTStatus = 0xC00000B5L; /* I/O Timeout */
+#endif
     }
     else if (code == CM_ERROR_NOACCESS) {
         NTStatus = 0xC0000022L;        /* Access denied */
@@ -2857,7 +3055,7 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     }
     else if (code == CM_ERROR_NOSUCHFILE ||
              code == CM_ERROR_BPLUS_NOMATCH) {
-        NTStatus = 0xC000000FL;        /* No such file */
+        NTStatus = 0xC0000034L;        /* Name not found */
     }
     else if (code == CM_ERROR_NOSUCHPATH) {
         NTStatus = 0xC000003AL;        /* Object path not found */
@@ -2874,6 +3072,9 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     else if (code == CM_ERROR_BADFDOP) {
         NTStatus = 0xC0000022L;        /* Access denied */
     }
+    else if (code == CM_ERROR_UNKNOWN) {
+        NTStatus = 0xC0000022L;        /* Access denied */
+    }
     else if (code == CM_ERROR_EXISTS) {
         NTStatus = 0xC0000035L;        /* Object name collision */
     }
@@ -2898,7 +3099,7 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
 #endif /* COMMENT */
     }
     else if (code == CM_ERROR_BADSHARENAME) {
-        NTStatus = 0xC00000CCL;        /* Bad network name */
+        NTStatus = 0xC00000BEL;        /* Bad network path (server valid, share bad) */
     }
     else if (code == CM_ERROR_NOIPC) {
 #ifdef COMMENT
@@ -2907,7 +3108,8 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
         NTStatus = 0xC000013DL; /* Remote Resources */
 #endif
     }
-    else if (code == CM_ERROR_CLOCKSKEW) {
+    else if (code == CM_ERROR_CLOCKSKEW ||
+             code == RXKADNOAUTH) {
         NTStatus = 0xC0000133L;        /* Time difference at DC */
     }
     else if (code == CM_ERROR_BADTID) {
@@ -2929,7 +3131,7 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
         NTStatus = 0xC0000033L;        /* Object name invalid */
     }
     else if (code == CM_ERROR_WOULDBLOCK) {
-        NTStatus = 0xC0000055L;        /* Lock not granted */
+        NTStatus = 0xC00000D8L;        /* Can't wait */
     }
     else if (code == CM_ERROR_SHARING_VIOLATION) {
         NTStatus = 0xC0000043L; /* Sharing violation */
@@ -2966,10 +3168,14 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
         NTStatus = 0xC0000257L; /* Path Not Covered */
     } 
     else if (code == CM_ERROR_ALLBUSY) {
+#ifdef COMMENT
         NTStatus = 0xC000022DL; /* Retry */
+#else
+        NTStatus = 0xC00000B5L; /* I/O Timeout */
+#endif
     } 
     else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
-        NTStatus = 0xC00000BEL; /* Bad Network Path */
+        NTStatus = 0xC000003AL; /* Path not found */
     } 
     else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
        NTStatus = 0xC0000322L; /* No Kerberos key */
@@ -2985,7 +3191,14 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     }
     else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
         NTStatus = 0xC0000055L; /* Lock Not Granted */
-    } else {
+    }
+    else if (code == ENOMEM) {
+        NTStatus = 0xC0000017L; /* Out of Memory */
+    }
+    else if (code == CM_ERROR_RPC_MOREDATA) {
+       NTStatus = 0x80000005L; /* Buffer overflow */
+    }
+    else  {
         NTStatus = 0xC0982001L;        /* SMB non-specific error */
     }
 
@@ -2993,6 +3206,184 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus);
 }       
 
+/* 
+ * NTSTATUS <-> Win32 Error Translation 
+ * http://support.microsoft.com/kb/113996 
+ */
+void smb_MapWin32Error(long code, unsigned long *Win32Ep)
+{
+    unsigned long Win32E;
+
+    /* map CM_ERROR_* errors to Win32 32-bit error codes */
+    if (code == 0) {
+        Win32E = 0;
+    } 
+    else if (code == CM_ERROR_NOSUCHCELL) {
+        Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+    }
+    else if (code == CM_ERROR_NOSUCHVOLUME) {
+        Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+    }
+    else if (code == CM_ERROR_TIMEDOUT) {
+#ifdef COMMENT
+        Win32E = ERROR_SHARING_PAUSED; /* Sharing Paused */
+#else
+        Win32E = ERROR_UNEXP_NET_ERR;   /* Timeout */
+#endif
+    }
+    else if (code == CM_ERROR_RETRY) {
+        Win32E = ERROR_RETRY;          /* Retry */
+    }
+    else if (code == CM_ERROR_NOACCESS) {
+        Win32E = ERROR_ACCESS_DENIED;  /* Access denied */
+    }
+    else if (code == CM_ERROR_READONLY) {
+        Win32E = ERROR_WRITE_PROTECT;  /* Write protected */
+    }
+    else if (code == CM_ERROR_NOSUCHFILE ||
+             code == CM_ERROR_BPLUS_NOMATCH) {
+        Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
+    }
+    else if (code == CM_ERROR_NOSUCHPATH) {
+        Win32E = ERROR_PATH_NOT_FOUND; /* Object path not found */
+    }          
+    else if (code == CM_ERROR_TOOBIG) {
+        Win32E = ERROR_BAD_EXE_FORMAT; /* Invalid image format */
+    }
+    else if (code == CM_ERROR_INVAL) {
+        Win32E = ERROR_INVALID_PARAMETER;/* Invalid parameter */
+    }
+    else if (code == CM_ERROR_BADFD) {
+        Win32E = ERROR_INVALID_HANDLE; /* Invalid handle */
+    }
+    else if (code == CM_ERROR_BADFDOP) {
+        Win32E = ERROR_ACCESS_DENIED;  /* Access denied */
+    }
+    else if (code == CM_ERROR_UNKNOWN) {
+        Win32E = ERROR_ACCESS_DENIED;  /* Access denied */
+    }
+    else if (code == CM_ERROR_EXISTS) {
+        Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
+    }
+    else if (code == CM_ERROR_NOTEMPTY) {
+        Win32E = ERROR_DIR_NOT_EMPTY;  /* Directory not empty */
+    }  
+    else if (code == CM_ERROR_CROSSDEVLINK) {
+        Win32E = ERROR_NOT_SAME_DEVICE;        /* Not same device */
+    }
+    else if (code == CM_ERROR_NOTDIR) {
+        Win32E = ERROR_DIRECTORY;      /* Not a directory */
+    }
+    else if (code == CM_ERROR_ISDIR) {
+        Win32E = ERROR_ACCESS_DENIED;  /* File is a directory */
+    }
+    else if (code == CM_ERROR_BADOP) {
+        Win32E = ERROR_NOT_SUPPORTED;   /* Not supported */
+    }
+    else if (code == CM_ERROR_BADSHARENAME) {
+        Win32E = ERROR_BAD_NETPATH;    /* Bad network path (server valid, share bad) */
+    }
+    else if (code == CM_ERROR_NOIPC) {
+#ifdef COMMENT
+        Win32E = ERROR_ACCESS_DENIED;  /* Access Denied */
+#else   
+        Win32E = ERROR_REM_NOT_LIST;    /* Remote Resources */
+#endif
+    }
+    else if (code == CM_ERROR_CLOCKSKEW ||
+             code == RXKADNOAUTH) {
+        Win32E = ERROR_TIME_SKEW;      /* Time difference at DC */
+    }
+    else if (code == CM_ERROR_BADTID) {
+        Win32E = ERROR_FILE_NOT_FOUND; /* SMB bad TID */
+    }
+    else if (code == CM_ERROR_USESTD) {
+        Win32E = ERROR_ACCESS_DENIED;  /* SMB use standard */
+    }
+    else if (code == CM_ERROR_QUOTA) {
+        Win32E = ERROR_NOT_ENOUGH_QUOTA;/* Quota exceeded */
+    }
+    else if (code == CM_ERROR_SPACE) {
+        Win32E = ERROR_DISK_FULL;      /* Disk full */
+    }
+    else if (code == CM_ERROR_ATSYS) {
+        Win32E = ERROR_INVALID_NAME;   /* Object name invalid */
+    }
+    else if (code == CM_ERROR_BADNTFILENAME) {
+        Win32E = ERROR_INVALID_NAME;   /* Object name invalid */
+    }
+    else if (code == CM_ERROR_WOULDBLOCK) {
+        Win32E = WAIT_TIMEOUT;         /* Can't wait */
+    }
+    else if (code == CM_ERROR_SHARING_VIOLATION) {
+        Win32E = ERROR_SHARING_VIOLATION; /* Sharing violation */
+    }
+    else if (code == CM_ERROR_LOCK_CONFLICT) {
+        Win32E = ERROR_LOCK_VIOLATION;   /* Lock conflict */
+    }
+    else if (code == CM_ERROR_PARTIALWRITE) {
+        Win32E = ERROR_DISK_FULL;      /* Disk full */
+    }
+    else if (code == CM_ERROR_BUFFERTOOSMALL) {
+        Win32E = ERROR_INSUFFICIENT_BUFFER;    /* Buffer too small */
+    }
+    else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+        Win32E = ERROR_ALREADY_EXISTS; /* Object name collision */
+    }   
+    else if (code == CM_ERROR_BADPASSWORD) {
+        Win32E = ERROR_LOGON_FAILURE;   /* unknown username or bad password */
+    }
+    else if (code == CM_ERROR_BADLOGONTYPE) {
+        Win32E = ERROR_INVALID_LOGON_TYPE; /* logon type not granted */
+    }
+    else if (code == CM_ERROR_GSSCONTINUE) {
+        Win32E = ERROR_MORE_DATA;       /* more processing required */
+    }
+    else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
+#ifdef COMMENT
+        Win32E = ERROR_CANT_RESOLVE_FILENAME; /* reparse point not resolved */
+#else
+        Win32E = ERROR_ACCESS_DENIED;   /* Access Denied */
+#endif
+    }
+    else if (code == CM_ERROR_PATH_NOT_COVERED) {
+        Win32E = ERROR_HOST_UNREACHABLE; /* Path Not Covered */
+    } 
+    else if (code == CM_ERROR_ALLBUSY) {
+        Win32E = ERROR_RETRY;           /* Retry */
+    } 
+    else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
+        Win32E = ERROR_HOST_UNREACHABLE; /* Path not found */
+    } 
+    else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
+       Win32E = SEC_E_NO_KERB_KEY;     /* No Kerberos key */
+    } 
+    else if (code == CM_ERROR_BAD_LEVEL) {
+       Win32E = ERROR_INVALID_LEVEL;   /* Invalid Level */
+    } 
+    else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
+       Win32E = ERROR_NOT_LOCKED;      /* Range Not Locked */
+    } 
+    else if (code == CM_ERROR_NOSUCHDEVICE) {
+        Win32E = ERROR_FILE_NOT_FOUND;  /* No Such Device */
+    }
+    else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
+        Win32E = ERROR_LOCK_VIOLATION;  /* Lock Not Granted */
+    }
+    else if (code == ENOMEM) {
+        Win32E = ERROR_NOT_ENOUGH_MEMORY; /* Out of Memory */
+    }
+    else if (code == CM_ERROR_RPC_MOREDATA) {
+       Win32E = ERROR_MORE_DATA;       /* Buffer overflow */
+    }
+    else  {
+        Win32E = ERROR_GEN_FAILURE;    /* SMB non-specific error */
+    }
+
+    *Win32Ep = Win32E;
+    osi_Log2(smb_logp, "SMB SEND code %lX as Win32 %lX", code, Win32E);
+}       
+
 void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
                       unsigned char *classp)
 {
@@ -3240,16 +3631,25 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
              fd, offset.HighPart, offset.LowPart, count);
 
     fidp = smb_FindFID(vcp, fd, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveCoreReadRaw Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
         goto send1;
+    }
+    lock_ObtainMutex(&fidp->mx);
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_BADFD;
+    }
 
-    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+    if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_CloseFID(vcp, fidp, NULL, 0);
         code = CM_ERROR_NOSUCHFILE;
         goto send1a;
     }
 
-
     pid = smbp->pid;
     {
         LARGE_INTEGER LOffset, LLength;
@@ -3267,6 +3667,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         lock_ReleaseWrite(&fidp->scp->rw);
     }    
     if (code) {
+        lock_ReleaseMutex(&fidp->mx);
         goto send1a;
     }
 
@@ -3277,13 +3678,13 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         smb_RawBufs = *(char **)smb_RawBufs;
     }
     lock_ReleaseMutex(&smb_RawBufLock);
-    if (!rawBuf)
+    if (!rawBuf) {
+        lock_ReleaseMutex(&fidp->mx);
         goto send1a;
+    }
 
-    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL)
     {
-       lock_ReleaseMutex(&fidp->mx);
         rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
         if (rawBuf) {
             /* Give back raw buffer */
@@ -3315,7 +3716,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
 
   send1:
     ncbp = outp->ncbp;
-    memset((char *)ncbp, 0, sizeof(NCB));
+    memset(ncbp, 0, sizeof(NCB));
 
     ncbp->ncb_length = (unsigned short) finalCount;
     ncbp->ncb_lsn = (unsigned char) vcp->lsn;
@@ -3497,7 +3898,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         smb_SetSMBParmLong(outp, 9, caps);
         time(&unixTime);
-        smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+        cm_SearchTimeFromUnixTime(&dosTime, unixTime);
         smb_SetSMBParmLong(outp, 11, LOWORD(dosTime));/* server time */
         smb_SetSMBParmLong(outp, 13, HIWORD(dosTime));/* server date */
 
@@ -3513,7 +3914,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             /* and the faux domain name */
             cm_ClientStringToUtf8(smb_ServerDomainName, -1,
                                   datap + MSV1_0_CHALLENGE_LENGTH,
-                                  sizeof(outp->data)/sizeof(char) - (datap - outp->data));
+                                  (int)(sizeof(outp->data)/sizeof(char) - (datap - outp->data)));
         } else if ( smb_authType == SMB_AUTH_EXTENDED ) {
             void * secBlob;
             int secBlobLength;
@@ -3557,7 +3958,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         smb_SetSMBParm(outp, 6, 1);    /* next 2: session key */
         smb_SetSMBParm(outp, 7, 1);
         time(&unixTime);
-        smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+        cm_SearchTimeFromUnixTime(&dosTime, unixTime);
         smb_SetSMBParm(outp, 8, LOWORD(dosTime));      /* server time */
         smb_SetSMBParm(outp, 9, HIWORD(dosTime));      /* server date */
 
@@ -3577,7 +3978,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             /* and the faux domain name */
             cm_ClientStringToUtf8(smb_ServerDomainName, -1,
                                   datap + MSV1_0_CHALLENGE_LENGTH,
-                                  sizeof(outp->data)/sizeof(char) - (datap - outp->data));
+                                  (int)(sizeof(outp->data)/sizeof(char) - (datap - outp->data)));
         } else {
             smb_SetSMBParm(outp, 11, 0); /* encryption key length */
             smb_SetSMBParm(outp, 12, 0); /* resvd */
@@ -3594,7 +3995,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 void smb_CheckVCs(void)
 {
     smb_vc_t * vcp, *nextp;
-    smb_packet_t * outp = GetPacket();
+    smb_packet_t * outp = smb_GetPacket();
     smb_t *smbp;
             
     lock_ObtainWrite(&smb_rctLock);
@@ -3604,14 +4005,24 @@ void smb_CheckVCs(void)
            osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp", 
                       __FILE__, __LINE__);
 
+        /* on the first pass hold 'vcp' which was not held as 'nextp' */
+        if (vcp != nextp)
+            smb_HoldVCNoLock(vcp);
+
+        /* 
+         * obtain a reference to 'nextp' now because we drop the
+         * smb_rctLock later and the list contents could change 
+         * or 'vcp' could be destroyed when released.
+         */
        nextp = vcp->nextp;
+       if (nextp)
+           smb_HoldVCNoLock(nextp);
 
-       if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
+       if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+            smb_ReleaseVCNoLock(vcp);
            continue;
+        }
 
-       smb_HoldVCNoLock(vcp);
-       if (nextp)
-           smb_HoldVCNoLock(nextp);
        smb_FormatResponsePacket(vcp, NULL, outp);
         smbp = (smb_t *)outp;
        outp->inCom = smbp->com = 0x2b /* Echo */;
@@ -3630,8 +4041,6 @@ void smb_CheckVCs(void)
 
        lock_ObtainWrite(&smb_rctLock);
        smb_ReleaseVCNoLock(vcp);
-       if (nextp)
-           smb_ReleaseVCNoLock(nextp);
     }
     lock_ReleaseWrite(&smb_rctLock);
     smb_FreePacket(outp);
@@ -3664,9 +4073,6 @@ 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();
@@ -3797,7 +4203,7 @@ void smb_WaitingLocksDaemon()
                 scp = wlRequest->scp;
                osi_Log2(smb_logp,"smb_WaitingLocksDaemon wlRequest 0x%p scp 0x%p", wlRequest, scp);
 
-                cm_InitReq(&req);
+                smb_InitReq(&req);
 
                 lock_ObtainWrite(&scp->rw);
 
@@ -3806,7 +4212,7 @@ void smb_WaitingLocksDaemon()
                 
                     if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
                         cm_Unlock(scp, wlRequest->lockType, wl->LOffset, 
-                                  wl->LLength, wl->key, NULL, &req);
+                                  wl->LLength, wl->key, 0, NULL, &req);
 
                     osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
 
@@ -3830,7 +4236,7 @@ void smb_WaitingLocksDaemon()
             vcp = wlRequest->vcp;
             inp = wlRequest->inp;
             outp = wlRequest->outp;
-            ncbp = GetNCB();
+            ncbp = smb_GetNCB();
             ncbp->ncb_length = inp->ncb_length;
             inp->spacep = cm_GetSpace();
 
@@ -3854,7 +4260,7 @@ void smb_WaitingLocksDaemon()
             smb_FreePacket(outp);
             smb_ReleaseVC(vcp);
             cm_ReleaseSCache(wlRequest->scp);
-            FreeNCB(ncbp);
+            smb_FreeNCB(ncbp);
             free(wlRequest);
         } while (nwlRequest && smbShutdownFlag == 0);
         thrd_Sleep(1000);
@@ -3894,6 +4300,8 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         char *tbp;
         tbp = smb_GetSMBData(inp, NULL);
         pathp = smb_ParseASCIIBlock(inp, tbp, &tbp, SMB_STRF_ANSIPATH);
+        if (!pathp)
+            return CM_ERROR_BADSMB;
     }
     tp = cm_ClientStrRChr(pathp, '\\');
     if (!tp)
@@ -3906,10 +4314,11 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
 
     tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
     uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+    if (!uidp)
+        return CM_ERROR_BADSMB;
     userp = smb_GetUserFromUID(uidp);
     shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
-    if (uidp)
-        smb_ReleaseUID(uidp);
+    smb_ReleaseUID(uidp);
     if (!shareFound) {
         smb_ReleaseTID(tidp, FALSE);
         return CM_ERROR_BADSHARENAME;
@@ -4064,7 +4473,8 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
     tp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, tp, &tp,
                                 SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
-    osi_assertx(pathp != NULL, "null path");
+    if (!pathp)
+        return CM_ERROR_BADSMB;
     statBlockp = smb_ParseVblBlock(tp, &tp, &statLen);
     osi_assertx(statBlockp != NULL, "null statBlock");
     if (statLen == 0) {
@@ -4122,7 +4532,7 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 }       
 
 static long 
-smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
+smb_ApplyDirListPatches(cm_scache_t * dscp, smb_dirListPatch_t **dirPatchespp,
                         clientchar_t * tidPathp, clientchar_t * relPathp,
                         cm_user_t *userp, cm_req_t *reqp)
 {
@@ -4135,6 +4545,68 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
     smb_dirListPatch_t *patchp;
     smb_dirListPatch_t *npatchp;
     clientchar_t path[AFSPATHMAX];
+    afs_uint32 rights;
+    afs_int32 mustFake = 0;
+
+    code = cm_FindACLCache(dscp, userp, &rights);
+    if (code == -1) {
+        lock_ObtainWrite(&dscp->rw);
+        code = cm_SyncOp(dscp, NULL, userp, reqp, PRSFS_READ,
+                          CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+        lock_ReleaseWrite(&dscp->rw);
+        if (code == CM_ERROR_NOACCESS) {
+            mustFake = 1;
+            code = 0;
+        }
+    }
+    if (code)
+        goto cleanup;
+
+    if (!mustFake) {    /* Bulk Stat */
+        afs_uint32 count;
+        cm_bulkStat_t *bsp = malloc(sizeof(cm_bulkStat_t));
+
+        memset(bsp, 0, sizeof(cm_bulkStat_t));
+
+        for (patchp = *dirPatchespp, count=0; 
+             patchp; 
+             patchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
+            cm_scache_t *tscp = cm_FindSCache(&patchp->fid);
+            int i;
+
+            if (tscp) {
+                if (lock_TryWrite(&tscp->rw)) {
+                    /* we have an entry that we can look at */
+                    if (!(tscp->flags & CM_SCACHEFLAG_EACCESS) && cm_HaveCallback(tscp)) {
+                        /* we have a callback on it.  Don't bother
+                        * fetching this stat entry, since we're happy
+                        * with the info we have.
+                        */
+                        lock_ReleaseWrite(&tscp->rw);
+                        cm_ReleaseSCache(tscp);
+                        continue;
+                    }
+                    lock_ReleaseWrite(&tscp->rw);
+                } /* got lock */
+                cm_ReleaseSCache(tscp);
+            }  /* found entry */
+
+            i = bsp->counter++;
+            bsp->fids[i].Volume = patchp->fid.volume;
+            bsp->fids[i].Vnode = patchp->fid.vnode;
+            bsp->fids[i].Unique = patchp->fid.unique;
+
+            if (bsp->counter == AFSCBMAX) {
+                code = cm_TryBulkStatRPC(dscp, bsp, userp, reqp);
+                memset(bsp, 0, sizeof(cm_bulkStat_t));
+            }
+        }
+
+        if (bsp->counter > 0)
+            code = cm_TryBulkStatRPC(dscp, bsp, userp, reqp);
+
+        free(bsp);
+    }
 
     for (patchp = *dirPatchespp; patchp; patchp =
          (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
@@ -4155,42 +4627,79 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
             continue;
         }
         lock_ObtainWrite(&scp->rw);
-        code = cm_SyncOp(scp, NULL, userp, reqp, 0,
-                          CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-        if (code) {    
+        if (mustFake || (scp->flags & CM_SCACHEFLAG_EACCESS) || !cm_HaveCallback(scp)) {
             lock_ReleaseWrite(&scp->rw);
-            cm_ReleaseSCache(scp);
-            if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
-                *dptr++ = SMB_ATTR_HIDDEN;
-            continue;
-        }
 
-       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+            /* set the attribute */
+            switch (scp->fileType) {
+            case CM_SCACHETYPE_DIRECTORY:
+            case CM_SCACHETYPE_MOUNTPOINT:
+            case CM_SCACHETYPE_INVALID:
+                attr = SMB_ATTR_DIRECTORY;
+                break;
+            case CM_SCACHETYPE_SYMLINK:
+                if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+                    attr = SMB_ATTR_DIRECTORY;
+                else
+                    attr = SMB_ATTR_NORMAL;
+                break;
+            default:
+                /* if we get here we either have a normal file
+                * or we have a file for which we have never 
+                * received status info.  In this case, we can
+                * check the even/odd value of the entry's vnode.
+                * odd means it is to be treated as a directory
+                * and even means it is to be treated as a file.
+                */
+                if (mustFake && (scp->fid.vnode & 0x1))
+                    attr = SMB_ATTR_DIRECTORY;
+                else
+                    attr = SMB_ATTR_NORMAL;
+            }
+            *dptr++ = attr;
+
+            /* 1969-12-31 23:59:58 +00*/
+            dosTime = 0xEBBFBF7D;
 
-        lock_ConvertWToR(&scp->rw);
-        attr = smb_Attributes(scp);
-        /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
-        if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
-            attr |= SMB_ATTR_HIDDEN;
-        *dptr++ = attr;
+            /* copy out time */
+            shortTemp = (unsigned short) (dosTime & 0xffff);
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+
+            /* and copy out date */
+            shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+                
+            /* copy out file length */
+            *((u_long *)dptr) = 0;
+            dptr += 4;
+        } else {
+            lock_ConvertWToR(&scp->rw);
+            attr = smb_Attributes(scp);
+            /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
+            if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
+                attr |= SMB_ATTR_HIDDEN;
+            *dptr++ = attr;
 
-        /* get dos time */
-        smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+            /* get dos time */
+            cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
                 
-        /* copy out time */
-        shortTemp = (unsigned short) (dosTime & 0xffff);
-        *((u_short *)dptr) = shortTemp;
-        dptr += 2;
-
-        /* and copy out date */
-        shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
-        *((u_short *)dptr) = shortTemp;
-        dptr += 2;
+            /* copy out time */
+            shortTemp = (unsigned short) (dosTime & 0xffff);
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
+
+            /* and copy out date */
+            shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
                 
-        /* copy out file length */
-        *((u_long *)dptr) = scp->length.LowPart;
-        dptr += 4;
-        lock_ReleaseRead(&scp->rw);
+            /* copy out file length */
+            *((u_long *)dptr) = scp->length.LowPart;
+            dptr += 4;
+            lock_ReleaseRead(&scp->rw);
+        }
         cm_ReleaseSCache(scp);
     }
         
@@ -4203,6 +4712,7 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
     /* and mark the list as empty */
     *dirPatchespp = NULL;
 
+  cleanup:
     return code;
 }
 
@@ -4250,7 +4760,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     cm_fid_t fid;
     int fileType;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     maxCount = smb_GetSMBParm(inp, 0);
 
@@ -4261,12 +4771,12 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     tp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, tp, &tp,
                                 SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
-    inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
+    if (!pathp)
+        return CM_ERROR_BADSMB;
 
-    /* bail out if request looks bad */
-    if (!tp || !pathp) {
+    inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
+    if (!tp)
         return CM_ERROR_BADSMB;
-    }
 
     /* We can handle long names */
     if (vcp->flags & SMB_VCFLAG_USENT)
@@ -4298,7 +4808,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         memcpy(dsp->mask, mask, 12);
 
         /* track if this is likely to match a lot of entries */
-        if (smb_IsStarMask(mask)) 
+        if (smb_Is8Dot3StarMask(mask)) 
             starPattern = 1;
         else 
             starPattern = 0;
@@ -4371,7 +4881,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                 if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
-                    return CM_ERROR_BADSHARENAME;
+                    return CM_ERROR_NOSUCHPATH;
             }
 #endif /* DFS_SUPPORT */
 
@@ -4385,12 +4895,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
              */
             cm_HoldSCache(scp);
             lock_ObtainWrite(&scp->rw);
-            if ((scp->flags & CM_SCACHEFLAG_BULKSTATTING) == 0
-                 && LargeIntegerGreaterOrEqualToZero(scp->bulkStatProgress)) {
-                scp->flags |= CM_SCACHEFLAG_BULKSTATTING;
-                dsp->flags |= SMB_DIRSEARCH_BULKST;
-               dsp->scp->bulkStatProgress = hzero;
-            }
+            dsp->flags |= SMB_DIRSEARCH_BULKST;
             lock_ReleaseWrite(&scp->rw);
         }
     }
@@ -4435,7 +4940,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     code = 0;
     returnedNames = 0;
     while (1) {
-        clientchar_t *actualName;
+        clientchar_t *actualName = NULL;
+        int           free_actualName = 0;
         clientchar_t shortName[13];
         clientchar_t *shortNameEnd;
 
@@ -4487,31 +4993,16 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                 bufferp = NULL;
             }  
             lock_ReleaseWrite(&scp->rw);
-            code = buf_Get(scp, &thyper, &bufferp);
+            code = buf_Get(scp, &thyper, &req, &bufferp);
             lock_ObtainMutex(&dsp->mx);
 
             /* now, if we're doing a star match, do bulk fetching of all of 
              * the status info for files in the dir.
              */
-            if (starPattern) {
-                smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
-                lock_ObtainWrite(&scp->rw);
-                if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
-                     LargeIntegerGreaterThanOrEqualTo(thyper, 
-                                                      scp->bulkStatProgress)) {
-                    /* Don't bulk stat if risking timeout */
-                    int now = GetTickCount();
-                    if (now - req.startTime > RDRtimeout * 1000) {
-                        scp->bulkStatProgress = thyper;
-                        scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
-                        dsp->flags &= ~SMB_DIRSEARCH_BULKST;
-                       dsp->scp->bulkStatProgress = hzero;
-                    } else
-                        code = cm_TryBulkStat(scp, &thyper, userp, &req);
-                }
-            } else {
-                lock_ObtainWrite(&scp->rw);
-            }
+            if (starPattern)
+                smb_ApplyDirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
+
+            lock_ObtainWrite(&scp->rw);
             lock_ReleaseMutex(&dsp->mx);
             if (code) {
                 osi_Log2(smb_logp, "SMB search dir buf_Get scp %x failed %d", scp, code);
@@ -4595,9 +5086,20 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         /* Compute 8.3 name if necessary */
         actualName = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
         if (dep->fid.vnode != 0 && !cm_Is8Dot3(actualName)) {
-            free(actualName);
+            if (actualName)
+                free(actualName);
             cm_Gen8Dot3NameInt(dep->name, &dep->fid, shortName, &shortNameEnd);
             actualName = shortName;
+            free_actualName = 0;
+        } else {
+            free_actualName = 1;
+        }
+
+        if (actualName == NULL) {
+            /* Couldn't convert the name for some reason */
+            osi_Log1(smb_logp, "SMB search dir skipping entry :[%s]",
+                     osi_LogSaveString(smb_logp, dep->name));
+            goto nextEntry;
         }
 
         osi_Log3(smb_logp, "SMB search dir vn %d name %s (%S)",
@@ -4698,6 +5200,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         }      /* if we're including this name */
 
       nextEntry:
+        if (free_actualName && actualName) {
+            free(actualName);
+            actualName = NULL;
+        }
+
         /* and adjust curOffset to be where the new cookie is */
         thyper.HighPart = 0;
         thyper.LowPart = CM_DIR_CHUNKSIZE * numDirChunks;
@@ -4714,7 +5221,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     /* 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.
      */
-    smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
+    smb_ApplyDirListPatches(scp, &dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
 
     /* special return code for unsuccessful search */
     if (code == 0 && dataLength < 21 && returnedNames == 0)
@@ -4772,12 +5279,12 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     cm_req_t req;
     char * pdata;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     pdata = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, pdata, NULL, SMB_STRF_ANSIPATH);
     if (!pathp)
-        return CM_ERROR_BADFD;
+        return CM_ERROR_BADSMB;
     osi_Log1(smb_logp, "SMB receive check path %S",
              osi_LogSaveClientString(smb_logp, pathp));
         
@@ -4809,7 +5316,7 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -4856,7 +5363,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     char * datap;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     /* decode basic attributes we're passed */
     attribute = smb_GetSMBParm(inp, 0);
@@ -4897,7 +5404,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -4931,12 +5438,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 & SMB_ATTR_READONLY) != 0) {
+    if ((newScp->unixModeBits & 0200) && (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 & SMB_ATTR_READONLY) == 0) {
+    else if ((newScp->unixModeBits & 0200) == 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;
@@ -4972,7 +5479,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     char * datap;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     datap = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
@@ -5030,7 +5537,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
                 if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
-                    return CM_ERROR_BADSHARENAME;
+                    return CM_ERROR_NOSUCHPATH;
             } else
 #endif /* DFS_SUPPORT */
             if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
@@ -5067,7 +5574,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -5084,21 +5591,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 
     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_INVALID)
-        attrs = SMB_ATTR_DIRECTORY;
-    else
-        attrs = 0;
-    if ((newScp->unixModeBits & 0222) == 0 || (newScp->flags & CM_SCACHEFLAG_RO))
-        attrs |= SMB_ATTR_READONLY;    /* turn on read-only flag */
-#else
     attrs = smb_Attributes(newScp);
-#endif
 
     smb_SetSMBParm(outp, 0, attrs);
         
@@ -5158,10 +5651,12 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     char * datap;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     datap = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
+    if (!pathp)
+        return CM_ERROR_BADSMB;
 
     osi_Log1(smb_logp, "SMB receive open file [%S]", osi_LogSaveClientString(smb_logp, pathp));
 
@@ -5179,7 +5674,24 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     attribute = smb_GetSMBParm(inp, 1);
 
     spacep = inp->spacep;
+    /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+
+    if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+        clientchar_t * hexp;
+
+        hexp = cm_GetRawCharsAlloc(pathp, -1);
+        osi_Log1(smb_logp, "CoreOpen rejecting invalid name. [%S]",
+                 osi_LogSaveClientString(smb_logp, hexp));
+        if (hexp)
+            free(hexp);
+#else
+        osi_Log0(smb_logp, "CoreOpen rejecting invalid name");
+#endif
+        return CM_ERROR_BADNTFILENAME;
+    }
+
     if (lastNamep && cm_ClientStrCmp(lastNamep, _C(SMB_IOCTL_FILENAME)) == 0) {
         /* special case magic file name for receiving IOCTL requests
          * (since IOCTL calls themselves aren't getting through).
@@ -5224,7 +5736,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -5248,17 +5760,6 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assertx(fidp, "null smb_fid_t");
 
-    /* save a pointer to the vnode */
-    fidp->scp = scp;
-    osi_Log2(smb_logp,"smb_ReceiveCoreOpen fidp 0x%p scp 0x%p", fidp, scp);
-    lock_ObtainWrite(&scp->rw);
-    scp->flags |= CM_SCACHEFLAG_SMB_FID;
-    lock_ReleaseWrite(&scp->rw);
-
-    /* and the user */
-    cm_HoldUser(userp);
-    fidp->userp = userp;
-
     lock_ObtainMutex(&fidp->mx);
     if ((share & 0xf) == 0)
         fidp->flags |= SMB_FID_OPENREAD_LISTDIR;
@@ -5266,9 +5767,17 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         fidp->flags |= SMB_FID_OPENWRITE;
     else 
         fidp->flags |= (SMB_FID_OPENREAD_LISTDIR | SMB_FID_OPENWRITE);
-    lock_ReleaseMutex(&fidp->mx);
 
-    lock_ObtainRead(&scp->rw);
+    /* save the  user */
+    cm_HoldUser(userp);
+    fidp->userp = userp;
+
+    /* and a pointer to the vnode */
+    fidp->scp = scp;
+    osi_Log2(smb_logp,"smb_ReceiveCoreOpen fidp 0x%p scp 0x%p", fidp, scp);
+    lock_ObtainWrite(&scp->rw);
+    scp->flags |= CM_SCACHEFLAG_SMB_FID;
     smb_SetSMBParm(outp, 0, fidp->fid);
     smb_SetSMBParm(outp, 1, smb_Attributes(scp));
     smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
@@ -5279,6 +5788,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* pass the open mode back; XXXX add access checks */
     smb_SetSMBParm(outp, 6, (share & 0xf));
     smb_SetSMBDataLength(outp, 0);
+       lock_ReleaseMutex(&fidp->mx);
     lock_ReleaseRead(&scp->rw);
         
     /* notify open */
@@ -5316,7 +5826,13 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
     if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
         caseFold |= CM_FLAG_8DOT3;
 
-    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+    if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+        /* Can't convert name */
+        osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string.",
+                 osi_LogSaveString(smb_logp, dep->name));
+        return 0;
+    }
+
     match = cm_MatchMask(matchName, rockp->maskp, caseFold);
     if (!match &&
         (rockp->flags & SMB_MASKFLAG_TILDE) &&
@@ -5361,12 +5877,15 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     clientchar_t *tidPathp;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
+    memset(&rock, 0, sizeof(rock));
 
     attribute = smb_GetSMBParm(inp, 0);
         
     tp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+    if (!pathp)
+        return CM_ERROR_BADSMB;
 
     osi_Log1(smb_logp, "SMB receive unlink %S",
              osi_LogSaveClientString(smb_logp, pathp));
@@ -5398,7 +5917,7 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -5410,6 +5929,10 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     rock.any = 0;
     rock.maskp = cm_ClientStringToNormStringAlloc(smb_FindMask(pathp), -1, NULL);
+    if (!rock.maskp) {
+        code = CM_ERROR_NOSUCHFILE;
+        goto done;
+    }
     rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
 
     thyper.LowPart = 0;
@@ -5450,6 +5973,8 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             osi_Log1(smb_logp, "Unlinking %s",
                      osi_LogSaveString(smb_logp, entry->name));
 
+            /* We assume this works because entry->name was
+               successfully converted in smb_UnlinkProc() once. */
             cm_FsStringToNormString(entry->name, -1,
                                     normalizedName, lengthof(normalizedName));
 
@@ -5464,10 +5989,14 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     cm_DirEntryListFree(&rock.matches);
 
+  done:
+    if (userp)
     cm_ReleaseUser(userp);
         
+    if (dscp)
     cm_ReleaseSCache(dscp);
 
+    if (rock.maskp)
     free(rock.maskp);
 
     if (code == 0 && !rock.any)
@@ -5499,7 +6028,13 @@ int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
 
     rockp = (smb_renameRock_t *) vrockp;
 
-    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+    if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+        /* Can't convert string */
+        osi_Log1(smb_logp, "Skpping entry [%s]. Can't normalize FS string",
+                 osi_LogSaveString(smb_logp, dep->name));
+        return 0;
+    }
+
     caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
     if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
         caseFold |= CM_FLAG_8DOT3;
@@ -5552,7 +6087,9 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
         return CM_ERROR_NOSUCHPATH;
     }
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
+    memset(&rock, 0, sizeof(rock));
+
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
 
@@ -5572,7 +6109,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -5595,7 +6132,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -5618,19 +6155,6 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
 
     /* TODO: The old name could be a wildcard.  The new name must not be */
 
-    /* do the vnode call */
-    rock.odscp = oldDscp;
-    rock.ndscp = newDscp;
-    rock.userp = userp;
-    rock.reqp = &req;
-    rock.vcp = vcp;
-    rock.maskp = cm_ClientStringToNormStringAlloc(oldLastNamep, -1, NULL);
-    rock.flags = ((cm_ClientStrChr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
-    rock.newNamep = newLastNamep;
-    rock.fsOldName[0] = '\0';
-    rock.clOldName[0] = '\0';
-    rock.any = 0;
-
     /* Check if the file already exists; if so return error */
     code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp);
     if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_BPLUS_NOMATCH) &&
@@ -5661,17 +6185,25 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
             osi_Log0(smb_logp, "Can't rename.  Target already exists");
             code = CM_ERROR_EXISTS;
         }
+        goto done;
+    }
 
-        if (tmpscp != NULL)
-            cm_ReleaseSCache(tmpscp);
-        cm_ReleaseSCache(newDscp);
-        cm_ReleaseSCache(oldDscp);
-        cm_ReleaseUser(userp);
-
-        free(rock.maskp);
-        rock.maskp = NULL;
-        return code; 
+    /* do the vnode call */
+    rock.odscp = oldDscp;
+    rock.ndscp = newDscp;
+    rock.userp = userp;
+    rock.reqp = &req;
+    rock.vcp = vcp;
+    rock.maskp = cm_ClientStringToNormStringAlloc(oldLastNamep, -1, NULL);
+    if (!rock.maskp) {
+        code = CM_ERROR_NOSUCHFILE;
+        goto done;
     }
+    rock.flags = ((cm_ClientStrChr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+    rock.newNamep = newLastNamep;
+    rock.fsOldName[0] = '\0';
+    rock.clOldName[0] = '\0';
+    rock.any = 0;
 
     /* Now search the directory for the pattern, and do the appropriate rename when found */
     thyper.LowPart = 0;                /* search dir from here */
@@ -5693,6 +6225,8 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
         /* if the call worked, stop doing the search now, since we
          * really only want to rename one file.
          */
+    if (code)
+        osi_Log0(smb_logp, "cm_Rename failure");
        osi_Log1(smb_logp, "cm_Rename returns %ld", code);
     } else if (code == 0) {
         code = CM_ERROR_NOSUCHFILE;
@@ -5722,14 +6256,17 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
         }
     }
 
+  done:
     if (tmpscp != NULL) 
         cm_ReleaseSCache(tmpscp);
-    cm_ReleaseUser(userp);
-    cm_ReleaseSCache(oldDscp);
-    cm_ReleaseSCache(newDscp);
-
-    free(rock.maskp);
-    rock.maskp = NULL;
+    if (userp)
+        cm_ReleaseUser(userp);
+    if (oldDscp)
+        cm_ReleaseSCache(oldDscp);
+    if (newDscp)
+        cm_ReleaseSCache(newDscp);
+    if (rock.maskp)
+        free(rock.maskp);
 
     return code;
 }       
@@ -5760,7 +6297,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t
         return CM_ERROR_NOSUCHPATH;
     }
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
 
@@ -5782,7 +6319,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -5804,7 +6341,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -5901,12 +6438,31 @@ smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     tp = smb_GetSMBData(inp, NULL);
     oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+    if (!oldPathp)
+        return CM_ERROR_BADSMB;
     newPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+    if (!newPathp)
+        return CM_ERROR_BADSMB;
 
     osi_Log2(smb_logp, "smb rename [%S] to [%S]",
              osi_LogSaveClientString(smb_logp, oldPathp),
              osi_LogSaveClientString(smb_logp, newPathp));
 
+    if (!cm_IsValidClientString(newPathp)) {
+#ifdef DEBUG
+        clientchar_t * hexp;
+
+        hexp = cm_GetRawCharsAlloc(newPathp, -1);
+        osi_Log1(smb_logp, "CoreRename rejecting invalid name. [%S]",
+                 osi_LogSaveClientString(smb_logp, hexp));
+        if (hexp)
+            free(hexp);
+#else
+        osi_Log0(smb_logp, "CoreRename rejecting invalid name");
+#endif
+        return CM_ERROR_BADNTFILENAME;
+    }
+
     code = smb_Rename(vcp,inp,oldPathp,newPathp,0);
 
     osi_Log1(smb_logp, "smb rename returns 0x%x", code);
@@ -5934,7 +6490,12 @@ int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper
         
     rockp = (smb_rmdirRock_t *) vrockp;
 
-    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+    if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+        osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+                 osi_LogSaveString(smb_logp, dep->name));
+        return 0;
+    }
+
     if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
         match = (cm_ClientStrCmpI(matchName, rockp->maskp) == 0);
     else
@@ -5970,10 +6531,13 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     clientchar_t *tidPathp;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
+    memset(&rock, 0, sizeof(rock));
 
     tp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+    if (!pathp)
+        return CM_ERROR_BADSMB;
 
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
@@ -6003,7 +6567,7 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -6015,6 +6579,10 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        
     rock.any = 0;
     rock.maskp = cm_ClientStringToNormStringAlloc(lastNamep, -1, NULL);
+    if (!rock.maskp) {
+        code = CM_ERROR_NOSUCHFILE;
+        goto done;
+    }
     rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
 
     thyper.LowPart = 0;
@@ -6039,6 +6607,8 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
             clientchar_t clientName[MAX_PATH];
 
+            /* We assume this will succeed because smb_RmdirProc()
+               successfully converted entry->name once above. */
             cm_FsStringToClientString(entry->name, -1, clientName, lengthof(clientName));
 
             osi_Log1(smb_logp, "Removing directory %s",
@@ -6053,17 +6623,21 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         }
     }
 
+  done:
+    if (rock.matches)
     cm_DirEntryListFree(&rock.matches);
 
+    if (userp)
     cm_ReleaseUser(userp);
         
+    if (dscp)
     cm_ReleaseSCache(dscp);
 
     if (code == 0 && !rock.any)
         code = CM_ERROR_NOSUCHFILE;        
 
+    if (rock.maskp)
     free(rock.maskp);
-    rock.maskp = NULL;
 
     return code;
 }
@@ -6077,7 +6651,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     long code = 0;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     fid = smb_GetSMBParm(inp, 0);
 
@@ -6085,41 +6659,42 @@ 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)
-       return CM_ERROR_BADFD;
-    
-    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
-        smb_CloseFID(vcp, fidp, NULL, 0);
-        smb_ReleaseFID(fidp);
-        return CM_ERROR_NOSUCHFILE;
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveCoreFlush Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
+        return CM_ERROR_BADFD;
     }
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     lock_ObtainMutex(&fidp->mx);
-    if (fidp->flags & SMB_FID_IOCTL) {
-       lock_ReleaseMutex(&fidp->mx);
-       smb_ReleaseFID(fidp);
+    if (!fidp->scp || (fidp->flags & SMB_FID_IOCTL)) {
+        cm_ReleaseUser(userp);
+        lock_ReleaseMutex(&fidp->mx);
+        smb_ReleaseFID(fidp);
         return CM_ERROR_BADFD;
     }
-    lock_ReleaseMutex(&fidp->mx);
-        
-    userp = smb_GetUserFromVCP(vcp, inp);
 
-    lock_ObtainMutex(&fidp->mx);
+    if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+        lock_ReleaseMutex(&fidp->mx);
+        cm_ReleaseUser(userp);
+        smb_CloseFID(vcp, fidp, NULL, 0);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_NOSUCHFILE;
+    }
+
     if ((fidp->flags & SMB_FID_OPENWRITE) && smb_AsyncStore != 2) {
-       cm_scache_t * scp = fidp->scp;
-       cm_HoldSCache(scp);
-       lock_ReleaseMutex(&fidp->mx);
+        cm_scache_t * scp = fidp->scp;
+        cm_HoldSCache(scp);
+        lock_ReleaseMutex(&fidp->mx);
         code = cm_FSync(scp, userp, &req);
-       cm_ReleaseSCache(scp);
+        cm_ReleaseSCache(scp);
     } else {
+        lock_ReleaseMutex(&fidp->mx);
         code = 0;
-       lock_ReleaseMutex(&fidp->mx);
     }
         
-    smb_ReleaseFID(fidp);
-        
     cm_ReleaseUser(userp);
-        
+    smb_ReleaseFID(fidp);                
     return code;
 }
 
@@ -6138,7 +6713,11 @@ int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
 
     vrockp = (struct smb_FullNameRock *)rockp;
 
-    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+    if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+        osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+                 osi_LogSaveString(smb_logp, dep->name));
+        return 0;
+    }
 
     if (!cm_Is8Dot3(matchName)) {
         clientchar_t shortName[13];
@@ -6197,7 +6776,8 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
 
     if (!userp) {
        lock_ObtainMutex(&fidp->mx);
-        if (!fidp->userp && !(fidp->flags & SMB_FID_IOCTL)) {
+        if (!fidp->userp && !(fidp->flags & (SMB_FID_IOCTL|
+                                            SMB_FID_RPC))) {
            lock_ReleaseMutex(&fidp->mx);
             osi_Log0(smb_logp, "  No user specified.  Not closing fid");
            return CM_ERROR_BADFD;
@@ -6208,30 +6788,29 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
        lock_ReleaseMutex(&fidp->mx);
     }
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     lock_ObtainWrite(&smb_rctLock);
     if (fidp->deleteOk) {
-       osi_Log0(smb_logp, "  Fid already closed.");
-       lock_ReleaseWrite(&smb_rctLock);
-       return CM_ERROR_BADFD;
+        osi_Log0(smb_logp, "  Fid already closed.");
+        lock_ReleaseWrite(&smb_rctLock);    
+        return CM_ERROR_BADFD;
     }
     fidp->deleteOk = 1;
     lock_ReleaseWrite(&smb_rctLock);
 
     lock_ObtainMutex(&fidp->mx);
     if (fidp->NTopen_dscp) {
-       dscp = fidp->NTopen_dscp;
-       cm_HoldSCache(dscp);
+        dscp = fidp->NTopen_dscp;   
+        cm_HoldSCache(dscp);
     }
 
-    if (fidp->NTopen_pathp) {
-       pathp = cm_ClientStrDup(fidp->NTopen_pathp);
-    }
+    if (fidp->NTopen_pathp)
+        pathp = cm_ClientStrDup(fidp->NTopen_pathp);
 
     if (fidp->scp) {
-       scp = fidp->scp;
-       cm_HoldSCache(scp);
+        scp = fidp->scp;
+        cm_HoldSCache(scp);
     }
 
     /* Don't jump the gun on an async raw write */
@@ -6246,10 +6825,12 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
         (fidp->flags & (SMB_FID_OPENWRITE | SMB_FID_DELONCLOSE))
          == SMB_FID_OPENWRITE) {
         if (dosTime != 0 && dosTime != -1) {
+            lock_ObtainWrite(&fidp->scp->rw);
             scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
             /* This fixes defect 10958 */
             CompensateForSmbClientLastWriteTimeBugs(&dosTime);
-            smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
+            smb_UnixTimeFromDosUTime(&scp->clientModTime, dosTime);
+            lock_ReleaseWrite(&fidp->scp->rw);
         }
         if (smb_AsyncStore != 2) {
             lock_ReleaseMutex(&fidp->mx);
@@ -6266,10 +6847,10 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
         cm_key_t key;
         long tcode;
 
-       lock_ReleaseMutex(&fidp->mx);
+        lock_ReleaseMutex(&fidp->mx);
 
-       /* CM_UNLOCK_BY_FID doesn't look at the process ID.  We pass
-           in zero. */
+        /* CM_UNLOCK_BY_FID doesn't look at the process ID.  We pass
+              * in zero. */
         key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
         lock_ObtainWrite(&scp->rw);
 
@@ -6370,16 +6951,16 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
     }
 
     if (scp) {
-       lock_ObtainWrite(&scp->rw);
+        lock_ObtainWrite(&scp->rw);
         if (nullcreator && scp->creator == userp)
             scp->creator = NULL;
-       scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
-       lock_ReleaseWrite(&scp->rw);
-       cm_ReleaseSCache(scp);
+        scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
+        lock_ReleaseWrite(&scp->rw);
+        cm_ReleaseSCache(scp);
     }
 
     if (pathp)
-       free(pathp);
+        free(pathp);
 
     return code;
 }
@@ -6401,6 +6982,8 @@ long smb_ReceiveCoreClose(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) {
+        osi_Log2(smb_logp, "smb_ReceiveCoreClose Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
         return CM_ERROR_BADFD;
     }
         
@@ -6447,8 +7030,14 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
         code = CM_ERROR_BADFDOP;
         goto done2;
     }
-    
-    cm_InitReq(&req);
+
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
+        code = CM_ERROR_BADFD;
+        goto done2;
+    }
+       
+    smb_InitReq(&req);
 
     bufferp = NULL;
     offset = *offsetp;
@@ -6517,7 +7106,7 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
             }
             lock_ReleaseWrite(&scp->rw);
 
-            code = buf_Get(scp, &thyper, &bufferp);
+            code = buf_Get(scp, &thyper, &req, &bufferp);
 
             lock_ObtainWrite(&scp->rw);
             if (code) goto done;
@@ -6603,6 +7192,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
     osi_hyper_t writeBackOffset;/* offset of region to write back when I/O is done */
     DWORD filter = 0;
     cm_req_t req;
+    int needSyncOpDone = 0;
 
     osi_Log3(smb_logp, "smb_WriteData fid %d, off 0x%x, size 0x%x",
               fidp->fid, offsetp->LowPart, count);
@@ -6619,7 +7209,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
         goto done2;
     }
     
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     scp = fidp->scp;
     cm_HoldSCache(scp);
@@ -6678,10 +7268,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
 
     /* now, copy the data one buffer at a time, until we've filled the
      * request packet */
-    while (1) {
-        /* if we've copied all the data requested, we're done */
-        if (count <= 0) 
-            break;
+    while (count != 0) {
 
         /* handle over quota or out of space */
         if (scp->flags & (CM_SCACHEFLAG_OVERQUOTA | CM_SCACHEFLAG_OUTOFSPACE)) {
@@ -6696,13 +7283,20 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
         if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
             /* wrong buffer */
             if (bufferp) {
+                if (needSyncOpDone) {
+                    cm_SyncOpDone(scp, bufferp,
+                                  CM_SCACHESYNC_NEEDCALLBACK
+                                  | CM_SCACHESYNC_WRITE
+                                  | CM_SCACHESYNC_BUFLOCKED);
+                    needSyncOpDone = 0;
+                }
                 lock_ReleaseMutex(&bufferp->mx);
                 buf_Release(bufferp);
                 bufferp = NULL;
             }  
             lock_ReleaseWrite(&scp->rw);
 
-            code = buf_Get(scp, &thyper, &bufferp);
+            code = buf_Get(scp, &thyper, &req, &bufferp);
 
             lock_ObtainMutex(&bufferp->mx);
             lock_ObtainWrite(&scp->rw);
@@ -6711,18 +7305,17 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
             bufferOffset = thyper;
 
             /* now get the data in the cache */
-            while (1) {
-                code = cm_SyncOp(scp, bufferp, userp, &req, 0,
-                                  CM_SCACHESYNC_NEEDCALLBACK
-                                  | CM_SCACHESYNC_WRITE
-                                  | CM_SCACHESYNC_BUFLOCKED);
-                if (code) 
-                    goto done;
-
-               cm_SyncOpDone(scp, bufferp, 
-                              CM_SCACHESYNC_NEEDCALLBACK 
-                              | CM_SCACHESYNC_WRITE 
-                              | CM_SCACHESYNC_BUFLOCKED);
+            while (code == 0) {
+                if (!needSyncOpDone) {
+                    code = cm_SyncOp(scp, bufferp, userp, &req, 0,
+                                     CM_SCACHESYNC_NEEDCALLBACK
+                                     | CM_SCACHESYNC_WRITE
+                                     | CM_SCACHESYNC_BUFLOCKED);
+                    if (code)
+                        goto done;
+
+                    needSyncOpDone = 1;
+                }
 
                 /* If we're overwriting the entire buffer, or
                  * if we're writing at or past EOF, mark the
@@ -6736,7 +7329,16 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
                  * Use minLength instead of scp->length, since
                  * the latter has already been updated by this
                  * call.
+                 *
+                 * The scp lock has been dropped multiple times
+                 * so the minLength must be refreshed before it
+                 * is used.
                  */
+
+                minLength = scp->length;
+                if (LargeIntegerGreaterThan(minLength, scp->serverLength))
+                    minLength = scp->serverLength;
+
                 if (LargeIntegerGreaterThanOrEqualTo(bufferp->offset, minLength)
                      || LargeIntegerEqualTo(offset, bufferp->offset)
                      && (count >= cm_data.buf_blockSize
@@ -6753,20 +7355,21 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
                 if (cm_HaveBuffer(scp, bufferp, 1)) break;
 
                 /* otherwise, load the buffer and try again */
+               cm_SyncOpDone(scp, bufferp,
+                             CM_SCACHESYNC_NEEDCALLBACK
+                             | CM_SCACHESYNC_WRITE
+                             | CM_SCACHESYNC_BUFLOCKED);
+                needSyncOpDone = 0;
+
                 lock_ReleaseMutex(&bufferp->mx);
                 code = cm_GetBuffer(scp, bufferp, NULL, userp,
                                      &req);
                 lock_ReleaseWrite(&scp->rw);
                 lock_ObtainMutex(&bufferp->mx);
                 lock_ObtainWrite(&scp->rw);
-                if (code) break;
             }
-            if (code) {
-                lock_ReleaseMutex(&bufferp->mx);
-                buf_Release(bufferp);
-                bufferp = NULL;
+            if (code)
                 goto done;
-            }
         }      /* if (wrong buffer) ... */
 
         /* now we have the right buffer loaded.  Copy out the
@@ -6781,26 +7384,23 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
 
         /* now copy the data */
        memcpy(bufferp->datap + bufIndex, op, nbytes);
-        buf_SetDirty(bufferp, bufIndex, nbytes);
-
-        /* and record the last writer */
-        if (bufferp->userp != userp) {
-            cm_HoldUser(userp);
-            if (bufferp->userp) 
-                cm_ReleaseUser(bufferp->userp);
-            bufferp->userp = userp;
-        }
+        buf_SetDirty(bufferp, bufIndex, nbytes, userp);
 
         /* adjust counters, pointers, etc. */
         op += nbytes;
         count -= nbytes;
         written += nbytes;
-        thyper.LowPart = nbytes;
-        thyper.HighPart = 0;
-        offset = LargeIntegerAdd(thyper, offset);
-    } /* while 1 */
+        offset = LargeIntegerAdd(offset, ConvertLongToLargeInteger(nbytes));
+    } /* while count != 0 */
 
   done:
+    if (bufferp && needSyncOpDone) {
+        cm_SyncOpDone(scp, bufferp,
+                      CM_SCACHESYNC_NEEDCALLBACK
+                      | CM_SCACHESYNC_WRITE
+                      | CM_SCACHESYNC_BUFLOCKED);
+    }
+
     lock_ReleaseWrite(&scp->rw);
 
     if (bufferp) {
@@ -6810,12 +7410,15 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
 
     lock_ObtainMutex(&fidp->mx);
     if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
-         && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
+         && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) 
+    {
+        lock_ReleaseMutex(&fidp->mx);
         smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
                           fidp->NTopen_dscp, fidp->NTopen_pathp,
                           NULL, TRUE);
-    }       
-    lock_ReleaseMutex(&fidp->mx);
+    } else {
+        lock_ReleaseMutex(&fidp->mx);
+    }
 
     if (code == 0) {
         if (smb_AsyncStore > 0) {
@@ -6860,6 +7463,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_t* smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp;
+       cm_scache_t *scp;
     cm_attr_t truncAttr;       /* attribute struct used for truncating file */
     char *op;
     int inDataBlockCount;
@@ -6879,16 +7483,11 @@ 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");
+        osi_Log2(smb_logp, "smb_ReceiveCoreWrite Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
         return CM_ERROR_BADFD;
     }
         
-    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
-        smb_CloseFID(vcp, fidp, NULL, 0);
-        smb_ReleaseFID(fidp);
-        return CM_ERROR_NOSUCHFILE;
-    }
-
     lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL) {
        lock_ReleaseMutex(&fidp->mx);
@@ -6897,6 +7496,30 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        osi_Log1(smb_logp, "smb_ReceiveCoreWrite ioctl code 0x%x", code);
        return code;
     }
+
+    if (fidp->flags & SMB_FID_RPC) {
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_RPCWrite(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       osi_Log1(smb_logp, "smb_ReceiveCoreWrite RPC code 0x%x", code);
+       return code;
+    }
+
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_BADFD;
+    }
+
+    if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_CloseFID(vcp, fidp, NULL, 0);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_NOSUCHFILE;
+    }
+
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
     lock_ReleaseMutex(&fidp->mx);
     userp = smb_GetUserFromVCP(vcp, inp);
 
@@ -6913,9 +7536,9 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LLength.HighPart = 0;
         LLength.LowPart = count;
 
-        lock_ObtainWrite(&fidp->scp->rw);
-        code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
-        lock_ReleaseWrite(&fidp->scp->rw);
+        lock_ObtainWrite(&scp->rw);
+        code = cm_LockCheckWrite(scp, LOffset, LLength, key);
+        lock_ReleaseWrite(&scp->rw);
 
         if (code) {
            osi_Log1(smb_logp, "smb_ReceiveCoreWrite lock check failure 0x%x", code);
@@ -6929,7 +7552,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        osi_Log1(smb_logp, "smb_ReceiveCoreWrite truncation to length 0x%x", offset.LowPart);
         
-        cm_InitReq(&req);
+        smb_InitReq(&req);
 
         truncAttr.mask = CM_ATTRMASK_LENGTH;
         truncAttr.length.LowPart = offset.LowPart;
@@ -6955,8 +7578,10 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
      */
     lock_ObtainMutex(&fidp->mx);
     if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
+        lock_ObtainWrite(&fidp->scp->rw);
         fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
         fidp->scp->clientModTime = time(NULL);
+        lock_ReleaseWrite(&fidp->scp->rw);
     }
     lock_ReleaseMutex(&fidp->mx);
 
@@ -6987,6 +7612,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
   done:
     smb_ReleaseFID(fidp);
     cm_ReleaseUser(userp);
+       cm_ReleaseSCache(scp);
 
     return code;
 }
@@ -7004,12 +7630,21 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
     fd = smb_GetSMBParm(inp, 0);
     fidp = smb_FindFID(vcp, fd, 0);
 
-    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
-        smb_CloseFID(vcp, fidp, NULL, 0);
+    lock_ObtainMutex(&fidp->mx);
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_ReleaseFID(fidp);
         return;
     }
 
+    if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_CloseFID(vcp, fidp, NULL, 0);
+        smb_ReleaseFID(fidp);
+        return;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+       
     osi_Log3(smb_logp, "Completing Raw Write offset 0x%x:%08x count %x",
              rwcp->offset.HighPart, rwcp->offset.LowPart, rwcp->count);
 
@@ -7063,6 +7698,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     smb_t *smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp;
+       cm_scache_t *scp;
     char *op;
     unsigned short writeMode;
     char *rawBuf;
@@ -7111,15 +7747,28 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveCoreWriteRaw Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
+        return CM_ERROR_BADFD;
+    }
+    lock_ObtainMutex(&fidp->mx);
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_ReleaseFID(fidp);
         return CM_ERROR_BADFD;
     }
 
-    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+    if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_CloseFID(vcp, fidp, NULL, 0);
         smb_ReleaseFID(fidp);
         return CM_ERROR_NOSUCHFILE;
     }
 
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
+
     {
         unsigned pid;
         cm_key_t key;
@@ -7134,11 +7783,12 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         LLength.HighPart = 0;
         LLength.LowPart = count;
 
-        lock_ObtainWrite(&fidp->scp->rw);
-        code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
-        lock_ReleaseWrite(&fidp->scp->rw);
+        lock_ObtainWrite(&scp->rw);
+        code = cm_LockCheckWrite(scp, LOffset, LLength, key);
+        lock_ReleaseWrite(&scp->rw);
 
         if (code) {
+            cm_ReleaseSCache(scp);
             smb_ReleaseFID(fidp);
             return code;
         }
@@ -7158,8 +7808,10 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
      */
     lock_ObtainMutex(&fidp->mx);
     if ((fidp->flags & SMB_FID_LOOKSLIKECOPY) != SMB_FID_LOOKSLIKECOPY) {
+        lock_ObtainWrite(&fidp->scp->rw);
         fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
         fidp->scp->clientModTime = time(NULL);
+        lock_ReleaseWrite(&fidp->scp->rw);
     }
     lock_ReleaseMutex(&fidp->mx);
 
@@ -7202,6 +7854,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
     smb_ReleaseFID(fidp);
     cm_ReleaseUser(userp);
+    cm_ReleaseSCache(scp);
 
     if (code) {
         smb_SetSMBParm(outp, 0, total_written);
@@ -7242,6 +7895,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_t *smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp;
+    cm_scache_t *scp;
     char *op;
         
     fd = smb_GetSMBParm(inp, 0);
@@ -7254,15 +7908,11 @@ 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) {
+        osi_Log2(smb_logp, "smb_ReceiveCoreRead Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
         return CM_ERROR_BADFD;
-        
-    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
-        smb_CloseFID(vcp, fidp, NULL, 0);
-        smb_ReleaseFID(fidp);
-        return CM_ERROR_NOSUCHFILE;
     }
-
     lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL) {
        lock_ReleaseMutex(&fidp->mx);
@@ -7270,6 +7920,29 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        smb_ReleaseFID(fidp);
        return code;
     }
+
+    if (fidp->flags & SMB_FID_RPC) {
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_RPCRead(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
+    }
+
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_BADFD;
+    }
+
+    if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_CloseFID(vcp, fidp, NULL, 0);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_NOSUCHFILE;
+    }
+
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
     lock_ReleaseMutex(&fidp->mx);
 
     {
@@ -7284,11 +7957,12 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LLength.HighPart = 0;
         LLength.LowPart = count;
         
-        lock_ObtainWrite(&fidp->scp->rw);
-        code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
-        lock_ReleaseWrite(&fidp->scp->rw);
+        lock_ObtainWrite(&scp->rw);
+        code = cm_LockCheckRead(scp, LOffset, LLength, key);
+        lock_ReleaseWrite(&scp->rw);
     }
     if (code) {
+        cm_ReleaseSCache(scp);
         smb_ReleaseFID(fidp);
         return code;
     }
@@ -7326,6 +8000,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_ReleaseFID(fidp);
        
     cm_ReleaseUser(userp);
+    cm_ReleaseSCache(scp);
     return code;
 }
 
@@ -7346,7 +8021,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     clientchar_t *tidPathp;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     scp = NULL;
         
@@ -7355,13 +8030,15 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         
     tp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
-
-    if (cm_ClientStrCmp(pathp, _C("\\")) == 0)
-        return CM_ERROR_EXISTS;
+    if (!pathp)
+        return CM_ERROR_BADSMB;
 
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
+    if (cm_ClientStrCmp(pathp, _C("\\")) == 0)
+        return CM_ERROR_EXISTS;
+
     userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
@@ -7389,7 +8066,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -7411,7 +8088,9 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         
     setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
     setAttr.clientModTime = time(NULL);
-    code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req);
+    smb_SetInitialModeBitsForDir(0, &setAttr);
+
+    code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req, NULL);
     if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
         smb_NotifyChange(FILE_ACTION_ADDED,
                          FILE_NOTIFY_CHANGE_DIR_NAME,
@@ -7459,7 +8138,6 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     cm_scache_t *dscp;                 /* dir we're dealing with */
     cm_scache_t *scp;                  /* file we're creating */
     cm_attr_t setAttr;
-    int initialModeBits;
     smb_fid_t *fidp;
     int attributes;
     clientchar_t *lastNamep;
@@ -7469,7 +8147,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     cm_req_t req;
     int created = 0;                   /* the file was new */
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     scp = NULL;
     excl = (inp->inCom == 0x03)? 0 : 1;
@@ -7477,17 +8155,30 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     attributes = smb_GetSMBParm(inp, 0);
     dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
         
-    /* compute initial mode bits based on read-only flag in attributes */
-    initialModeBits = 0666;
-    if (attributes & SMB_ATTR_READONLY) 
-       initialModeBits &= ~0222;
-        
     tp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+    if (!pathp)
+        return CM_ERROR_BADSMB;
 
     spacep = inp->spacep;
+    /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
+    if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+        clientchar_t * hexp;
+
+        hexp = cm_GetRawCharsAlloc(pathp, -1);
+        osi_Log1(smb_logp, "CoreCreate rejecting invalid name. [%S]",
+                 osi_LogSaveClientString(smb_logp, hexp));
+        if (hexp)
+            free(hexp);
+#else
+        osi_Log0(smb_logp, "CoreCreate rejecting invalid name");
+#endif
+        return CM_ERROR_BADNTFILENAME;
+    }
+
     userp = smb_GetUserFromVCP(vcp, inp);
 
     caseFold = CM_FLAG_CASEFOLD;
@@ -7513,7 +8204,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -7565,6 +8256,8 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     else {
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
+        smb_SetInitialModeBitsForFile(attributes, &setAttr);
+
         code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
                          &req);
         if (code == 0) {
@@ -7658,7 +8351,7 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     cm_user_t *userp;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
         
     fd = smb_GetSMBParm(inp, 0);
     whence = smb_GetSMBParm(inp, 1);
@@ -7667,23 +8360,27 @@ 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)
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveCoreSeek Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
        return CM_ERROR_BADFD;
-    
-    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
-        smb_CloseFID(vcp, fidp, NULL, 0);
-        smb_ReleaseFID(fidp);
-        return CM_ERROR_NOSUCHFILE;
     }
-
     lock_ObtainMutex(&fidp->mx);
-    if (fidp->flags & SMB_FID_IOCTL) {
+    if (!fidp->scp || (fidp->flags & SMB_FID_IOCTL)) {
        lock_ReleaseMutex(&fidp->mx);
        smb_ReleaseFID(fidp);
         return CM_ERROR_BADFD;
     }
+
+    if (fidp->scp->flags & CM_SCACHEFLAG_DELETED) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_CloseFID(vcp, fidp, NULL, 0);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_NOSUCHFILE;
+    }
+
     lock_ReleaseMutex(&fidp->mx);
-       
+
     userp = smb_GetUserFromVCP(vcp, inp);
 
     lock_ObtainMutex(&fidp->mx);
@@ -7815,25 +8512,70 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
         if (dp->procp) {
             /* we have a recognized operation */
             char * opName = myCrt_Dispatch(inp->inCom);
+            smb_t *smbp;
+
+            smbp = (smb_t *) inp;
 
-            if (inp->inCom == 0x1d)
+            osi_Log5(smb_logp,"Dispatch %s mid 0x%x vcp 0x%p lana %d lsn %d",
+                      opName, smbp->mid, vcp, vcp->lana, vcp->lsn);
+            if (inp->inCom == 0x1d) {
                 /* Raw Write */
                 code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, rwcp);
-            else {
-                osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d",
-                         opName,vcp,vcp->lana,vcp->lsn);
+            } else {
                 code = (*(dp->procp)) (vcp, inp, outp);
-                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 )
-                     smb_LogPacket(inp);
-#endif /* LOG_PACKET */
             }   
+            osi_Log5(smb_logp,"Dispatch return code 0x%x mid 0x%x vcp 0x%p lana %d lsn %d",
+                      code, smbp->mid, vcp, vcp->lana, vcp->lsn);
 
             newTime = GetTickCount();
-            osi_Log2(smb_logp, "Dispatch %s duration %d ms", opName, newTime - oldTime);
+            osi_Log3(smb_logp, "Dispatch %s mid 0x%x duration %d ms", 
+                     opName, smbp->mid, newTime - oldTime);
+
+#ifdef LOG_PACKET
+            if ( code == CM_ERROR_BADSMB ||
+                 code == CM_ERROR_BADOP )
+                smb_LogPacket(inp);
+#endif /* LOG_PACKET */
+
+            /* ReceiveV3Tran2A handles its own logging */
+            if (inp->inCom != 0x32 && newTime - oldTime > 45000) {
+                smb_user_t *uidp;
+                smb_fid_t *fidp;
+                clientchar_t *treepath = NULL;  /* do not free */
+                clientchar_t *pathname = NULL;
+                cm_fid_t afid = {0,0,0,0,0};
+
+                uidp = smb_FindUID(vcp, smbp->uid, 0);
+                smb_LookupTIDPath(vcp, smbp->tid, &treepath);
+                fidp = smb_FindFID(vcp, inp->fid, 0);
+
+                if (fidp) {
+                    lock_ObtainMutex(&fidp->mx);
+                    if (fidp->NTopen_pathp)
+                        pathname = fidp->NTopen_pathp;
+                    if (fidp->scp)
+                        afid = fidp->scp->fid;
+                } else {
+                    if (inp->stringsp->wdata)
+                        pathname = inp->stringsp->wdata;
+                }
+
+                afsi_log("Request %s duration %d ms user 0x%x \"%S\" pid 0x%x mid 0x%x tid 0x%x \"%S\" path? \"%S\" afid (%d.%d.%d.%d)", 
+                          opName, newTime - oldTime, 
+                          smbp->uid, uidp ? uidp->unp->name : NULL,
+                          smbp->pid, smbp->mid, smbp->tid,
+                          treepath,
+                          pathname, 
+                          afid.cell, afid.volume, afid.vnode, afid.unique);
+
+                if (fidp)
+                    lock_ReleaseMutex(&fidp->mx);
+
+                if (uidp)
+                    smb_ReleaseUID(uidp);
+                if (fidp)
+                    smb_ReleaseFID(fidp);
+            }
 
             if (oldGen != sessionGen) {
                LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION, 
@@ -8162,8 +8904,8 @@ void smb_Server(VOID *parmp)
 
     rx_StartClientThread();
 
-    outncbp = GetNCB();
-    outbufp = GetPacket();
+    outncbp = smb_GetNCB();
+    outbufp = smb_GetPacket();
     outbufp->ncbp = outncbp;
 
     while (1) {
@@ -8172,7 +8914,7 @@ void smb_Server(VOID *parmp)
            vcp = NULL;
        }
 
-       smb_ResetServerPriority();
+       cm_ResetServerPriority();
 
         code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
                                                  FALSE, INFINITE);
@@ -8253,12 +8995,12 @@ void smb_Server(VOID *parmp)
                    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);
                }
+                smb_CleanupDeadVC(vcp);
+                smb_ReleaseVC(vcp);
+                vcp = NULL;
             }
             goto doneWithNCB;
 
@@ -8285,31 +9027,33 @@ void smb_Server(VOID *parmp)
         default:
             /* A weird error code.  Log it, sleep, and continue. */
             vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
-           if (vcp) 
+           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);
-               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)
+                if (vcp->errorCount++ > 3) {
+                    osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
+                    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);
+                    } else {
+                        lock_ReleaseMutex(&vcp->mx);
+                    }
+                    smb_CleanupDeadVC(vcp);
+                    smb_ReleaseVC(vcp);
+                    vcp = NULL;
+                    goto doneWithNCB;
+                }
+                else {
                    lock_ReleaseMutex(&vcp->mx);
-                thrd_Sleep(1000);
-               thrd_SetEvent(SessionEvents[idx_session]);
+                    smb_ReleaseVC(vcp);
+                    vcp = NULL;
+                    Sleep(10);
+                    thrd_SetEvent(SessionEvents[idx_session]);
+                }
             }
            continue;
         }
@@ -8357,7 +9101,7 @@ void smb_Server(VOID *parmp)
             continue;
         }
 
-       smb_SetRequestStartTime();
+       cm_SetRequestStartTime();
 
         vcp->errorCount = 0;
         bufp = (struct smb_packet *) ncbp->ncb_buffer;
@@ -8371,14 +9115,17 @@ void smb_Server(VOID *parmp)
             if (smbp->com == 0x1d) {
                 /* Special handling for Write Raw */
                 raw_write_cont_t rwc;
-                EVENT_HANDLE rwevent;
-                char eventName[MAX_PATH];
             
                 smb_DispatchPacket(vcp, bufp, outbufp, ncbp, &rwc);
                 if (rwc.code == 0) {
-                    rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, TEXT("smb_Server() rwevent"));
+                    EVENT_HANDLE rwevent;
+                    char eventName[MAX_PATH];
+
+                    snprintf(eventName, MAX_PATH, "smb_Server() rwevent %d", myIdx);
+                    rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
                     if ( GetLastError() == ERROR_ALREADY_EXISTS )
                         osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
+
                     ncbp->ncb_command = NCBRECV | ASYNCH;
                     ncbp->ncb_lsn = (unsigned char) vcp->lsn;
                     ncbp->ncb_lana_num = vcp->lana;
@@ -8418,6 +9165,10 @@ void smb_Server(VOID *parmp)
     }
     if (vcp)
         smb_ReleaseVC(vcp);
+    if (outbufp)
+        smb_FreePacket(outbufp);
+    if (outncbp)
+        smb_FreeNCB(outncbp);
 }
 
 /*
@@ -8452,7 +9203,7 @@ void InitNCBslot(int idx)
 
     osi_assertx( idx < (sizeof(NCBs) / sizeof(NCBs[0])), "invalid index" );
 
-    NCBs[idx] = GetNCB();
+    NCBs[idx] = smb_GetNCB();
     sprintf(eventName,"NCBavails[%d]", idx);
     NCBavails[idx] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
@@ -8467,7 +9218,7 @@ void InitNCBslot(int idx)
         osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
     for (i=0; i<smb_NumServerThreads; i++)
         NCBreturns[i][idx] = retHandle;
-    bufp = GetPacket();
+    bufp = smb_GetPacket();
     bufp->spacep = cm_GetSpace();
     bufs[idx] = bufp;
 }
@@ -8487,13 +9238,15 @@ void smb_Listener(void *parmp)
     int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
     INT_PTR lana = (INT_PTR) parmp;
     char eventName[MAX_PATH];
+    int bridgeCount = 0;
+    int nowildCount = 0;
 
     sprintf(eventName,"smb_Listener_lana_%d", (unsigned char)lana);
     ListenerShutdown[lana] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
         thrd_ResetEvent(ListenerShutdown[lana]);
 
-    ncbp = GetNCB();
+    ncbp = smb_GetNCB();
 
     /* retrieve computer name */
     GetComputerName(cname, &cnamelen);
@@ -8521,9 +9274,10 @@ void smb_Listener(void *parmp)
 
         if (code == NRC_NAMERR) {
          /* An smb shutdown or Vista resume must have taken place */
-         osi_Log2(smb_logp,
+         osi_Log1(smb_logp,
                   "NCBLISTEN lana=%d failed with NRC_NAMERR.",
-                  ncbp->ncb_lana_num, code);
+                  ncbp->ncb_lana_num);
+         afsi_log("NCBLISTEN lana=%d failed with NRC_NAMERR.", ncbp->ncb_lana_num);
 
             if (lock_TryMutex(&smb_StartedLock)) {
                 lana_list.lana[i] = LANA_INVALID;
@@ -8533,6 +9287,29 @@ void smb_Listener(void *parmp)
         } else if (code ==  NRC_BRIDGE || code != 0) {
             int lanaRemaining = 0;
 
+            if (code == NRC_BRIDGE) {
+                if (++bridgeCount <= 5) {
+                    afsi_log("NCBLISTEN lana=%d failed with NRC_BRIDGE, retrying ...", ncbp->ncb_lana_num);
+                    continue;
+                }
+            } else if (code == NRC_NOWILD) {
+                if (++nowildCount <= 5) {
+                    afsi_log("NCBLISTEN lana=%d failed with NRC_NOWILD, retrying ...", ncbp->ncb_lana_num);
+
+                    if (bridgeCount > 0) {
+                        memset(ncbp, 0, sizeof(*ncbp));
+                        ncbp->ncb_command = NCBADDNAME;
+                        ncbp->ncb_lana_num = (UCHAR)lana;
+                        /* pad out with spaces instead of null termination */
+                        len = (long)strlen(smb_localNamep);
+                        strncpy(ncbp->ncb_name, smb_localNamep, NCBNAMSZ);
+                        for (i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
+                        code = Netbios(ncbp);
+                    }
+                    continue;
+                }
+            }
+
             while (!lock_TryMutex(&smb_StartedLock)) {
                 if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1)
                     goto exit_thread;
@@ -8542,6 +9319,8 @@ void smb_Listener(void *parmp)
             osi_Log2(smb_logp,
                       "NCBLISTEN lana=%d failed with %s.  Listener thread exiting.",
                       ncbp->ncb_lana_num, ncb_error_string(code));
+           afsi_log("NCBLISTEN lana=%d failed with %s.  Listener thread exiting.",
+                    ncbp->ncb_lana_num, ncb_error_string(code));
 
            for (i = 0; i < lana_list.length; i++) {
                if (lana_list.lana[i] == lana) {
@@ -8596,6 +9375,10 @@ void smb_Listener(void *parmp)
         }
 #endif /* 0 */
 
+        /* a successful packet received.  clear bridge error count */
+        bridgeCount = 0;
+        nowildCount = 0;
+
         /* check for remote conns */
         /* first get remote name and insert null terminator */
         memcpy(rname, ncbp->ncb_callname, NCBNAMSZ);
@@ -8675,7 +9458,7 @@ void smb_Listener(void *parmp)
 
         if (session >= SESSION_MAX - 1  || numNCBs >= NCB_MAX - 1) {
             unsigned long code = CM_ERROR_ALLBUSY;
-            smb_packet_t * outp = GetPacket();
+            smb_packet_t * outp = smb_GetPacket();
             unsigned char *outWctp;
             smb_t *smbp;
             
@@ -8776,12 +9559,301 @@ void smb_Listener(void *parmp)
     }  /* dispatch while loop */
 
 exit_thread:
-    FreeNCB(ncbp);
+    smb_FreeNCB(ncbp);
     thrd_SetEvent(ListenerShutdown[lana]);
     return;
 }
 
 static void
+configureBackConnectionHostNames(void)
+{
+    /* On Windows XP SP2, Windows 2003 SP1, and all future Windows operating systems
+     * there is a restriction on the use of SMB authentication on loopback connections.
+     * There are two work arounds available:
+     * 
+     *   (1) We can disable the check for matching host names.  This does not
+     *   require a reboot:
+     *   [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
+     *     "DisableLoopbackCheck"=dword:00000001
+     *
+     *   (2) We can add the AFS SMB/CIFS service name to an approved list.  This
+     *   does require a reboot:
+     *   [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0]
+     *     "BackConnectionHostNames"=multi-sz
+     *
+     * The algorithm will be:
+     *   (1) Check to see if cm_NetbiosName exists in the BackConnectionHostNames list
+     *   (2a) If not, add it to the list.  (This will not take effect until the next reboot.)
+     *   (2b1)    and check to see if DisableLoopbackCheck is set.
+     *   (2b2)    If not set, set the DisableLoopbackCheck value to 0x1 
+     *   (2b3)                and create HKLM\SOFTWARE\OpenAFS\Client  UnsetDisableLoopbackCheck
+     *   (2c) else If cm_NetbiosName exists in the BackConnectionHostNames list,
+     *             check for the UnsetDisableLoopbackCheck value.  
+     *             If set, set the DisableLoopbackCheck flag to 0x0 
+     *             and delete the UnsetDisableLoopbackCheck value
+     *
+     * Starting in Longhorn Beta 1, an entry in the BackConnectionHostNames value will
+     * force Windows to use the loopback authentication mechanism for the specified 
+     * services.
+     * 
+     * Do not permit the "DisableLoopbackCheck" value to be removed within the same
+     * service session that set it.  
+     */
+    HKEY hkLsa;
+    HKEY hkMSV10;
+    HKEY hkClient;
+    DWORD dwType;
+    DWORD dwSize, dwAllocSize;
+    DWORD dwValue;
+    PBYTE pHostNames = NULL, pName = NULL;
+    BOOL  bNameFound = FALSE;   
+    static BOOL bLoopbackCheckDisabled = FALSE;
+
+    /* BackConnectionHostNames and DisableLoopbackCheck */
+    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                       "SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0",
+                       0,
+                       KEY_READ|KEY_WRITE,
+                       &hkMSV10) == ERROR_SUCCESS )
+    {
+        if ((RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, 
+                            &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) &&
+            (dwType == REG_MULTI_SZ)) 
+        {
+           dwAllocSize += 1 /* in case the source string is not nul terminated */
+               + (DWORD)strlen(cm_NetbiosName) + 2;
+           pHostNames = malloc(dwAllocSize);
+           dwSize = dwAllocSize;
+            if (RegQueryValueEx( hkMSV10, "BackConnectionHostNames", 0, &dwType, 
+                                pHostNames, &dwSize) == ERROR_SUCCESS) 
+            {
+               for (pName = pHostNames; 
+                    (pName - pHostNames < (int) dwSize) && *pName ; 
+                    pName += strlen(pName) + 1)
+               {
+                   if ( !stricmp(pName, cm_NetbiosName) ) {
+                       bNameFound = TRUE;
+                       break;
+                   }   
+               }
+           }
+        }
+             
+        if ( !bNameFound ) {
+            size_t size = strlen(cm_NetbiosName) + 2;
+            if ( !pHostNames ) {
+                pHostNames = malloc(size);
+               pName = pHostNames;
+            }
+            StringCbCopyA(pName, size, cm_NetbiosName);
+            pName += size - 1;
+            *pName = '\0';  /* add a second nul terminator */
+
+            dwType = REG_MULTI_SZ;
+           dwSize = (DWORD)(pName - pHostNames + 1);
+            RegSetValueEx( hkMSV10, "BackConnectionHostNames", 0, dwType, pHostNames, dwSize);
+
+            if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                               "SYSTEM\\CurrentControlSet\\Control\\Lsa",
+                               0,
+                               KEY_READ|KEY_WRITE,
+                               &hkLsa) == ERROR_SUCCESS )
+            {
+                dwSize = sizeof(DWORD);
+                if ( RegQueryValueEx( hkLsa, "DisableLoopbackCheck", 0, &dwType, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS ||
+                     dwValue == 0 ) {
+                    dwType = REG_DWORD;
+                    dwSize = sizeof(DWORD);
+                    dwValue = 1;
+                    RegSetValueEx( hkLsa, "DisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize);
+
+                    if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
+                                        AFSREG_CLT_OPENAFS_SUBKEY,
+                                        0,
+                                        NULL,
+                                        REG_OPTION_NON_VOLATILE,
+                                        KEY_READ|KEY_WRITE,
+                                        NULL,
+                                        &hkClient,
+                                        NULL) == ERROR_SUCCESS) {
+
+                        dwType = REG_DWORD;
+                        dwSize = sizeof(DWORD);
+                        dwValue = 1;
+                        RegSetValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, dwType, (LPBYTE)&dwValue, dwSize);
+                        bLoopbackCheckDisabled = TRUE;
+                        RegCloseKey(hkClient);
+                    }
+                    RegCloseKey(hkLsa);
+                }
+            }
+        } else if (!bLoopbackCheckDisabled) {
+            if (RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
+                                AFSREG_CLT_OPENAFS_SUBKEY,
+                                0,
+                                NULL,
+                                REG_OPTION_NON_VOLATILE,
+                                KEY_READ|KEY_WRITE,
+                                NULL,
+                                &hkClient,
+                                NULL) == ERROR_SUCCESS) {
+
+                dwSize = sizeof(DWORD);
+                if ( RegQueryValueEx( hkClient, "RemoveDisableLoopbackCheck", 0, &dwType, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS &&
+                     dwValue == 1 ) {
+                    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                                       "SYSTEM\\CurrentControlSet\\Control\\Lsa",
+                                       0,
+                                       KEY_READ|KEY_WRITE,
+                                       &hkLsa) == ERROR_SUCCESS )
+                    {
+                        RegDeleteValue(hkLsa, "DisableLoopbackCheck");
+                        RegCloseKey(hkLsa);
+                    }
+                }
+                RegDeleteValue(hkClient, "RemoveDisableLoopbackCheck");
+                RegCloseKey(hkClient);
+            }
+        }
+
+        if (pHostNames) {
+            free(pHostNames);
+            pHostNames = NULL;
+        }
+
+        RegCloseKey(hkMSV10);
+    }
+}
+
+
+static void
+configureExtendedSMBSessionTimeouts(void)
+{
+    /*
+     * In a Hot Fix to Windows 2003 SP2, the smb redirector was given the following
+     * new functionality:
+     *
+     *  [HKLM\SYSTEM\CurrentControlSet\Services\LanManWorkstation\Parameters]
+     *   "ReconnectableServers"            REG_MULTI_SZ
+     *   "ExtendedSessTimeout"             REG_DWORD  (seconds)
+     *   "ServersWithExtendedSessTimeout"  REG_MULTI_SZ 
+     *  
+     * These values can be used to prevent the smb redirector from timing out
+     * smb connection to the afs smb server prematurely.
+     */
+    HKEY hkLanMan;
+    DWORD dwType;
+    DWORD dwSize, dwAllocSize;
+    DWORD dwValue;
+    PBYTE pHostNames = NULL, pName = NULL;
+    BOOL  bNameFound = FALSE;   
+
+    if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE, 
+                       "SYSTEM\\CurrentControlSet\\Services\\LanManWorkstation\\Parameters",
+                       0,
+                       KEY_READ|KEY_WRITE,
+                       &hkLanMan) == ERROR_SUCCESS )
+    {
+        if ((RegQueryValueEx( hkLanMan, "ReconnectableServers", 0, 
+                            &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) &&
+            (dwType == REG_MULTI_SZ)) 
+        {
+           dwAllocSize += 1 /* in case the source string is not nul terminated */
+               + (DWORD)strlen(cm_NetbiosName) + 2;
+           pHostNames = malloc(dwAllocSize);
+           dwSize = dwAllocSize;
+            if (RegQueryValueEx( hkLanMan, "ReconnectableServers", 0, &dwType, 
+                                pHostNames, &dwSize) == ERROR_SUCCESS) 
+            {
+               for (pName = pHostNames; 
+                    (pName - pHostNames < (int) dwSize) && *pName ; 
+                    pName += strlen(pName) + 1)
+               {
+                   if ( !stricmp(pName, cm_NetbiosName) ) {
+                       bNameFound = TRUE;
+                       break;
+                   }   
+               }
+           }
+        }
+             
+        if ( !bNameFound ) {
+            size_t size = strlen(cm_NetbiosName) + 2;
+            if ( !pHostNames ) {
+                pHostNames = malloc(size);
+               pName = pHostNames;
+            }
+            StringCbCopyA(pName, size, cm_NetbiosName);
+            pName += size - 1;
+            *pName = '\0';  /* add a second nul terminator */
+
+            dwType = REG_MULTI_SZ;
+           dwSize = (DWORD)(pName - pHostNames + 1);
+            RegSetValueEx( hkLanMan, "ReconnectableServers", 0, dwType, pHostNames, dwSize);
+        }
+
+        if (pHostNames) {
+            free(pHostNames);
+            pHostNames = NULL;
+        }
+        
+        if ((RegQueryValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0, 
+                            &dwType, NULL, &dwAllocSize) == ERROR_SUCCESS) &&
+            (dwType == REG_MULTI_SZ)) 
+        {
+           dwAllocSize += 1 /* in case the source string is not nul terminated */
+               + (DWORD)strlen(cm_NetbiosName) + 2;
+           pHostNames = malloc(dwAllocSize);
+           dwSize = dwAllocSize;
+            if (RegQueryValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0, &dwType, 
+                                pHostNames, &dwSize) == ERROR_SUCCESS) 
+            {
+               for (pName = pHostNames; 
+                    (pName - pHostNames < (int) dwSize) && *pName ; 
+                    pName += strlen(pName) + 1)
+               {
+                   if ( !stricmp(pName, cm_NetbiosName) ) {
+                       bNameFound = TRUE;
+                       break;
+                   }   
+               }
+           }
+        }
+             
+        if ( !bNameFound ) {
+            size_t size = strlen(cm_NetbiosName) + 2;
+            if ( !pHostNames ) {
+                pHostNames = malloc(size);
+               pName = pHostNames;
+            }
+            StringCbCopyA(pName, size, cm_NetbiosName);
+            pName += size - 1;
+            *pName = '\0';  /* add a second nul terminator */
+
+            dwType = REG_MULTI_SZ;
+           dwSize = (DWORD)(pName - pHostNames + 1);
+            RegSetValueEx( hkLanMan, "ServersWithExtendedSessTimeout", 0, dwType, pHostNames, dwSize);
+        }
+
+        if (pHostNames) {
+            free(pHostNames);
+            pHostNames = NULL;
+        }
+
+        if ((RegQueryValueEx( hkLanMan, "ExtendedSessTimeout", 0, 
+                              &dwType, (LPBYTE)&dwValue, &dwAllocSize) != ERROR_SUCCESS) ||
+             (dwType != REG_DWORD)) 
+        {
+            dwType = REG_DWORD;
+           dwSize = sizeof(dwValue);
+            dwValue = 300;      /* 5 minutes */
+            RegSetValueEx( hkLanMan, "ExtendedSessTimeout", 0, dwType, (const BYTE *)&dwValue, dwSize);
+        }
+        RegCloseKey(hkLanMan);
+    }
+}
+
+static void
 smb_LanAdapterChangeThread(void *param)
 {
     /* 
@@ -8831,33 +9903,41 @@ void smb_LanAdapterChange(int locked) {
         SUCCEEDED(lana_GetUncServerNameEx(NetbiosName, &lanaNum, &bGateway, 
                                           LANA_NETBIOS_NAME_FULL)) &&
         lanaNum != LANA_INVALID && smb_LANadapter != lanaNum) {
-        if ( isGateway != bGateway ||
-             strcmp(cm_NetbiosName, NetbiosName) ) {
+        if ( isGateway != bGateway ) {
+            afsi_log("Lan Adapter Change detected (%d != %d): gateway %d != %d",
+                      smb_LANadapter, lanaNum, isGateway, bGateway);
+            change = 1;
+        } else if (strcmp(cm_NetbiosName, NetbiosName) ) {
+            afsi_log("Lan Adapter Change detected (%d != %d): name %s != %s",
+                      smb_LANadapter, lanaNum, cm_NetbiosName, NetbiosName);
             change = 1;
         } else {
-            NCB *ncbp = GetNCB();
+            NCB *ncbp = smb_GetNCB();
             ncbp->ncb_command = NCBENUM;
             ncbp->ncb_buffer = (PUCHAR)&temp_list;
             ncbp->ncb_length = sizeof(temp_list);
             code = Netbios(ncbp);
             if (code == 0) {
-                if (temp_list.length != lana_list.length)
+                if (temp_list.length != lana_list.length) {
+                    afsi_log("Lan Adapter Change detected (%d != %d): lan list length changed %d != %d",
+                              smb_LANadapter, lanaNum, temp_list.length, lana_list.length);
                     change = 1;
-                else {
+                } else {
                     for (i=0; i<lana_list.length; i++) {
                         if ( temp_list.lana[i] != lana_list.lana[i] ) {
+                            afsi_log("Lan Adapter Change detected (%d != %d): lana[%d] %d != %d",
+                                      smb_LANadapter, lanaNum, i, temp_list.lana[i], lana_list.lana[i]);
                             change = 1;
                             break;
                         }
                     }
                 }
             }
-           FreeNCB(ncbp);
+           smb_FreeNCB(ncbp);
         }
     } 
 
     if (change) {
-        afsi_log("Lan Adapter Change detected");
         smb_StopListeners(1);
         smb_RestartListeners(1);
     }
@@ -8887,7 +9967,7 @@ int smb_NetbiosInit(int locked)
         return 0;
     }
     /* setup the NCB system */
-    ncbp = GetNCB();
+    ncbp = smb_GetNCB();
 
     /* Call lanahelper to get Netbios name, lan adapter number and gateway flag */
     if (SUCCEEDED(code = lana_GetUncServerNameEx(cm_NetbiosName, &lanaNum, &isGateway, LANA_NETBIOS_NAME_FULL))) {
@@ -9039,7 +10119,7 @@ int smb_NetbiosInit(int locked)
     }
         
     /* we're done with the NCB now */
-    FreeNCB(ncbp);
+    smb_FreeNCB(ncbp);
 
     afsi_log("smb_NetbiosInit smb_LANadapter=%d",smb_LANadapter);
     if (lana_list.length > 0)
@@ -9067,6 +10147,15 @@ void smb_StartListeners(int locked)
     }
 
     afsi_log("smb_StartListeners");
+    /* Ensure the AFS Netbios Name is registered to allow loopback access */
+    configureBackConnectionHostNames();
+
+    /* Configure Extended SMB Session Timeouts */
+    if (msftSMBRedirectorSupportsExtendedTimeouts()) {
+        afsi_log("Microsoft SMB Redirector supports Extended Timeouts");
+        configureExtendedSMBSessionTimeouts();
+    }
+
     smb_ListenerState = SMB_LISTENER_STARTED;
     cm_VolStatus_Network_Started(cm_NetbiosName
 #ifdef _WIN64
@@ -9116,7 +10205,7 @@ void smb_StopListener(NCB *ncbp, int lana, int wait)
     memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
     code = Netbios(ncbp);
           
-    afsi_log("Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
+    afsi_log("StopListener: Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
              lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
 
     /* and then reset the LANA; this will cause the listener threads to exit */
@@ -9128,9 +10217,9 @@ void smb_StopListener(NCB *ncbp, int lana, int wait)
     if (code == 0) 
        code = ncbp->ncb_retcode;
     if (code != 0) {
-       afsi_log("Netbios NCBRESET lana %d error code %d", lana, code);
+       afsi_log("StopListener: Netbios NCBRESET lana %d error code %d", lana, code);
     } else {
-       afsi_log("Netbios NCBRESET lana %d succeeded", lana);
+       afsi_log("StopListener: Netbios NCBRESET lana %d succeeded", lana);
     }
 
     if (wait)
@@ -9159,7 +10248,7 @@ void smb_StopListeners(int locked)
 #endif
                                   );
 
-    ncbp = GetNCB();
+    ncbp = smb_GetNCB();
 
     /* Unregister the SMB name */
     for (l = 0; l < lana_list.length; l++) {
@@ -9176,7 +10265,7 @@ void smb_StopListeners(int locked)
     /* force a re-evaluation of the network adapters */
     lana_list.length = 0;
     smb_LANadapter = LANA_INVALID;
-    FreeNCB(ncbp);
+    smb_FreeNCB(ncbp);
     if (!locked)
         lock_ReleaseMutex(&smb_StartedLock);
 }
@@ -9189,14 +10278,12 @@ void smb_Init(osi_log_t *logp, int useV3,
 {
     thread_t phandle;
     int lpid;
-    INT_PTR i;
+    UINT_PTR i;
     struct tm myTime;
     EVENT_HANDLE retHandle;
     char eventName[MAX_PATH];
     int startListeners = 0;
 
-    smb_TlsRequestSlot = TlsAlloc();
-
     smb_MBfunc = aMBfunc;
 
     smb_useV3 = useV3;
@@ -9211,10 +10298,6 @@ void smb_Init(osi_log_t *logp, int useV3,
     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();
@@ -9224,14 +10307,14 @@ void smb_Init(osi_log_t *logp, int useV3,
     smb_logp = logp;
         
     /* and the global lock */
-    lock_InitializeRWLock(&smb_globalLock, "smb global lock");
-    lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock");
+    lock_InitializeRWLock(&smb_globalLock, "smb global lock", LOCK_HIERARCHY_SMB_GLOBAL);
+    lock_InitializeRWLock(&smb_rctLock, "smb refct and tree struct lock", LOCK_HIERARCHY_SMB_RCT_GLOBAL);
 
     /* Raw I/O data structures */
-    lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock");
+    lock_InitializeMutex(&smb_RawBufLock, "smb raw buffer lock", LOCK_HIERARCHY_SMB_RAWBUF);
 
-    lock_InitializeMutex(&smb_ListenerLock, "smb listener lock");
-    lock_InitializeMutex(&smb_StartedLock, "smb started lock");
+    lock_InitializeMutex(&smb_ListenerLock, "smb listener lock", LOCK_HIERARCHY_SMB_LISTENER);
+    lock_InitializeMutex(&smb_StartedLock, "smb started lock", LOCK_HIERARCHY_SMB_STARTED);
        
     /* 4 Raw I/O buffers */
     smb_RawBufs = calloc(65536,1);
@@ -9445,13 +10528,12 @@ void smb_Init(osi_log_t *logp, int useV3,
                                                     );
 
                 if (nts != STATUS_SUCCESS && ntsEx != STATUS_SUCCESS) {
-                    char message[AFSPATHMAX];
-                    sprintf(message,"MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x",
-                                       nts, ntsEx);
-                    OutputDebugString(message);
-                    afsi_log(message);
+                    osi_Log2(smb_logp, "MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x",
+                             nts, ntsEx);
+
+                    afsi_log("MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x", nts, ntsEx);
                 } else {
-                    OutputDebugString("MsV1_0SetProcessOption success");
+                    osi_Log0(smb_logp, "MsV1_0SetProcessOption success");
                     afsi_log("MsV1_0SetProcessOption success");
                 }
                 /* END - code from Larry */
@@ -9558,13 +10640,13 @@ void smb_Shutdown(void)
     /*fprintf(stderr, "Entering smb_Shutdown\n");*/
         
     /* setup the NCB system */
-    ncbp = GetNCB();
+    ncbp = smb_GetNCB();
 
     /* Block new sessions by setting shutdown flag */
     smbShutdownFlag = 1;
 
     /* Hang up all sessions */
-    memset((char *)ncbp, 0, sizeof(NCB));
+    memset(ncbp, 0, sizeof(NCB));
     for (i = 1; i < numSessions; i++)
     {
         if (dead_sessions[i])
@@ -9602,7 +10684,7 @@ void smb_Shutdown(void)
     }                                                                            
 
     /* Delete Netbios name */
-    memset((char *)ncbp, 0, sizeof(NCB));
+    memset(ncbp, 0, sizeof(NCB));
     for (i = 0; i < lana_list.length; i++) {
         if (lana_list.lana[i] == LANA_INVALID) continue;
         ncbp->ncb_command = NCBDELNAME;
@@ -9612,7 +10694,7 @@ void smb_Shutdown(void)
         if (code == 0) 
             code = ncbp->ncb_retcode;
         if (code != 0) {
-            fprintf(stderr, "Netbios NCBDELNAME lana %d error code %d",
+            fprintf(stderr, "Shutdown: Netbios NCBDELNAME lana %d error code %d",
                      ncbp->ncb_lana_num, code);
         }       
         fflush(stderr);
@@ -9634,6 +10716,7 @@ void smb_Shutdown(void)
             if (fidp->scp != NULL) {
                 cm_scache_t * scp;
 
+                lock_ReleaseWrite(&smb_rctLock);
                 lock_ObtainMutex(&fidp->mx);
                 if (fidp->scp != NULL) {
                     scp = fidp->scp;
@@ -9645,6 +10728,7 @@ void smb_Shutdown(void)
                     cm_ReleaseSCache(scp);
                 }
                 lock_ReleaseMutex(&fidp->mx);
+                lock_ObtainWrite(&smb_rctLock);
             }
         }
 
@@ -9659,15 +10743,14 @@ void smb_Shutdown(void)
         }
     }
     lock_ReleaseWrite(&smb_rctLock);
-    FreeNCB(ncbp);
-    TlsFree(smb_TlsRequestSlot);
+    smb_FreeNCB(ncbp);
 }
 
 /* Get the UNC \\<servername>\<sharename> prefix. */
 char *smb_GetSharename()
 {
     char *name;
-    int len;
+    size_t len;
 
     /* Make sure we have been properly initialized. */
     if (smb_localNamep == NULL)
@@ -9751,37 +10834,119 @@ void smb_LogPacket(smb_packet_t *packet)
 int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
 {
     int zilch;
-    char output[1024];
+    char output[4196];
   
     smb_vc_t *vcp;
-  
+    smb_username_t *unp;
+    smb_waitingLockRequest_t *wlrp;
+
     if (lock)
         lock_ObtainRead(&smb_rctLock);
   
+    sprintf(output, "begin dumping smb_username_t\r\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+    for (unp = usernamesp; unp; unp=unp->nextp) 
+    {
+        cm_ucell_t *ucellp;
+
+        sprintf(output, "%s -- smb_unp=0x%p, refCount=%d, cm_userp=0x%p, flags=0x%x, logoff=%u, name=%S, machine=%S\r\n", 
+                cookie, unp, unp->refCount, unp->userp, unp->flags, unp->last_logoff_t,
+                unp->name ? unp->name : _C("NULL"), 
+                unp->machine ? unp->machine : _C("NULL"));
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+        sprintf(output, "  begin dumping cm_ucell_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+        for ( ucellp = unp->userp->cellInfop; ucellp; ucellp = ucellp->nextp ) {
+            sprintf(output, "  %s -- ucellp=0x%p, cellp=0x%p, flags=0x%x, tktLen=%04u, kvno=%03u, expires=%I64u, gen=%d, name=%s, cellname=%s\r\n", 
+                     cookie, ucellp, ucellp->cellp, ucellp->flags, ucellp->ticketLen, ucellp->kvno, 
+                     ucellp->expirationTime, ucellp->gen, 
+                     ucellp->userName,
+                     ucellp->cellp->name);
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+
+        sprintf(output, "  done dumping cm_ucell_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+    }
+    sprintf(output, "done dumping smb_username_t\r\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+
+    sprintf(output, "begin dumping smb_waitingLockRequest_t\r\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+
+    for ( wlrp = smb_allWaitingLocks; wlrp; wlrp = (smb_waitingLockRequest_t *) osi_QNext(&wlrp->q)) {
+        smb_waitingLock_t *lockp;
+
+        sprintf(output, "%s wlrp=0x%p vcp=0x%p, scp=0x%p, type=0x%x, start_t=0x%I64u msTimeout=0x%x\r\n",
+                 cookie, wlrp, wlrp->vcp, wlrp->scp, wlrp->lockType, wlrp->start_t, wlrp->msTimeout);
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+      
+        sprintf(output, "  begin dumping smb_waitingLock_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        for (lockp = wlrp->locks; lockp; lockp = (smb_waitingLock_t *) osi_QNext(&lockp->q)) {
+            sprintf(output, "  %s -- waitlockp=0x%p lockp=0x%p key=0x%I64x offset=0x%I64x length=0x%I64x state=0x%x\r\n", 
+                    cookie, lockp, lockp->lockp, lockp->key, lockp->LOffset.QuadPart, lockp->LLength.QuadPart, lockp->state);
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+        sprintf(output, "  done dumping smb_waitingLock_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+    }
+
+    sprintf(output, "done dumping smb_waitingLockRequest_t\r\n");
+    WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
     sprintf(output, "begin dumping smb_vc_t\r\n");
     WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
 
     for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) 
     {
         smb_fid_t *fidp;
+        smb_tid_t *tidp;
+        smb_user_t *userp;
       
-        sprintf(output, "%s vcp=0x%p, refCount=%d, flags=%d, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\n",
+        sprintf(output, "%s vcp=0x%p, refCount=%d, flags=0x%x, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\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\r\n");
+        sprintf(output, "  begin dumping smb_user_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        for (userp = vcp->usersp; userp; userp = userp->nextp) {
+            sprintf(output, "  %s -- smb_userp=0x%p, refCount=%d, uid=%d, vcp=0x%p, unp=0x%p, flags=0x%x, delOk=%d\r\n", 
+                    cookie, userp, userp->refCount, userp->userID, userp->vcp, userp->unp, userp->flags, userp->deleteOk);
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+        sprintf(output, "  done dumping smb_user_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+        sprintf(output, "  begin dumping smb_tid_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+            sprintf(output, "  %s -- smb_tidp=0x%p, refCount=%d, tid=%d, vcp=0x%p, cm_userp=0x%p, flags=0x%x, delOk=%d, path=%S\r\n", 
+                    cookie, tidp, tidp->refCount, tidp->tid, tidp->vcp, tidp->userp, tidp->flags, tidp->deleteOk,
+                    tidp->pathname ? tidp->pathname : _C("NULL"));
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+        sprintf(output, "  done dumping smb_tid_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+        sprintf(output, "  begin dumping smb_fid_t\r\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\r\n", 
-                     cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
+            sprintf(output, "  %s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, userp=0x%p, ioctlp=0x%p, flags=0x%x, delOk=%d, NTopen_pathp=%S, NTopen_wholepathp=%S\r\n", 
+                    cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->userp, fidp->ioctlp, fidp->flags, fidp->deleteOk,
                     fidp->NTopen_pathp ? fidp->NTopen_pathp : _C("NULL"), 
                     fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : _C("NULL"));
             WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
         }
       
-        sprintf(output, "done dumping smb_fid_t\r\n");
+        sprintf(output, "  done dumping smb_fid_t\r\n");
         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
     }
 
@@ -9794,24 +10959,47 @@ int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
     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\r\n",
-                 cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
+        smb_tid_t *tidp;
+        smb_user_t *userp;
+
+        sprintf(output, "%s vcp=0x%p, refCount=%d, flags=0x%x, vcID=%d, lsn=%d, uidCounter=%d, tidCounter=%d, fidCounter=%d\r\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\r\n");
+        sprintf(output, "  begin dumping smb_user_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        for (userp = vcp->usersp; userp; userp = userp->nextp) {
+            sprintf(output, "  %s -- smb_userp=0x%p, refCount=%d, uid=%d, vcp=0x%p, unp=0x%p, flags=0x%x, delOk=%d\r\n", 
+                    cookie, userp, userp->refCount, userp->userID, userp->vcp, userp->unp, userp->flags, userp->deleteOk);
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+        sprintf(output, "  done dumping smb_user_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+        sprintf(output, "  begin dumping smb_tid_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
+            sprintf(output, "  %s -- smb_tidp=0x%p, refCount=%d, tid=%d, vcp=0x%p, cm_userp=0x%p, flags=0x%x, delOk=%d, path=%S\r\n", 
+                    cookie, tidp, tidp->refCount, tidp->tid, tidp->vcp, tidp->userp, tidp->flags, tidp->deleteOk,
+                    tidp->pathname ? tidp->pathname : _C("NULL"));
+            WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+        }
+        sprintf(output, "  done dumping smb_tid_t\r\n");
+        WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
+
+        sprintf(output, "  begin dumping smb_fid_t\r\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\r\n", 
-                     cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
+            sprintf(output, "  %s -- smb_fidp=0x%p, refCount=%d, fid=%d, vcp=0x%p, scp=0x%p, userp=0x%p, ioctlp=0x%p, flags=0x%x, delOk=%d, NTopen_pathp=%S, NTopen_wholepathp=%S\r\n", 
+                    cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->userp, fidp->ioctlp, fidp->flags, fidp->deleteOk,
                     fidp->NTopen_pathp ? fidp->NTopen_pathp : _C("NULL"), 
                     fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : _C("NULL"));
             WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
         }
       
-        sprintf(output, "done dumping smb_fid_t\r\n");
+        sprintf(output, "  done dumping smb_fid_t\r\n");
         WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
     }