Windows: Make default mode bits configurable
[openafs.git] / src / WINNT / afsd / smb.c
index 76decf3..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);
@@ -196,83 +193,47 @@ void smb_InitReq(cm_req_t *reqp)
     reqp->flags |= CM_REQ_SOURCE_SMB;
 }
 
-void smb_ResetServerPriority()
-{
-    void * p = TlsGetValue(smb_TlsRequestSlot);
-    if (p) {
-       free(p);
-       TlsSetValue(smb_TlsRequestSlot, NULL);
-       SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
-    }
-}
-
-void smb_SetRequestStartTime()
-{
-    time_t * tp = TlsGetValue(smb_TlsRequestSlot);
-    if (!tp)
-       tp = malloc(sizeof(time_t));
-    if (tp) {
-       *tp = osi_Time();
-
-       if (!TlsSetValue(smb_TlsRequestSlot, tp))
-           free(tp);
-    }  
-}
-
-void smb_UpdateServerPriority()
-{      
-    time_t *tp = TlsGetValue(smb_TlsRequestSlot);
-
-    if (tp) {
-       time_t now = osi_Time();
-
-       /* Give one priority boost for each 15 seconds */
-       SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
-    }
-}
-
-
 const char * ncb_error_string(int code)
 {
     const char * s;
     switch ( code ) {
-    case 0x01: s = "llegal buffer length";                     break; 
-    case 0x03: s = "illegal command";                          break; 
-    case 0x05: s = "command timed out";                        break; 
-    case 0x06: s = "message incomplete, issue another command"; break; 
-    case 0x07: s = "illegal buffer address";                   break; 
-    case 0x08: s = "session number out of range";              break; 
-    case 0x09: s = "no resource available";                    break; 
-    case 0x0a: s = "session closed";                           break; 
-    case 0x0b: s = "command cancelled";                        break; 
-    case 0x0d: s = "duplicate name";                           break; 
-    case 0x0e: s = "name table full";                          break; 
-    case 0x0f: s = "no deletions, name has active sessions";   break; 
-    case 0x11: s = "local session table full";                         break; 
-    case 0x12: s = "remote session table full";                break; 
-    case 0x13: s = "illegal name number";                      break; 
-    case 0x14: s = "no callname";                              break; 
-    case 0x15: s = "cannot put * in NCB_NAME";                         break; 
-    case 0x16: s = "name in use on remote adapter";            break; 
-    case 0x17: s = "name deleted";                             break; 
-    case 0x18: s = "session ended abnormally";                         break; 
-    case 0x19: s = "name conflict detected";                   break; 
-    case 0x21: s = "interface busy, IRET before retrying";     break; 
-    case 0x22: s = "too many commands outstanding, retry later";break;
-    case 0x23: s = "ncb_lana_num field invalid";               break; 
-    case 0x24: s = "command completed while cancel occurring "; break; 
-    case 0x26: s = "command not valid to cancel";              break; 
-    case 0x30: s = "name defined by anther local process";     break; 
-    case 0x34: s = "environment undefined. RESET required";    break; 
-    case 0x35: s = "required OS resources exhausted";          break; 
-    case 0x36: s = "max number of applications exceeded";      break; 
-    case 0x37: s = "no saps available for netbios";            break; 
-    case 0x38: s = "requested resources are not available";    break; 
-    case 0x39: s = "invalid ncb address or length > segment";  break; 
-    case 0x3B: s = "invalid NCB DDID";                                 break; 
-    case 0x3C: s = "lock of user area failed";                         break; 
-    case 0x3f: s = "NETBIOS not loaded";                       break; 
-    case 0x40: s = "system error";                             break;                 
+    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;
@@ -462,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)
@@ -487,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 */
@@ -541,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());
@@ -642,181 +660,73 @@ 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
@@ -834,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));
@@ -851,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;
@@ -884,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
@@ -893,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);
@@ -913,7 +827,7 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
     return vcp;
 }
 
-int smb_IsStarMask(clientchar_t *maskp)
+static int smb_Is8Dot3StarMask(clientchar_t *maskp)
 {
     int i;
     clientchar_t tc;
@@ -926,6 +840,18 @@ 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)
@@ -1199,7 +1125,7 @@ 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
@@ -1264,12 +1190,12 @@ void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked)
             free(tidp);
         }
     }
+    if (vcp)
+        smb_ReleaseVCNoLock(vcp);
     if (!locked)
         lock_ReleaseWrite(&smb_rctLock);
     if (userp)
         cm_ReleaseUser(userp);
-    if (vcp)
-        smb_ReleaseVCNoLock(vcp);
 }              
 
 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
@@ -1294,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,
@@ -1325,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;
     }
@@ -1515,27 +1441,35 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
     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,
@@ -1552,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 ) {
@@ -1571,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;
@@ -1595,25 +1535,61 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
     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);
@@ -1621,7 +1597,7 @@ smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
       }
 #endif
     lock_ReleaseWrite(&smb_rctLock);
-    return fidp;
+    return (fidp);
 }
 
 #ifdef DEBUG_SMB_REFCOUNT
@@ -1639,8 +1615,8 @@ void smb_HoldFIDNoLock(smb_fid_t *fidp)
 }
 
 
-/* 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
@@ -1688,17 +1664,22 @@ void smb_ReleaseFID(smb_fid_t *fidp)
                 if (ioctlp->ioctl.outAllocp)
                     free(ioctlp->ioctl.outAllocp);
                 free(ioctlp);
-            }       
+            }
+
+           smb_CleanupRPCFid(fidp);
+
             lock_ReleaseMutex(&fidp->mx);
             lock_FinalizeMutex(&fidp->mx);
             free(fidp);
+            fidp = NULL;
 
             if (vcp)
                 smb_ReleaseVCNoLock(vcp);
-        } else {
-            lock_ReleaseMutex(&fidp->mx);
         }
     }
+    if (fidp)
+        lock_ReleaseMutex(&fidp->mx);
+
     lock_ReleaseWrite(&smb_rctLock);
 
     /* now release the scache structure */
@@ -1760,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;
 
@@ -1824,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
         ) {
@@ -1888,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;
@@ -1953,6 +1937,8 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
         thyper.LowPart = 0;
 
         vrock.shareName = cm_ClientStringToNormStringAlloc(shareName, -1, NULL);
+        if (vrock.shareName == NULL) 
+            return 0;
         vrock.match = NULL;
         vrock.matchType = 0;
 
@@ -1979,13 +1965,13 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
         }
         /* Get the full name for this cell */
         cellname = cm_ClientStringToFsStringAlloc(p, -1, NULL);
-        code = cm_SearchCellFile(cellname, ftemp, 0, 0);
-#ifdef AFS_AFSDB_ENV
+        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);
 
@@ -1993,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;
@@ -2019,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;
@@ -2069,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;
         }
     }
@@ -2087,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);
@@ -2102,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 */
@@ -2110,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) 
@@ -2155,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 */
@@ -2236,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;
         }      
@@ -2248,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) 
@@ -2572,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;
@@ -2593,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);
 }
 
@@ -2629,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,
@@ -2725,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
@@ -2751,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 */
@@ -2761,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;
         }
@@ -2786,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
@@ -2807,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),
@@ -2821,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;
     }
@@ -2831,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;
     }
@@ -2935,7 +2971,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
         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 */
@@ -2980,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 */
@@ -3004,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 */
@@ -3021,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 */
     }
@@ -3045,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
@@ -3054,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) {
@@ -3076,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 */
@@ -3113,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 */
@@ -3132,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 */
     }
 
@@ -3140,24 +3206,202 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus);
 }       
 
-void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
-                      unsigned char *classp)
+/* 
+ * NTSTATUS <-> Win32 Error Translation 
+ * http://support.microsoft.com/kb/113996 
+ */
+void smb_MapWin32Error(long code, unsigned long *Win32Ep)
 {
-    unsigned char class;
-    unsigned short error;
+    unsigned long Win32E;
 
-    /* map CM_ERROR_* errors to SMB errors */
-    if (code == CM_ERROR_NOSUCHCELL) {
-        class = 1;
-        error = 3;     /* bad path */
+    /* 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) {
-        class = 1;
-        error = 3;     /* bad path */
+        Win32E = ERROR_FILE_NOT_FOUND; /* No such file */
     }
     else if (code == CM_ERROR_TIMEDOUT) {
-        class = 2;
-        error = 81;    /* server is paused */
+#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)
+{
+    unsigned char class;
+    unsigned short error;
+
+    /* map CM_ERROR_* errors to SMB errors */
+    if (code == CM_ERROR_NOSUCHCELL) {
+        class = 1;
+        error = 3;     /* bad path */
+    }
+    else if (code == CM_ERROR_NOSUCHVOLUME) {
+        class = 1;
+        error = 3;     /* bad path */
+    }
+    else if (code == CM_ERROR_TIMEDOUT) {
+        class = 2;
+        error = 81;    /* server is paused */
     }
     else if (code == CM_ERROR_RETRY) {
         class = 2;     /* shouldn't happen */
@@ -3387,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;
@@ -3414,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;
     }
 
@@ -3424,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 */
@@ -3462,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;
@@ -3644,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 */
 
@@ -3660,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;
@@ -3704,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 */
 
@@ -3724,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 */
@@ -3751,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 */;
@@ -3777,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);
@@ -3811,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();
@@ -3953,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);
 
@@ -4041,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)
@@ -4053,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;
@@ -4211,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) {
@@ -4269,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)
 {
@@ -4282,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)) {
@@ -4302,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;
+
+            /* copy out time */
+            shortTemp = (unsigned short) (dosTime & 0xffff);
+            *((u_short *)dptr) = shortTemp;
+            dptr += 2;
 
-        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;
+            /* 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);
     }
         
@@ -4350,6 +4712,7 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
     /* and mark the list as empty */
     *dirPatchespp = NULL;
 
+  cleanup:
     return code;
 }
 
@@ -4408,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)
@@ -4445,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;
@@ -4518,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 */
 
@@ -4532,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);
         }
     }
@@ -4582,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;
 
@@ -4634,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);
@@ -4742,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)",
@@ -4845,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;
@@ -4861,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)
@@ -4924,7 +5284,7 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     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));
         
@@ -4956,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 */
 
@@ -5044,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 */
 
@@ -5078,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;
@@ -5177,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)
@@ -5214,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 */
 
@@ -5231,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);
         
@@ -5309,6 +5655,8 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     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));
 
@@ -5326,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).
@@ -5371,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 */
 
@@ -5395,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;
@@ -5413,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);
@@ -5426,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 */
@@ -5463,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) &&
@@ -5509,11 +5878,14 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     cm_req_t 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));
@@ -5545,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 */
 
@@ -5557,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;
@@ -5597,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));
 
@@ -5611,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)
@@ -5646,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;
@@ -5700,6 +6088,8 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar
     }
 
     smb_InitReq(&req);
+    memset(&rock, 0, sizeof(rock));
+
     spacep = inp->spacep;
     smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
 
@@ -5719,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 */
 
@@ -5742,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 */
 
@@ -5765,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) &&
@@ -5808,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 */
@@ -5840,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;
@@ -5869,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;
 }       
@@ -5929,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 */
 
@@ -5951,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 */
 
@@ -6048,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);
@@ -6081,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
@@ -6118,9 +6532,12 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     cm_req_t 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);
@@ -6150,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 */
 
@@ -6162,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;
@@ -6186,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",
@@ -6200,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;
 }
@@ -6232,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;
 }
 
@@ -6285,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];
@@ -6344,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;
@@ -6359,26 +6792,25 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
 
     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 */
@@ -6393,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);
@@ -6413,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);
 
@@ -6517,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;
 }
@@ -6548,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;
     }
         
@@ -6594,7 +7030,13 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
         code = CM_ERROR_BADFDOP;
         goto done2;
     }
-    
+
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
+        code = CM_ERROR_BADFD;
+        goto done2;
+    }
+       
     smb_InitReq(&req);
 
     bufferp = NULL;
@@ -6664,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;
@@ -6750,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);
@@ -6825,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)) {
@@ -6843,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);
@@ -6858,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
@@ -6883,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
@@ -6900,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
@@ -6934,12 +7390,17 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char
         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) {
@@ -6949,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) {
@@ -6999,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;
@@ -7018,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);
@@ -7036,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);
 
@@ -7052,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);
@@ -7094,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);
 
@@ -7126,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;
 }
@@ -7143,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);
 
@@ -7202,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;
@@ -7250,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;
@@ -7273,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;
         }
@@ -7297,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);
 
@@ -7341,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);
@@ -7381,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);
@@ -7393,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);
@@ -7409,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);
 
     {
@@ -7423,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;
     }
@@ -7465,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;
 }
 
@@ -7494,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;
@@ -7528,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 */
 
@@ -7550,6 +8088,8 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         
     setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
     setAttr.clientModTime = time(NULL);
+    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,
@@ -7598,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;
@@ -7616,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;
@@ -7652,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 */
 
@@ -7704,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) {
@@ -7806,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);
@@ -7954,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, 
@@ -8311,7 +8914,7 @@ void smb_Server(VOID *parmp)
            vcp = NULL;
        }
 
-       smb_ResetServerPriority();
+       cm_ResetServerPriority();
 
         code = thrd_WaitForMultipleObjects_Event(numNCBs, NCBreturns[myIdx],
                                                  FALSE, INFINITE);
@@ -8498,7 +9101,7 @@ void smb_Server(VOID *parmp)
             continue;
         }
 
-       smb_SetRequestStartTime();
+       cm_SetRequestStartTime();
 
         vcp->errorCount = 0;
         bufp = (struct smb_packet *) ncbp->ncb_buffer;
@@ -8512,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;
@@ -8632,6 +9238,8 @@ 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);
@@ -8666,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;
@@ -8678,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;
@@ -8687,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) {
@@ -8741,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);
@@ -8927,6 +9565,295 @@ exit_thread:
 }
 
 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)
 {
     /* 
@@ -8976,8 +9903,13 @@ 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 = smb_GetNCB();
@@ -8986,11 +9918,15 @@ void smb_LanAdapterChange(int locked) {
             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;
                         }
@@ -9002,7 +9938,6 @@ void smb_LanAdapterChange(int locked) {
     } 
 
     if (change) {
-        afsi_log("Lan Adapter Change detected");
         smb_StopListeners(1);
         smb_RestartListeners(1);
     }
@@ -9212,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
@@ -9261,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 */
@@ -9273,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)
@@ -9334,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;
@@ -9356,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();
@@ -9369,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);
@@ -9590,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 */
@@ -9709,7 +10646,7 @@ void smb_Shutdown(void)
     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])
@@ -9747,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;
@@ -9757,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);
@@ -9779,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;
@@ -9790,6 +10728,7 @@ void smb_Shutdown(void)
                     cm_ReleaseSCache(scp);
                 }
                 lock_ReleaseMutex(&fidp->mx);
+                lock_ObtainWrite(&smb_rctLock);
             }
         }
 
@@ -9805,14 +10744,13 @@ void smb_Shutdown(void)
     }
     lock_ReleaseWrite(&smb_rctLock);
     smb_FreeNCB(ncbp);
-    TlsFree(smb_TlsRequestSlot);
 }
 
 /* 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)
@@ -9896,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);
     }
 
@@ -9939,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);
     }