windows-smb-dumpvars-20080801
[openafs.git] / src / WINNT / afsd / smb.c
index ca9f514..6e95e68 100644 (file)
 #include "smb.h"
 #include "lanahelper.h"
 
+#define STRSAFE_NO_DEPRECATE
+#include <strsafe.h>
+
 /* These characters are illegal in Windows filenames */
-static char *illegalChars = "\\/:*?\"<>|";
+static clientchar_t *illegalChars = _C("\\/:*?\"<>|");
 
 static int smbShutdownFlag = 0;
 static int smb_ListenerState = SMB_LISTENER_UNINITIALIZED;
@@ -60,10 +63,12 @@ osi_rwlock_t smb_globalLock;
 osi_rwlock_t smb_rctLock;
 osi_mutex_t  smb_ListenerLock;
 osi_mutex_t  smb_StartedLock;
+
 unsigned char smb_LANadapter = LANA_INVALID;
 unsigned char smb_sharename[NCBNAMSZ+1] = {0};
 int  smb_LanAdapterChangeDetected = 0;
+afs_uint32    smb_AsyncStore = 1;
+afs_uint32    smb_AsyncStoreSize = CM_CONFIGDEFAULT_ASYNCSTORESIZE;
 
 BOOL isGateway = FALSE;
 
@@ -76,9 +81,9 @@ smb_dispatch_t smb_dispatchTable[SMB_NOPCODES];
 smb_packet_t *smb_packetFreeListp;
 smb_ncb_t *smb_ncbFreeListp;
 
-int smb_NumServerThreads;
+afs_uint32 smb_NumServerThreads;
 
-int numNCBs, numSessions, numVCs;
+afs_uint32 numNCBs, numSessions, numVCs;
 
 int smb_maxVCPerServer;
 int smb_maxMpxRequests;
@@ -115,12 +120,12 @@ char *smb_RawBufs;
 
 /* for raw write */
 typedef struct raw_write_cont {
-       long code;
-       osi_hyper_t offset;
-       long count;
-       char *buf;
-       int writeMode;
-       long alreadyWritten;
+    long code;
+    osi_hyper_t offset;
+    long count;
+    char *buf;
+    int writeMode;
+    long alreadyWritten;
 } raw_write_cont_t;
 
 /* dir search stuff */
@@ -131,12 +136,16 @@ smb_dirSearch_t *smb_lastDirSearchp;
 /* hide dot files? */
 int smb_hideDotFiles;
 
+/* Negotiate Unicode support? */
+LONG smb_UseUnicode;
+
 /* global state about V3 protocols */
 int smb_useV3;         /* try to negotiate V3 */
 
-static showErrors = 0;
+static int showErrors = 0;
 /* MessageBox or something like it */
-int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT)
+= NULL;
 
 /* GMT time info:
  * Time in Unix format of midnight, 1/1/1970 local time.
@@ -170,17 +179,23 @@ int smb_NetbiosInit(int);
 #ifdef LOG_PACKET
 void smb_LogPacket(smb_packet_t *packet);
 #endif /* LOG_PACKET */
-
-char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
+                                                         
+clientchar_t smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = _C(""); /* domain name */
 int smb_ServerDomainNameLength = 0;
-char smb_ServerOS[] = "Windows 5.0"; /* Faux OS String */
-int smb_ServerOSLength = sizeof(smb_ServerOS);
-char smb_ServerLanManager[] = "Windows 2000 LAN Manager"; /* Faux LAN Manager string */
-int smb_ServerLanManagerLength = sizeof(smb_ServerLanManager);
+clientchar_t smb_ServerOS[] = _C("Windows 5.0"); /* Faux OS String */
+int smb_ServerOSLength = lengthof(smb_ServerOS);
+clientchar_t smb_ServerLanManager[] = _C("Windows 2000 LAN Manager"); /* Faux LAN Manager string */
+int smb_ServerLanManagerLength = lengthof(smb_ServerLanManager);
 
 /* Faux server GUID. This is never checked. */
 GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
 
+void smb_InitReq(cm_req_t *reqp)
+{
+    cm_InitReq(reqp);
+    reqp->flags |= CM_REQ_SOURCE_SMB;
+}
+
 void smb_ResetServerPriority()
 {
     void * p = TlsGetValue(smb_TlsRequestSlot);
@@ -212,7 +227,7 @@ void smb_UpdateServerPriority()
        time_t now = osi_Time();
 
        /* Give one priority boost for each 15 seconds */
-       SetThreadPriority(GetCurrentThread(), (now - *tp) / 15);
+       SetThreadPriority(GetCurrentThread(), (int)((now - *tp) / 15));
     }
 }
 
@@ -485,8 +500,9 @@ unsigned int smb_Attributes(cm_scache_t *scp)
 /* 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 */
-unsigned int smb_IsDotFile(char *lastComp) {
-    char *s;
+unsigned int smb_IsDotFile(clientchar_t *lastComp) {
+    clientchar_t *s;
+
     if(lastComp) {
         /* skip over slashes */
         for(s=lastComp;*s && (*s == '\\' || *s == '/'); s++);
@@ -495,12 +511,12 @@ unsigned int smb_IsDotFile(char *lastComp) {
         return 0;
 
     /* nulls, curdir and parent dir doesn't count */
-    if (!*s) 
+    if (!*s)
         return 0;
-    if (*s == '.') {
+    if (*s == _C('.')) {
         if (!*(s + 1)) 
             return 0;
-        if(*(s+1) == '.' && !*(s + 2)) 
+        if(*(s+1) == _C('.') && !*(s + 2)) 
             return 0;
         return 1;
     }
@@ -803,11 +819,15 @@ void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
     *unixTimep = dosTime + smb_localZero;
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+smb_vc_t *smb_FindVCDbg(unsigned short lsn, int flags, int lana, char *file, long line)
+#else
 smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
+#endif
 {
     smb_vc_t *vcp;
 
-       lock_ObtainWrite(&smb_globalLock);      /* for numVCs */
+    lock_ObtainWrite(&smb_globalLock); /* for numVCs */
     lock_ObtainWrite(&smb_rctLock);
     for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
        if (vcp->magic != SMB_VC_MAGIC)
@@ -882,71 +902,127 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
             osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
         }
     }
+#ifdef DEBUG_SMB_REFCOUNT
+    if (vcp) {
+        afsi_log("%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_FindVC vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+    }
+#endif
     lock_ReleaseWrite(&smb_rctLock);
-       lock_ReleaseWrite(&smb_globalLock);
+    lock_ReleaseWrite(&smb_globalLock);
     return vcp;
 }
 
-int smb_IsStarMask(char *maskp)
+int smb_IsStarMask(clientchar_t *maskp)
 {
     int i;
-    char tc;
+    clientchar_t tc;
         
     for(i=0; i<11; i++) {
         tc = *maskp++;
-        if (tc == '?' || tc == '*' || tc == '>')
+        if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
            return 1;
-    }  
+    }
     return 0;
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCInternalDbg(smb_vc_t *vcp, char * file, long line)
+#define smb_ReleaseVCInternal(a) smb_ReleaseVCInternalDbg(a, file, line)
+#else
 void smb_ReleaseVCInternal(smb_vc_t *vcp)
+#endif
 {
     smb_vc_t **vcpp;
     smb_vc_t * avcp;
 
+    lock_AssertWrite(&smb_rctLock);
     vcp->refCount--;
 
     if (vcp->refCount == 0) {
-      if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
-       /* remove VCP from smb_deadVCsp */
-       for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
-         if (*vcpp == vcp) {
-           *vcpp = vcp->nextp;
-           break;
-         }
-       } 
-       lock_FinalizeMutex(&vcp->mx);
-       memset(vcp,0,sizeof(smb_vc_t));
-       free(vcp);
-      } else {
-       for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
-         if (avcp == vcp)
-           break;
-       }
-       osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
-                avcp?"not ":"",vcp, vcp->refCount);
-#ifdef DEBUG
-       GenerateMiniDump(NULL);
+        if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+#ifdef DEBUG_SMB_REFCOUNT
+            afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
+            osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is dead ref %d", file, line, vcp, vcp->refCount);
+#endif
+            /* remove VCP from smb_deadVCsp */
+            for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
+                if (*vcpp == vcp) {
+                    *vcpp = vcp->nextp;
+                    break;
+                }
+            } 
+            lock_FinalizeMutex(&vcp->mx);
+            memset(vcp,0,sizeof(smb_vc_t));
+            free(vcp);
+        } else {
+#ifdef DEBUG_SMB_REFCOUNT
+            afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is alive ref %d", file, line, vcp, vcp->refCount);
+#endif
+            for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
+                if (avcp == vcp)
+                    break;
+            }
+            osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
+                      avcp?"":"not ",vcp, vcp->refCount);
+
+            /* This is a wrong.  However, I suspect that there is an undercount
+             * and I don't want to release 1.4.1 in a state that will allow
+             * smb_vc_t objects to be deallocated while still in the
+             * smb_allVCsp list.  The list is supposed to keep a reference
+             * to the smb_vc_t.  Put it back.
+             */
+            if (avcp) {
+                vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+                afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
+                osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p is in smb_allVCsp ref %d", file, line, vcp, vcp->refCount);
+#endif
+            }
+        }
+    } else if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+        /* The reference count is non-zero but the VC is dead.
+         * This implies that some FIDs, TIDs, etc on the VC have yet to 
+         * be cleaned up.  If we were not called by smb_CleanupDeadVC(),
+         * add a reference that will be dropped by
+         * smb_CleanupDeadVC() and try to cleanup the VC again.
+         * Eventually the refCount will drop to zero when all of the
+         * active threads working with the VC end their task.
+         */
+        if (!(vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS)) {
+            vcp->refCount++;        /* put the refCount back */
+            lock_ReleaseWrite(&smb_rctLock);
+            smb_CleanupDeadVC(vcp);
+#ifdef DEBUG_SMB_REFCOUNT
+            afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
+            osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p after CleanupDeadVC ref %d", file, line, vcp, vcp->refCount);
+#endif
+            lock_ObtainWrite(&smb_rctLock);
+        }
+    } else {
+#ifdef DEBUG_SMB_REFCOUNT
+        afsi_log("%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_ReleaseVCInternal vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
 #endif
-       /* This is a wrong.  However, I suspect that there is an undercount
-        * and I don't want to release 1.4.1 in a state that will allow
-        * smb_vc_t objects to be deallocated while still in the
-        * smb_allVCsp list.  The list is supposed to keep a reference
-        * to the smb_vc_t.  Put it back.
-        */
-       vcp->refCount++;
-      }
     }
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
+#else
 void smb_ReleaseVCNoLock(smb_vc_t *vcp)
+#endif
 {
+    lock_AssertWrite(&smb_rctLock);
     osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
     smb_ReleaseVCInternal(vcp);
 }       
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseVCDbg(smb_vc_t *vcp, char * file, long line)
+#else
 void smb_ReleaseVC(smb_vc_t *vcp)
+#endif
 {
     lock_ObtainWrite(&smb_rctLock);
     osi_Log2(smb_logp,"smb_ReleaseVC       vcp %x ref %d",vcp, vcp->refCount);
@@ -954,17 +1030,36 @@ void smb_ReleaseVC(smb_vc_t *vcp)
     lock_ReleaseWrite(&smb_rctLock);
 }       
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldVCNoLockDbg(smb_vc_t *vcp, char * file, long line)
+#else
 void smb_HoldVCNoLock(smb_vc_t *vcp)
+#endif
 {
+    lock_AssertWrite(&smb_rctLock);
     vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+    osi_Log4(smb_logp,"%s:%d smb_HoldVCNoLock vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+#else
     osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
+#endif
 }       
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldVCDbg(smb_vc_t *vcp, char * file, long line)
+#else
 void smb_HoldVC(smb_vc_t *vcp)
+#endif
 {
     lock_ObtainWrite(&smb_rctLock);
     vcp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_HoldVC       vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+    osi_Log4(smb_logp,"%s:%d smb_HoldVC       vcp 0x%p ref %d", file, line, vcp, vcp->refCount);
+#else
     osi_Log2(smb_logp,"smb_HoldVC       vcp %x ref %d",vcp, vcp->refCount);
+#endif
     lock_ReleaseWrite(&smb_rctLock);
 }       
 
@@ -979,7 +1074,7 @@ void smb_CleanupDeadVC(smb_vc_t *vcp)
     smb_user_t *uidpIter;
     smb_user_t *uidpNext;
     smb_vc_t **vcpp;
-
+    afs_uint32 refCount = 0;
 
     lock_ObtainMutex(&vcp->mx);
     if (vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS) {
@@ -1009,7 +1104,7 @@ void smb_CleanupDeadVC(smb_vc_t *vcp)
     for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
         fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
 
-        if (fidpIter->delete)
+        if (fidpIter->deleteOk)
             continue;
 
         fid = fidpIter->fid;
@@ -1027,27 +1122,23 @@ void smb_CleanupDeadVC(smb_vc_t *vcp)
 
     for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
        tidpNext = tidpIter->nextp;
-       if (tidpIter->delete)
+       if (tidpIter->deleteOk)
            continue;
-       tidpIter->delete = 1;
+       tidpIter->deleteOk = 1;
 
        tid = tidpIter->tid;
        osi_Log2(smb_logp, "  Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
 
        smb_HoldTIDNoLock(tidpIter);
-       lock_ReleaseWrite(&smb_rctLock);
-
-       smb_ReleaseTID(tidpIter);
-
-       lock_ObtainWrite(&smb_rctLock);
+       smb_ReleaseTID(tidpIter, TRUE);
        tidpNext = vcp->tidsp;
     }
 
     for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
        uidpNext = uidpIter->nextp;
-       if (uidpIter->delete)
+       if (uidpIter->deleteOk)
            continue;
-       uidpIter->delete = 1;
+       uidpIter->deleteOk = 1;
 
        /* do not add an additional reference count for the smb_user_t
         * as the smb_vc_t already is holding a reference */
@@ -1060,32 +1151,45 @@ void smb_CleanupDeadVC(smb_vc_t *vcp)
     }
 
     /* The vcp is now on the deadVCsp list.  We intentionally drop the
-     * reference so that the refcount can reach 0 and we can delete it */
+     * reference so that the refcount can reach 0 and we can delete it 
+     *
+     * If the refCount == 1 going into the ReleaseVCNoLock call 
+     * the object will be freed and it won't be safe to clear 
+     * the flag.
+     */
+    refCount = vcp->refCount;
     smb_ReleaseVCNoLock(vcp);
-    
+    if (refCount > 1) {
+        lock_ObtainMutex(&vcp->mx);
+        vcp->flags &= ~SMB_VCFLAG_CLEAN_IN_PROGRESS;
+        lock_ReleaseMutex(&vcp->mx);
+    }
+
     lock_ReleaseWrite(&smb_rctLock);
     osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+smb_tid_t *smb_FindTIDDbg(smb_vc_t *vcp, unsigned short tid, int flags, char * file, long line)
+#else
 smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
+#endif
 {
     smb_tid_t *tidp;
 
     lock_ObtainWrite(&smb_rctLock);
   retry:
     for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
-       if (tidp->refCount == 0 && tidp->delete) {
+       if (tidp->refCount == 0 && tidp->deleteOk) {
            tidp->refCount++;
-           lock_ReleaseWrite(&smb_rctLock);
-           smb_ReleaseTID(tidp);
-           lock_ObtainWrite(&smb_rctLock);
+           smb_ReleaseTID(tidp, TRUE);
            goto retry;
        }
 
         if (tid == tidp->tid) {
             tidp->refCount++;
             break;
-        }      
+        }
     }
     if (!tidp && (flags & SMB_FLAG_CREATE)) {
         tidp = malloc(sizeof(*tidp));
@@ -1098,41 +1202,74 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
         lock_InitializeMutex(&tidp->mx, "tid_t mutex");
         tidp->tid = tid;
     }
+#ifdef DEBUG_SMB_REFCOUNT
+    if (tidp) {
+        afsi_log("%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_FindTID tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+    }
+#endif
     lock_ReleaseWrite(&smb_rctLock);
     return tidp;
-}              
+}
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldTIDNoLockDbg(smb_tid_t *tidp, char * file, long line)
+#else
 void smb_HoldTIDNoLock(smb_tid_t *tidp)
+#endif
 {
+    lock_AssertWrite(&smb_rctLock);
     tidp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+    osi_Log4(smb_logp,"%s:%d smb_HoldTIDNoLock tidp 0x%p ref %d", file, line, tidp, tidp->refCount);
+#endif
 }
 
-void smb_ReleaseTID(smb_tid_t *tidp)
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseTIDDbg(smb_tid_t *tidp, afs_uint32 locked, char *file, long line)
+#else
+void smb_ReleaseTID(smb_tid_t *tidp, afs_uint32 locked)
+#endif
 {
     smb_tid_t *tp;
     smb_tid_t **ltpp;
-    cm_user_t *userp;
+    cm_user_t *userp = NULL;
+    smb_vc_t  *vcp = NULL;
+
+    if (!locked)
+        lock_ObtainWrite(&smb_rctLock);
+    else
+        lock_AssertWrite(&smb_rctLock);
 
-    userp = NULL;
-    lock_ObtainWrite(&smb_rctLock);
     osi_assertx(tidp->refCount-- > 0, "smb_tid_t refCount 0");
-    if (tidp->refCount == 0 && (tidp->delete)) {
-        ltpp = &tidp->vcp->tidsp;
-        for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
-            if (tp == tidp) 
-                break;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
+    osi_Log5(smb_logp,"%s:%d smb_ReleaseTID tidp 0x%p ref %d deleteOk %d", file, line, tidp, tidp->refCount, tidp->deleteOk);
+#endif
+    if (tidp->refCount == 0) {
+        if (tidp->deleteOk) {
+            ltpp = &tidp->vcp->tidsp;
+            for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
+                if (tp == tidp) 
+                    break;
+            }
+            osi_assertx(tp != NULL, "null smb_tid_t");
+            *ltpp = tp->nextp;
+            lock_FinalizeMutex(&tidp->mx);
+            userp = tidp->userp;       /* remember to drop ref later */
+            tidp->userp = NULL;
+            vcp = tidp->vcp;
+            tidp->vcp = NULL;
+            free(tidp);
         }
-        osi_assertx(tp != NULL, "null smb_tid_t");
-        *ltpp = tp->nextp;
-        lock_FinalizeMutex(&tidp->mx);
-        userp = tidp->userp;   /* remember to drop ref later */
-        tidp->userp = NULL;
-        smb_ReleaseVCNoLock(tidp->vcp);
-        tidp->vcp = NULL;
     }
-    lock_ReleaseWrite(&smb_rctLock);
+    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)
@@ -1143,9 +1280,9 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
     for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
         if (uid == uidp->userID) {
             uidp->refCount++;
-            osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%s]",
+            osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%S]",
                     vcp, uidp->userID, 
-                    osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
+                    ((uidp->unp)? osi_LogSaveClientString(smb_logp, uidp->unp->name):_C("")));
             break;
         }
     }
@@ -1159,22 +1296,23 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
         vcp->usersp = uidp;
         lock_InitializeMutex(&uidp->mx, "user_t mutex");
         uidp->userID = uid;
-        osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%s]",
-                vcp, uidp->userID, 
-                osi_LogSaveString(smb_logp,uidp->unp ? uidp->unp->name : ""));
+        osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%S]",
+                vcp, uidp->userID,
+                ((uidp->unp)?osi_LogSaveClientString(smb_logp,uidp->unp->name):_C("")));
     }
     lock_ReleaseWrite(&smb_rctLock);
     return uidp;
 }              
 
-smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
+smb_username_t *smb_FindUserByName(clientchar_t *usern, clientchar_t *machine,
+                                   afs_uint32 flags)
 {
     smb_username_t *unp= NULL;
 
     lock_ObtainWrite(&smb_rctLock);
     for(unp = usernamesp; unp; unp = unp->nextp) {
-        if (stricmp(unp->name, usern) == 0 &&
-             stricmp(unp->machine, machine) == 0) {
+        if (cm_ClientStrCmpI(unp->name, usern) == 0 &&
+            cm_ClientStrCmpI(unp->machine, machine) == 0) {
             unp->refCount++;
             break;
         }
@@ -1184,8 +1322,8 @@ smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
         memset(unp, 0, sizeof(*unp));
         unp->refCount = 1;
         unp->nextp = usernamesp;
-        unp->name = strdup(usern);
-        unp->machine = strdup(machine);
+        unp->name = cm_ClientStrDup(usern);
+        unp->machine = cm_ClientStrDup(machine);
         usernamesp = unp;
         lock_InitializeMutex(&unp->mx, "username_t mutex");
        if (flags & SMB_FLAG_AFSLOGON)
@@ -1196,7 +1334,7 @@ smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
     return unp;
 }      
 
-smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
+smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, clientchar_t *usern)
 {
     smb_user_t *uidp= NULL;
 
@@ -1204,10 +1342,10 @@ smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
     for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
         if (!uidp->unp) 
             continue;
-        if (stricmp(uidp->unp->name, usern) == 0) {
+        if (cm_stricmp_utf16(uidp->unp->name, usern) == 0) {
             uidp->refCount++;
-            osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%s]",
-                    vcp,uidp->userID,osi_LogSaveString(smb_logp,usern));
+            osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%S]",
+                    vcp,uidp->userID,osi_LogSaveClientString(smb_logp,usern));
             break;
         } else
             continue;
@@ -1240,16 +1378,15 @@ void smb_ReleaseUsername(smb_username_t *unp)
        free(unp->name);
        free(unp->machine);
        free(unp);
-    }          
+    }
     lock_ReleaseWrite(&smb_rctLock);
-
-    if (userp) {
+    if (userp)
         cm_ReleaseUser(userp);
-    }  
 }      
 
 void smb_HoldUIDNoLock(smb_user_t *uidp)
 {
+    lock_AssertWrite(&smb_rctLock);
     uidp->refCount++;
 }
 
@@ -1327,7 +1464,7 @@ cm_user_t *smb_GetUserFromVCP(smb_vc_t *vcp, smb_packet_t *inp)
  * Return a pointer to a pathname extracted from a TID structure.  The
  * TID structure is not held; assume it won't go away.
  */
-long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** treepath)
+long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, clientchar_t ** treepath)
 {
     smb_tid_t *tidp;
     long code = 0;
@@ -1341,7 +1478,7 @@ long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** treepath)
             /* tidp->pathname would be NULL, but that's fine */
         }
         *treepath = tidp->pathname;
-       smb_ReleaseTID(tidp);
+       smb_ReleaseTID(tidp, FALSE);
     }
     return code;
 }
@@ -1369,7 +1506,11 @@ int smb_SUser(cm_user_t *userp)
  * If the SMB_FLAG_CREATE flag is set, we allocate a new  
  * smb_fid_t data structure if desired File ID cannot be found.
  */
+#ifdef DEBUG_SMB_REFCOUNT
+smb_fid_t *smb_FindFIDDbg(smb_vc_t *vcp, unsigned short fid, int flags, char *file, long line)
+#else
 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
+#endif
 {
     smb_fid_t *fidp;
     int newFid = 0;
@@ -1386,7 +1527,7 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
 
   retry:
     for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
-       if (fidp->refCount == 0 && fidp->delete) {
+       if (fidp->refCount == 0 && fidp->deleteOk) {
            fidp->refCount++;
            lock_ReleaseWrite(&smb_rctLock);
            smb_ReleaseFID(fidp);
@@ -1444,11 +1585,21 @@ smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
        }
     }
 
+#ifdef DEBUG_SMB_REFCOUNT
+    if (fidp) {
+        afsi_log("%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_FindFID fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+    }
+#endif
     lock_ReleaseWrite(&smb_rctLock);
     return fidp;
 }
 
+#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;
@@ -1463,19 +1614,38 @@ smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
             break;
         }
     }
+#ifdef DEBUG_SMB_REFCOUNT
+    if (fidp) {
+        afsi_log("%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+        osi_Log4(smb_logp,"%s:%d smb_FindFIDByScache fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+      }
+#endif
     lock_ReleaseWrite(&smb_rctLock);
     return fidp;
 }
 
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_HoldFIDNoLockDbg(smb_fid_t *fidp, char *file, long line)
+#else
 void smb_HoldFIDNoLock(smb_fid_t *fidp)
+#endif
 {
+    lock_AssertWrite(&smb_rctLock);
     fidp->refCount++;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+    osi_Log4(smb_logp,"%s:%d smb_HoldFIDNoLock fidp 0x%p ref %d", file, line, fidp, fidp->refCount);
+#endif
 }
 
 
 /* smb_ReleaseFID cannot be called while an cm_scache_t mutex lock is held */
 /* the sm_fid_t->mx and smb_rctLock must not be held */
+#ifdef DEBUG_SMB_REFCOUNT
+void smb_ReleaseFIDDbg(smb_fid_t *fidp, char *file, long line)
+#else
 void smb_ReleaseFID(smb_fid_t *fidp)
+#endif
 {
     cm_scache_t *scp = NULL;
     cm_user_t *userp = NULL;
@@ -1485,43 +1655,49 @@ void smb_ReleaseFID(smb_fid_t *fidp)
     lock_ObtainMutex(&fidp->mx);
     lock_ObtainWrite(&smb_rctLock);
     osi_assertx(fidp->refCount-- > 0, "smb_fid_t refCount 0");
-    if (fidp->refCount == 0 && (fidp->delete)) {
-        vcp = fidp->vcp;
-        fidp->vcp = NULL;
-        scp = fidp->scp;    /* release after lock is released */
-       if (scp) {
-           lock_ObtainMutex(&scp->mx);
-           scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
-           lock_ReleaseMutex(&scp->mx);
-           osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
-           fidp->scp = NULL;
-       }
-        userp = fidp->userp;
-        fidp->userp = NULL;
+#ifdef DEBUG_SMB_REFCOUNT
+    afsi_log("%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
+    osi_Log5(smb_logp,"%s:%d smb_ReleaseFID fidp 0x%p ref %d deleteOk %d", file, line, fidp, fidp->refCount, fidp->deleteOk);
+#endif
+    if (fidp->refCount == 0) {
+        if (fidp->deleteOk) {
+            vcp = fidp->vcp;
+            fidp->vcp = NULL;
+            scp = fidp->scp;    /* release after lock is released */
+            if (scp) {
+                lock_ObtainWrite(&scp->rw);
+                scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
+                lock_ReleaseWrite(&scp->rw);
+                osi_Log2(smb_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
+                fidp->scp = NULL;
+            }
+            userp = fidp->userp;
+            fidp->userp = NULL;
 
-       if (vcp->fidsp) 
-           osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
-        thrd_CloseHandle(fidp->raw_write_event);
+            if (vcp->fidsp) 
+                osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
+            thrd_CloseHandle(fidp->raw_write_event);
 
-        /* and see if there is ioctl stuff to free */
-        ioctlp = fidp->ioctlp;
-        if (ioctlp) {
-            if (ioctlp->prefix)
+            /* and see if there is ioctl stuff to free */
+            ioctlp = fidp->ioctlp;
+            if (ioctlp) {
+                if (ioctlp->prefix)
                 cm_FreeSpace(ioctlp->prefix);
-            if (ioctlp->inAllocp)
-                free(ioctlp->inAllocp);
-            if (ioctlp->outAllocp)
-                free(ioctlp->outAllocp);
-            free(ioctlp);
-        }       
-       lock_ReleaseMutex(&fidp->mx);
-       lock_FinalizeMutex(&fidp->mx);
-        free(fidp);
-
-       if (vcp)
-           smb_ReleaseVCNoLock(vcp);
-    } else {
-       lock_ReleaseMutex(&fidp->mx);
+                if (ioctlp->ioctl.inAllocp)
+                    free(ioctlp->ioctl.inAllocp);
+                if (ioctlp->ioctl.outAllocp)
+                    free(ioctlp->ioctl.outAllocp);
+                free(ioctlp);
+            }       
+            lock_ReleaseMutex(&fidp->mx);
+            lock_FinalizeMutex(&fidp->mx);
+            free(fidp);
+
+            if (vcp)
+                smb_ReleaseVCNoLock(vcp);
+        } else {
+            lock_ReleaseMutex(&fidp->mx);
+        }
     }
     lock_ReleaseWrite(&smb_rctLock);
 
@@ -1537,12 +1713,12 @@ void smb_ReleaseFID(smb_fid_t *fidp)
  * Case-insensitive search for one string in another;
  * used to find variable names in submount pathnames.
  */
-static char *smb_stristr(char *str1, char *str2)
+static clientchar_t *smb_stristr(clientchar_t *str1, clientchar_t *str2)
 {
-    char *cursor;
+    clientchar_t *cursor;
 
     for (cursor = str1; *cursor; cursor++)
-        if (stricmp(cursor, str2) == 0)
+        if (cm_ClientStrCmpI(cursor, str2) == 0)
             return cursor;
 
     return NULL;
@@ -1553,25 +1729,24 @@ static char *smb_stristr(char *str1, char *str2)
  * name has been identified by smb_stristr() and is in substr.  Variable name
  * length (plus one) is in substr_size.  Variable value is in newstr.
  */
-static void smb_subst(char *str1, char *substr, unsigned int substr_size,
-                      char *newstr)
+static void smb_subst(clientchar_t *str1, int cchstr1, clientchar_t *substr,
+                      unsigned int substr_size, clientchar_t *newstr)
 {
-    char temp[1024];
+    clientchar_t temp[1024];
 
-    strcpy(temp, substr + substr_size - 1);
-    strcpy(substr, newstr);
-    strcat(str1, temp);
-}       
-
-char VNUserName[] = "%USERNAME%";
-char VNLCUserName[] = "%LCUSERNAME%";
-char VNComputerName[] = "%COMPUTERNAME%";
-char VNLCComputerName[] = "%LCCOMPUTERNAME%";
+    cm_ClientStrCpy(temp, lengthof(temp), substr + substr_size - 1);
+    cm_ClientStrCpy(substr, cchstr1 - (substr - str1), newstr);
+    cm_ClientStrCat(str1, cchstr1, temp);
+}
 
+clientchar_t VNUserName[] = _C("%USERNAME%");
+clientchar_t VNLCUserName[] = _C("%LCUSERNAME%");
+clientchar_t VNComputerName[] = _C("%COMPUTERNAME%");
+clientchar_t VNLCComputerName[] = _C("%LCCOMPUTERNAME%");
 
 typedef struct smb_findShare_rock {
-    char * shareName;
-    char * match;
+    clientchar_t * shareName;
+    clientchar_t * match;
     int matchType;
 } smb_findShare_rock_t;
 
@@ -1583,13 +1758,17 @@ long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
 {
     int matchType = 0;
     smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
-    if (!strnicmp(dep->name, vrock->shareName, 12)) {
-        if(!stricmp(dep->name, vrock->shareName))
+    normchar_t normName[MAX_PATH];
+
+    cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[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);
-        vrock->match = strdup(dep->name);
+        vrock->match = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
         vrock->matchType = matchType;
 
         if(matchType == SMB_FINDSHARE_EXACT_MATCH)
@@ -1600,15 +1779,17 @@ long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
 
 
 /* find a shareName in the table of submounts */
-int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
-       char **pathNamep)
-{
-    DWORD len;
-    char pathName[1024];
-    char *var;
-    char temp[1024];
+int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp,
+                  clientchar_t *shareName,
+                  clientchar_t **pathNamep)
+{
+    DWORD cblen;
+    DWORD cchlen;
+    clientchar_t pathName[1024];
+    clientchar_t *var;
     DWORD sizeTemp;
-    char *p, *q;
+    clientchar_t *p, *q;
+    fschar_t *cellname = NULL;
     HKEY parmKey;
     DWORD code;
     DWORD allSubmount = 1;
@@ -1619,18 +1800,18 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
      * world to do so.
      */
     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
-                         0, KEY_QUERY_VALUE, &parmKey);
+                        0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
-        len = sizeof(allSubmount);
+        cblen = sizeof(allSubmount);
         code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
-                                (BYTE *) &allSubmount, &len);
+                               (BYTE *) &allSubmount, &cblen);
         if (code != ERROR_SUCCESS) {
             allSubmount = 1;
         }
         RegCloseKey (parmKey);
     }
 
-    if (allSubmount && _stricmp(shareName, "all") == 0) {
+    if (allSubmount && cm_ClientStrCmpI(shareName, _C("all")) == 0) {
         *pathNamep = NULL;
         return 1;
     }
@@ -1638,15 +1819,17 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
     /* In case, the all share is disabled we need to still be able
      * to handle ioctl requests 
      */
-    if (_stricmp(shareName, "ioctl$") == 0) {
-        *pathNamep = strdup("/.__ioctl__");
+    if (cm_ClientStrCmpI(shareName, _C("ioctl$")) == 0) {
+        *pathNamep = cm_ClientStrDup(_C("/.__ioctl__"));
         return 1;
     }
 
-    if (_stricmp(shareName, "IPC$") == 0 ||
-        _stricmp(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
-        _stricmp(shareName, "DESKTOP.INI") == 0
-         ) {
+    if (cm_ClientStrCmpIA(shareName, _C("IPC$")) == 0 ||
+        cm_ClientStrCmpIA(shareName, _C("srvsvc")) == 0 ||
+        cm_ClientStrCmpIA(shareName, _C("wkssvc")) == 0 ||
+        cm_ClientStrCmpIA(shareName, _C(SMB_IOCTL_FILENAME_NOSLASH)) == 0 ||
+        cm_ClientStrCmpIA(shareName, _C("DESKTOP.INI")) == 0
+        ) {
         *pathNamep = NULL;
         return 0;
     }
@@ -1655,25 +1838,24 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
      * 
      * They look like <cell>{%,#}<volume>
      */
-    if (strchr(shareName, '%') != NULL ||
-        strchr(shareName, '#') != NULL) {
-        char pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH];
-                                /* make room for '/@vol:' + mountchar + NULL terminator*/
+    if (cm_ClientStrChr(shareName, '%') != NULL ||
+        cm_ClientStrChr(shareName, '#') != NULL) {
+        clientchar_t pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH];
+        /* make room for '/@vol:' + mountchar + NULL terminator*/
 
-        osi_Log1(smb_logp, "smb_FindShare found volume reference [%s]",
-                 osi_LogSaveString(smb_logp, shareName));
+        osi_Log1(smb_logp, "smb_FindShare found volume reference [%S]",
+                 osi_LogSaveClientString(smb_logp, shareName));
 
-        snprintf(pathstr, sizeof(pathstr)/sizeof(char),
-                 "/" CM_PREFIX_VOL "%s", shareName);
-        pathstr[sizeof(pathstr)/sizeof(char) - 1] = '\0';
-        len = strlen(pathstr) + 1;
+        cm_ClientStrPrintfN(pathstr, lengthof(pathstr),
+                            _C("/") _C(CM_PREFIX_VOL) _C("%s"), shareName);
+        cchlen = (DWORD)(cm_ClientStrLen(pathstr) + 1);
 
-        *pathNamep = malloc(len);
+        *pathNamep = malloc(cchlen * sizeof(clientchar_t));
         if (*pathNamep) {
-            strcpy(*pathNamep, pathstr);
-            strlwr(*pathNamep);
-            osi_Log1(smb_logp, "   returning pathname [%s]",
-                     osi_LogSaveString(smb_logp, *pathNamep));
+            cm_ClientStrCpy(*pathNamep, cchlen, pathstr);
+            cm_ClientStrLwr(*pathNamep);
+            osi_Log1(smb_logp, "   returning pathname [%S]",
+                     osi_LogSaveClientString(smb_logp, *pathNamep));
 
             return 1;
         } else {
@@ -1682,64 +1864,75 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
     }
 
     code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
-                         0, KEY_QUERY_VALUE, &parmKey);
+                        0, KEY_QUERY_VALUE, &parmKey);
     if (code == ERROR_SUCCESS) {
-        len = sizeof(pathName);
-        code = RegQueryValueEx(parmKey, shareName, NULL, NULL,
-                                (BYTE *) pathName, &len);
+        cblen = sizeof(pathName);
+        code = RegQueryValueExW(parmKey, shareName, NULL, NULL,
+                                (BYTE *) pathName, &cblen);
         if (code != ERROR_SUCCESS)
-            len = 0;
+            cblen = 0;
         RegCloseKey (parmKey);
     } else {
-        len = 0;
-    }   
-    if (len != 0 && len != sizeof(pathName) - 1) {
+        cblen = 0;
+    }
+    cchlen = cblen / sizeof(clientchar_t);
+    if (cchlen != 0 && cchlen != lengthof(pathName) - 1) {
         /* We can accept either unix or PC style AFS pathnames.  Convert
          * Unix-style to PC style here for internal use. 
          */
         p = pathName;
-        if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) == 0)
-            p += strlen(cm_mountRoot);  /* skip mount path */
+        cchlen = lengthof(pathName);
+
+        /* within this code block, we maintain, cchlen = writeable
+           buffer length of p */
+
+        if (cm_ClientStrCmpN(p, cm_mountRootC, cm_mountRootCLen) == 0) {
+            p += cm_mountRootCLen;  /* skip mount path */
+            cchlen -= (DWORD)(p - pathName);
+        }
+
         q = p;
         while (*q) {
-            if (*q == '/') *q = '\\';    /* change to \ */
+            if (*q == _C('/')) *q = _C('\\');    /* change to \ */
             q++;
         }
 
         while (1)
         {
+            clientchar_t temp[1024];
+
             if (var = smb_stristr(p, VNUserName)) {
                 if (uidp && uidp->unp)
-                    smb_subst(p, var, sizeof(VNUserName),uidp->unp->name);
+                    smb_subst(p, cchlen, var, lengthof(VNUserName),uidp->unp->name);
                 else
-                    smb_subst(p, var, sizeof(VNUserName)," ");
+                    smb_subst(p, cchlen, var, lengthof(VNUserName), _C(" "));
             }
             else if (var = smb_stristr(p, VNLCUserName)) 
             {
                 if (uidp && uidp->unp)
-                    strcpy(temp, uidp->unp->name);
+                    cm_ClientStrCpy(temp, lengthof(temp), uidp->unp->name);
                 else 
-                    strcpy(temp, " ");
-                _strlwr(temp);
-                smb_subst(p, var, sizeof(VNLCUserName), temp);
+                    cm_ClientStrCpy(temp, lengthof(temp), _C(" "));
+                cm_ClientStrLwr(temp);
+                smb_subst(p, cchlen, var, lengthof(VNLCUserName), temp);
             }
             else if (var = smb_stristr(p, VNComputerName)) 
             {
-                sizeTemp = sizeof(temp);
-                GetComputerName((LPTSTR)temp, &sizeTemp);
-                smb_subst(p, var, sizeof(VNComputerName), temp);
+                sizeTemp = lengthof(temp);
+                GetComputerNameW(temp, &sizeTemp);
+                smb_subst(p, cchlen, var, lengthof(VNComputerName), temp);
             }
             else if (var = smb_stristr(p, VNLCComputerName)) 
             {
-                sizeTemp = sizeof(temp);
+                sizeTemp = lengthof(temp);
                 GetComputerName((LPTSTR)temp, &sizeTemp);
-                _strlwr(temp);
-                smb_subst(p, var, sizeof(VNLCComputerName), temp);
+                cm_ClientStrLwr(temp);
+                smb_subst(p, cchlen, var, lengthof(VNLCComputerName), temp);
             }
             else     
                 break;
         }
-        *pathNamep = strdup(p);
+        *pathNamep = cm_ClientStrDup(p);
         return 1;
     } 
     else
@@ -1748,28 +1941,32 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
         cm_req_t req;
         smb_findShare_rock_t vrock;
         osi_hyper_t thyper;
-        char * p = shareName; 
+        fschar_t ftemp[1024];
+        clientchar_t * p = shareName; 
         int rw = 0;
 
         /*  attempt to locate a partial match in root.afs.  This is because
             when using the ANSI RAP calls, the share name is limited to 13 chars
             and hence is truncated. Of course we prefer exact matches. */
-        cm_InitReq(&req);
+        smb_InitReq(&req);
         thyper.HighPart = 0;
         thyper.LowPart = 0;
 
-        vrock.shareName = shareName;
+        vrock.shareName = cm_ClientStringToNormStringAlloc(shareName, -1, NULL);
         vrock.match = NULL;
         vrock.matchType = 0;
 
         cm_HoldSCache(cm_data.rootSCachep);
         code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
-            (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
+                           (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
         cm_ReleaseSCache(cm_data.rootSCachep);
 
+        free(vrock.shareName);
+        vrock.shareName = NULL;
+
         if (vrock.matchType) {
-            sprintf(pathName,"/%s/",vrock.match);
-            *pathNamep = strdup(strlwr(pathName));
+            cm_ClientStrPrintfN(pathName, lengthof(pathName), _C("/%s/"), vrock.match);
+            *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
             free(vrock.match);
             return 1;
         }
@@ -1781,17 +1978,25 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
             rw = 1;
         }
         /* Get the full name for this cell */
-        code = cm_SearchCellFile(p, temp, 0, 0);
+        cellname = cm_ClientStringToFsStringAlloc(p, -1, NULL);
+        code = cm_SearchCellFile(cellname, ftemp, 0, 0);
 #ifdef AFS_AFSDB_ENV
         if (code && cm_dnsEnabled) {
             int ttl;
-            code = cm_SearchCellByDNS(p, temp, &ttl, 0, 0);
+            code = cm_SearchCellByDNS(cellname, ftemp, &ttl, 0, 0);
         }
 #endif
+        if (cellname)
+            free(cellname);
+
         /* construct the path */
-        if (code == 0) {     
-            sprintf(pathName,rw ? "/.%s/" : "/%s/",temp);
-            *pathNamep = strdup(strlwr(pathName));
+        if (code == 0) {
+            clientchar_t temp[1024];
+
+            cm_FsStringToClientString(ftemp, (int)cm_FsStrLen(ftemp), temp, 1024);
+            cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
+                                rw ? _C("/.%S/") : _C("/%S/"), temp);
+            *pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
             return 1;
         }
     }
@@ -1806,10 +2011,10 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
 #define CSC_POLICY_PROGRAMS 2
 #define CSC_POLICY_DISABLE 3
 
-int smb_FindShareCSCPolicy(char *shareName)
+int smb_FindShareCSCPolicy(clientchar_t *shareName)
 {
     DWORD len;
-    char policy[1024];
+    clientchar_t policy[1024];
     DWORD dwType;
     HKEY hkCSCPolicy;
     int  retval = CSC_POLICY_MANUAL;
@@ -1825,19 +2030,19 @@ int smb_FindShareCSCPolicy(char *shareName)
                     NULL );
 
     len = sizeof(policy);
-    if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) ||
+    if ( RegQueryValueExW( hkCSCPolicy, shareName, 0, &dwType, (LPBYTE) policy, &len ) ||
          len == 0) {
-        retval = stricmp("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
+        retval = cm_ClientStrCmpIA(_C("all"),shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
     }
-    else if (stricmp(policy, "documents") == 0)
+    else if (cm_ClientStrCmpIA(policy, _C("documents")) == 0)
     {
         retval = CSC_POLICY_DOCUMENTS;
     }
-    else if (stricmp(policy, "programs") == 0)
+    else if (cm_ClientStrCmpIA(policy, _C("programs")) == 0)
     {
         retval = CSC_POLICY_PROGRAMS;
     }
-    else if (stricmp(policy, "disable") == 0)
+    else if (cm_ClientStrCmpIA(policy, _C("disable")) == 0)
     {
         retval = CSC_POLICY_DISABLE;
     }
@@ -1888,13 +2093,13 @@ void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
              dsp->cookie, dsp, dsp->scp);
     dsp->flags |= SMB_DIRSEARCH_DELETE;
     if (dsp->scp != NULL) {
-        lock_ObtainMutex(&dsp->scp->mx);
+        lock_ObtainWrite(&dsp->scp->rw);
         if (dsp->flags & SMB_DIRSEARCH_BULKST) {
             dsp->flags &= ~SMB_DIRSEARCH_BULKST;
             dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
             dsp->scp->bulkStatProgress = hzero;
         }      
-        lock_ReleaseMutex(&dsp->scp->mx);
+        lock_ReleaseWrite(&dsp->scp->rw);
     }  
     lock_ReleaseMutex(&dsp->mx);
     lock_ReleaseWrite(&smb_globalLock);
@@ -2057,7 +2262,7 @@ smb_dirSearch_t *smb_NewDirSearch(int isV3)
     return dsp;
 }
 
-static smb_packet_t *GetPacket(void)
+static smb_packet_t *smb_GetPacket(void)
 {
     smb_packet_t *tbp;
 
@@ -2067,7 +2272,7 @@ static smb_packet_t *GetPacket(void)
         smb_packetFreeListp = tbp->nextp;
     lock_ReleaseWrite(&smb_globalLock);
     if (!tbp) {
-        tbp = calloc(65540,1);
+        tbp = calloc(sizeof(*tbp),1);
         tbp->magic = SMB_PACKETMAGIC;
         tbp->ncbp = NULL;
         tbp->vcp = NULL;
@@ -2080,7 +2285,7 @@ static smb_packet_t *GetPacket(void)
         tbp->ncb_length = 0;
         tbp->flags = 0;
         tbp->spacep = NULL;
-        
+        tbp->stringsp = NULL;
     }
     osi_assertx(tbp->magic == SMB_PACKETMAGIC, "invalid smb_packet_t magic");
 
@@ -2090,15 +2295,16 @@ static smb_packet_t *GetPacket(void)
 smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
 {
     smb_packet_t *tbp;
-    tbp = GetPacket();
+    tbp = smb_GetPacket();
     memcpy(tbp, pkt, sizeof(smb_packet_t));
     tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
+    tbp->stringsp = NULL;
     if (tbp->vcp)
        smb_HoldVC(tbp->vcp);
     return tbp;
 }
 
-static NCB *GetNCB(void)
+static NCB *smb_GetNCB(void)
 {
     smb_ncb_t *tbp;
     NCB *ncbp;
@@ -2120,6 +2326,18 @@ static NCB *GetNCB(void)
     return ncbp;
 }
 
+static void FreeSMBStrings(smb_packet_t * pkt)
+{
+    cm_space_t * s;
+    cm_space_t * ns;
+
+    for (s = pkt->stringsp; s; s = ns) {
+        ns = s->nextp;
+        cm_FreeSpace(s);
+    }
+    pkt->stringsp = NULL;
+}
+
 void smb_FreePacket(smb_packet_t *tbp)
 {
     smb_vc_t * vcp = NULL;
@@ -2140,13 +2358,14 @@ void smb_FreePacket(smb_packet_t *tbp)
     tbp->oddByte = 0;
     tbp->ncb_length = 0;
     tbp->flags = 0;
+    FreeSMBStrings(tbp);
     lock_ReleaseWrite(&smb_globalLock);
 
     if (vcp)
         smb_ReleaseVC(vcp);
 }
 
-static void FreeNCB(NCB *bufferp)
+static void smb_FreeNCB(NCB *bufferp)
 {
     smb_ncb_t *tbp;
         
@@ -2290,7 +2509,7 @@ unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
 
 void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
 {
-    char *parmDatap;
+    unsigned char *parmDatap;
 
     /* make sure we have enough slots */
     if (*smbp->wctp <= slot) 
@@ -2303,7 +2522,7 @@ void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
 
 void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
 {
-    char *parmDatap;
+    unsigned char *parmDatap;
 
     /* make sure we have enough slots */
     if (*smbp->wctp <= slot) 
@@ -2318,7 +2537,7 @@ void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
 
 void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
 {
-    char *parmDatap;
+    unsigned char *parmDatap;
     int i;
 
     /* make sure we have enough slots */
@@ -2332,7 +2551,7 @@ void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
 
 void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmValue)
 {
-    char *parmDatap;
+    unsigned char *parmDatap;
 
     /* make sure we have enough slots */
     if (*smbp->wctp <= slot) {
@@ -2347,11 +2566,14 @@ void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmValue)
     *parmDatap++ = parmValue & 0xff;
 }
 
-void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp)
+
+
+void smb_StripLastComponent(clientchar_t *outPathp, clientchar_t **lastComponentp,
+                            clientchar_t *inPathp)
 {
-    char *lastSlashp;
+    clientchar_t *lastSlashp;
         
-    lastSlashp = strrchr(inPathp, '\\');
+    lastSlashp = cm_ClientStrRChr(inPathp, '\\');
     if (lastComponentp)
         *lastComponentp = lastSlashp;
     if (lastSlashp) {
@@ -2367,14 +2589,255 @@ void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp
     }
 }
 
-unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp)
+clientchar_t *smb_ParseASCIIBlock(smb_packet_t * pktp, unsigned char *inp,
+                                  char **chainpp, int flags)
 {
+    size_t cb;
+
     if (*inp++ != 0x4) 
         return NULL;
-    if (chainpp) {
-        *chainpp = inp + strlen(inp) + 1;      /* skip over null-terminated string */
+
+#ifdef SMB_UNICODE
+    if (!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);
+}
+
+clientchar_t *smb_ParseString(smb_packet_t * pktp, unsigned char * inp,
+                              char ** chainpp, int flags)
+{
+    size_t cb;
+
+#ifdef SMB_UNICODE
+    if (!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);
+}
+
+clientchar_t *smb_ParseStringCb(smb_packet_t * pktp, unsigned char * inp,
+                                size_t cb, char ** chainpp, int flags)
+{
+#ifdef SMB_UNICODE
+    if (!WANTS_UNICODE(pktp))
+        flags |= SMB_STRF_FORCEASCII;
+#endif
+
+    return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+clientchar_t *smb_ParseStringCch(smb_packet_t * pktp, unsigned char * inp,
+                                 size_t cch, char ** chainpp, int flags)
+{
+    size_t cb = cch;
+
+#ifdef SMB_UNICODE
+    if (!WANTS_UNICODE(pktp))
+        flags |= SMB_STRF_FORCEASCII;
+    else
+        cb = cch * sizeof(wchar_t);
+#endif
+
+    return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
+}
+
+clientchar_t *
+smb_ParseStringBuf(const unsigned char * bufbase,
+                   cm_space_t ** stringspp,
+                   unsigned char *inp, size_t *pcb_max,
+                   char **chainpp, int flags)
+{
+#ifdef SMB_UNICODE
+    if (!(flags & SMB_STRF_FORCEASCII)) {
+        size_t cch_src;
+        cm_space_t * spacep;
+        int    null_terms = 0;
+
+        if (bufbase && ((inp - bufbase) % 2) != 0) {
+            inp++;              /* unicode strings are always word aligned */
+        }
+
+        if (*pcb_max > 0) {
+            if (FAILED(StringCchLengthW((const wchar_t *) inp, *pcb_max / sizeof(wchar_t),
+                                        &cch_src))) {
+                cch_src = *pcb_max / sizeof(wchar_t);
+                *pcb_max = 0;
+                null_terms = 0;
+            } else {
+                *pcb_max -= (cch_src + 1) * sizeof(wchar_t);
+                null_terms = 1;
+            }
+        } else {
+            cch_src = 0;
+        }
+
+        spacep = cm_GetSpace();
+        spacep->nextp = *stringspp;
+        *stringspp = spacep;
+
+        if (cch_src == 0) {
+            if (chainpp) {
+                *chainpp = inp + sizeof(wchar_t);
+            }
+
+            *(spacep->wdata) = 0;
+            return spacep->wdata;
+        }
+
+        StringCchCopyNW(spacep->wdata,
+                        lengthof(spacep->wdata),
+                        (const clientchar_t *) inp, cch_src);
+
+        if (chainpp)
+            *chainpp = inp + (cch_src + null_terms)*sizeof(wchar_t);
+
+        return spacep->wdata;
+
+    } else {
+#endif
+        cm_space_t * spacep;
+        int cchdest;
+
+        /* Not using Unicode */
+        if (chainpp) {
+            *chainpp = inp + strlen(inp) + 1;
+        }
+
+        spacep = cm_GetSpace();
+        spacep->nextp = *stringspp;
+        *stringspp = spacep;
+
+        cchdest = lengthof(spacep->wdata);
+        cm_Utf8ToUtf16(inp, (int)*pcb_max, spacep->wdata, cchdest);
+
+        return spacep->wdata;
+#ifdef SMB_UNICODE
+    }
+#endif
+}
+
+unsigned char * smb_UnparseString(smb_packet_t * pktp, unsigned char * outp,
+                            clientchar_t * str,
+                            size_t * plen, int flags)
+{
+    size_t buffersize;
+    int align = 0;
+
+    if (outp == NULL) {
+        /* we are only calculating the required size */
+
+        if (plen == NULL)
+            return NULL;
+
+#ifdef SMB_UNICODE
+
+        if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
+
+            StringCbLengthW(str, SMB_STRINGBUFSIZE * sizeof(wchar_t), plen);
+            if (!(flags & SMB_STRF_IGNORENULL))
+                *plen += sizeof(wchar_t);
+
+            return (unsigned char *) 1; /* return TRUE if we are using unicode */
+        }
+        else
+#endif
+        {
+            /* Storing ANSI */
+
+            size_t cch_str;
+            size_t cch_dest;
+
+            cch_str = cm_ClientStrLen(str);
+            cch_dest = cm_ClientStringToUtf8(str, (int)cch_str, NULL, 0);
+
+            if (plen)
+                *plen = ((flags & SMB_STRF_IGNORENULL)? cch_dest: cch_dest+1);
+
+            return NULL;
+        }
+
+        /* Not reached. */
+    }
+
+    /* if outp != NULL ... */
+
+    /* Number of bytes left in the buffer.
+
+       If outp lies inside the packet data buffer, we assume that the
+       buffer is the packet data buffer.  Otherwise we assume that the
+       buffer is sizeof(packet->data).
+
+    */
+    if (outp >= pktp->data && outp < pktp->data + sizeof(pktp->data)) {
+        align = (int)((outp - pktp->data) % 2);
+        buffersize = (pktp->data + sizeof(pktp->data)) - ((char *) outp);
+    } else {
+        align = (int)(((size_t) outp) % 2);
+        buffersize = (int)sizeof(pktp->data);
+    }
+
+#ifdef SMB_UNICODE
+
+    if (WANTS_UNICODE(pktp) && !(flags & SMB_STRF_FORCEASCII)) {
+        int nchars;
+
+        if (align)
+            *outp++ = '\0';
+
+        if (*str == _C('\0')) {
+
+            if (buffersize < sizeof(wchar_t))
+                return NULL;
+
+            *((wchar_t *) outp) = L'\0';
+            if (plen && !(flags & SMB_STRF_IGNORENULL))
+                *plen += sizeof(wchar_t);
+            return outp + 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),
+                     GetLastError());
+            return NULL;
+        }
+
+        if (plen)
+            *plen += sizeof(wchar_t) * ((flags & SMB_STRF_IGNORENULL)? nchars - 1: nchars);
+
+        return outp + sizeof(wchar_t) * nchars;
+    }
+    else
+#endif
+    {
+        /* Storing ANSI */
+        size_t cch_dest;
+
+        cch_dest = cm_ClientStringToUtf8(str, -1, outp, (int)buffersize);
+
+        if (plen)
+            *plen += ((flags & SMB_STRF_IGNORENULL)? cch_dest - 1: cch_dest);
+
+        return outp + cch_dest;
     }
-    return inp;
 }
 
 unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp)
@@ -2396,6 +2859,23 @@ unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *length
     return inp;
 }      
 
+unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
+{
+    int tlen;
+
+    if (*inp++ != 0x1) return NULL;
+    tlen = inp[0] + (inp[1]<<8);
+    inp += 2;          /* skip length field */
+        
+    if (chainpp) {
+        *chainpp = inp + tlen;
+    }  
+
+    if (lengthp) *lengthp = tlen;
+        
+    return inp;
+}
+
 /* format a packet as a response */
 void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op)
 {
@@ -2429,6 +2909,10 @@ void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op
     outp->reb |= SMB_FLAGS_CANONICAL_PATHNAMES;
 #endif
     outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
+#ifdef SMB_UNICODE
+    if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE)
+        outp->flg2 |= SMB_FLAGS2_UNICODE;
+#endif
 
     /* copy fields in generic packet area */
     op->wctp = &outp->wct;
@@ -2447,7 +2931,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
         
     ncbp = inp->ncbp;
     if (ncbp == NULL) {
-        ncbp = GetNCB();
+        ncbp = smb_GetNCB();
         localNCB = 1;
     }
  
@@ -2487,7 +2971,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
     }
 
     if (localNCB)
-        FreeNCB(ncbp);
+        smb_FreeNCB(ncbp);
 }
 
 void smb_MapNTError(long code, unsigned long *NTStatusp)
@@ -2634,11 +3118,20 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
     else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
         NTStatus = 0xC00000BEL; /* Bad Network Path */
     } 
-    else if (code == RXKADUNKNOWNKEY) {
-       NTStatus = 0xC0000322L; /* Bad Kerberos key */
+    else if (code >= ERROR_TABLE_BASE_RXK && code < ERROR_TABLE_BASE_RXK + 256) {
+       NTStatus = 0xC0000322L; /* No Kerberos key */
     } 
     else if (code == CM_ERROR_BAD_LEVEL) {
        NTStatus = 0xC0000148L; /* Invalid Level */
+    } 
+    else if (code == CM_ERROR_RANGE_NOT_LOCKED) {
+       NTStatus = 0xC000007EL; /* Range Not Locked */
+    } 
+    else if (code == CM_ERROR_NOSUCHDEVICE) {
+        NTStatus = 0xC000000EL; /* No Such Device */
+    }
+    else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
+        NTStatus = 0xC0000055L; /* Lock Not Granted */
     } else {
         NTStatus = 0xC0982001L;        /* SMB non-specific error */
     }
@@ -2824,6 +3317,7 @@ long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     return CM_ERROR_BADOP;
 }
 
+/* SMB_COM_ECHO */
 long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     unsigned short EchoCount, i;
@@ -2844,6 +3338,7 @@ long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     return 0;
 }
 
+/* SMB_COM_READ_RAW */
 long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     osi_hyper_t offset;
@@ -2851,6 +3346,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     unsigned short fd;
     unsigned pid;
     smb_fid_t *fidp;
+    smb_t *smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp = NULL;
     NCB *ncbp;
@@ -2901,7 +3397,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     }
 
 
-    pid = ((smb_t *) inp)->pid;
+    pid = smbp->pid;
     {
         LARGE_INTEGER LOffset, LLength;
         cm_key_t key;
@@ -2913,9 +3409,9 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         LLength.HighPart = 0;
         LLength.LowPart = count;
 
-        lock_ObtainMutex(&fidp->scp->mx);
+        lock_ObtainWrite(&fidp->scp->rw);
         code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
-        lock_ReleaseMutex(&fidp->scp->mx);
+        lock_ReleaseWrite(&fidp->scp->rw);
     }    
     if (code) {
         goto send1a;
@@ -2945,6 +3441,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
             lock_ReleaseMutex(&smb_RawBufLock);
         }
 
+        lock_ReleaseMutex(&fidp->mx);
         smb_ReleaseFID(fidp);
         return rc;
     }
@@ -3003,6 +3500,7 @@ long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
     return 0;
 }
 
+/* SMB_COM_NEGOTIATE */
 long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     char *namep;
@@ -3122,7 +3620,8 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
          * and NT Find *
          * and NT SMB's *
          * and raw mode 
-         * and DFS */
+         * and DFS
+         * and Unicode */
         caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
 #ifdef DFS_SUPPORT
                NTNEGOTIATE_CAPABILITY_DFS |
@@ -3137,6 +3636,12 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         if ( smb_authType == SMB_AUTH_EXTENDED )
             caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY;
 
+#ifdef SMB_UNICODE
+        if ( smb_UseUnicode ) {
+            caps |= NTNEGOTIATE_CAPABILITY_UNICODE;
+        }
+#endif
+
         smb_SetSMBParmLong(outp, 9, caps);
         time(&unixTime);
         smb_SearchTimeFromUnixTime(&dosTime, unixTime);
@@ -3153,7 +3658,9 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             datap = smb_GetSMBData(outp, NULL);
             memcpy(datap,vcp->encKey,MSV1_0_CHALLENGE_LENGTH);
             /* and the faux domain name */
-            strcpy(datap + MSV1_0_CHALLENGE_LENGTH,smb_ServerDomainName);
+            cm_ClientStringToUtf8(smb_ServerDomainName, -1,
+                                  datap + MSV1_0_CHALLENGE_LENGTH,
+                                  (int)(sizeof(outp->data)/sizeof(char) - (datap - outp->data)));
         } else if ( smb_authType == SMB_AUTH_EXTENDED ) {
             void * secBlob;
             int secBlobLength;
@@ -3215,7 +3722,9 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             /* paste in a new encryption key */
             memcpy(datap, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
             /* and the faux domain name */
-            strcpy(datap + MSV1_0_CHALLENGE_LENGTH, smb_ServerDomainName);
+            cm_ClientStringToUtf8(smb_ServerDomainName, -1,
+                                  datap + MSV1_0_CHALLENGE_LENGTH,
+                                  (int)(sizeof(outp->data)/sizeof(char) - (datap - outp->data)));
         } else {
             smb_SetSMBParm(outp, 11, 0); /* encryption key length */
             smb_SetSMBParm(outp, 12, 0); /* resvd */
@@ -3232,7 +3741,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 void smb_CheckVCs(void)
 {
     smb_vc_t * vcp, *nextp;
-    smb_packet_t * outp = GetPacket();
+    smb_packet_t * outp = smb_GetPacket();
     smb_t *smbp;
             
     lock_ObtainWrite(&smb_rctLock);
@@ -3317,7 +3826,7 @@ void smb_Daemon(void *parmp)
        now = osi_Time();
        lock_ObtainWrite(&smb_rctLock);
        for ( unpp=&usernamesp; *unpp; ) {
-           int delete = 0;
+           int deleteOk = 0;
            smb_username_t *unp;
 
            lock_ObtainMutex(&(*unpp)->mx);
@@ -3327,10 +3836,10 @@ void smb_Daemon(void *parmp)
                ;
            else if (!smb_LogoffTokenTransfer ||
                     ((*unpp)->last_logoff_t + smb_LogoffTransferTimeout < now))
-               delete = 1;
+               deleteOk = 1;
            lock_ReleaseMutex(&(*unpp)->mx);
 
-           if (delete) {
+           if (deleteOk) {
                cm_user_t * userp;
 
                unp = *unpp;    
@@ -3341,11 +3850,8 @@ void smb_Daemon(void *parmp)
                free(unp->name);
                free(unp->machine);
                free(unp);
-               if (userp) {
-                   lock_ReleaseWrite(&smb_rctLock);
+               if (userp)
                    cm_ReleaseUser(userp);
-                   lock_ObtainWrite(&smb_rctLock);
-               }
            } else {
                unpp = &(*unpp)->nextp;
            }
@@ -3396,6 +3902,11 @@ void smb_WaitingLocksDaemon()
                 if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
                     continue;
 
+                if (wl->state == SMB_WAITINGLOCKSTATE_CANCELLED) {
+                    code = CM_ERROR_LOCK_NOT_GRANTED;
+                    break;
+                }
+
                 osi_assertx(wl->state != SMB_WAITINGLOCKSTATE_ERROR, "!SMB_WAITINGLOCKSTATE_ERROR");
                 
                 /* wl->state is either _DONE or _WAITING.  _ERROR
@@ -3414,8 +3925,8 @@ void smb_WaitingLocksDaemon()
             if (code == CM_ERROR_WOULDBLOCK) {
 
                 /* no progress */
-                if (wlRequest->timeRemaining != 0xffffffff
-                     && (wlRequest->timeRemaining -= 1000) < 0)
+                if (wlRequest->msTimeout != 0xffffffff
+                     && ((osi_Time() - wlRequest->start_t) * 1000 > wlRequest->msTimeout))
                     goto endWait;
 
                 continue;
@@ -3433,22 +3944,23 @@ void smb_WaitingLocksDaemon()
                 scp = wlRequest->scp;
                osi_Log2(smb_logp,"smb_WaitingLocksDaemon wlRequest 0x%p scp 0x%p", wlRequest, scp);
 
-                cm_InitReq(&req);
+                smb_InitReq(&req);
 
-                lock_ObtainMutex(&scp->mx);
+                lock_ObtainWrite(&scp->rw);
 
                 for (wl = wlRequest->locks; wl; wl = wlNext) {
                     wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
-                    
-                    cm_Unlock(scp, wlRequest->lockType, wl->LOffset, 
-                              wl->LLength, wl->key, NULL, &req);
+                
+                    if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
+                        cm_Unlock(scp, wlRequest->lockType, wl->LOffset, 
+                                  wl->LLength, wl->key, NULL, &req);
 
                     osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
 
                     free(wl);
                 }
                 
-                lock_ReleaseMutex(&scp->mx);
+                lock_ReleaseWrite(&scp->rw);
 
             } else {
 
@@ -3465,7 +3977,7 @@ void smb_WaitingLocksDaemon()
             vcp = wlRequest->vcp;
             inp = wlRequest->inp;
             outp = wlRequest->outp;
-            ncbp = GetNCB();
+            ncbp = smb_GetNCB();
             ncbp->ncb_length = inp->ncb_length;
             inp->spacep = cm_GetSpace();
 
@@ -3489,7 +4001,7 @@ void smb_WaitingLocksDaemon()
             smb_FreePacket(outp);
             smb_ReleaseVC(vcp);
             cm_ReleaseSCache(wlRequest->scp);
-            FreeNCB(ncbp);
+            smb_FreeNCB(ncbp);
             free(wlRequest);
         } while (nwlRequest && smbShutdownFlag == 0);
         thrd_Sleep(1000);
@@ -3509,31 +4021,31 @@ long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     return 0;
 }
 
+/* SMB_COM_TREE_CONNECT */
 long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp)
 {
     smb_tid_t *tidp;
     smb_user_t *uidp;
     unsigned short newTid;
-    char shareName[AFSPATHMAX];
-    char *sharePath;
+    clientchar_t shareName[AFSPATHMAX];
+    clientchar_t *sharePath;
     int shareFound;
-    char *tp;
-    char *pathp;
-    char *passwordp;
+    clientchar_t *tp;
+    clientchar_t *pathp;
     cm_user_t *userp;
 
     osi_Log0(smb_logp, "SMB receive tree connect");
 
     /* parse input parameters */
-    tp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(tp, &tp);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
-    passwordp = smb_ParseASCIIBlock(tp, &tp);
-    tp = strrchr(pathp, '\\');
+    {
+        char *tbp;
+        tbp = smb_GetSMBData(inp, NULL);
+        pathp = smb_ParseASCIIBlock(inp, tbp, &tbp, SMB_STRF_ANSIPATH);
+    }
+    tp = cm_ClientStrRChr(pathp, '\\');
     if (!tp)
         return CM_ERROR_BADSMB;
-    strcpy(shareName, tp+1);
+    cm_ClientStrCpy(shareName, lengthof(shareName), tp+1);
 
     lock_ObtainMutex(&vcp->mx);
     newTid = vcp->tidCounter++;
@@ -3546,14 +4058,14 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     if (uidp)
         smb_ReleaseUID(uidp);
     if (!shareFound) {
-        smb_ReleaseTID(tidp);
+        smb_ReleaseTID(tidp, FALSE);
         return CM_ERROR_BADSHARENAME;
     }
     lock_ObtainMutex(&tidp->mx);
     tidp->userp = userp;
     tidp->pathname = sharePath;
     lock_ReleaseMutex(&tidp->mx);
-    smb_ReleaseTID(tidp);
+    smb_ReleaseTID(tidp, FALSE);
 
     smb_SetSMBParm(rsp, 0, SMB_PACKETSIZE);
     smb_SetSMBParm(rsp, 1, newTid);
@@ -3563,32 +4075,15 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     return 0;
 }
 
-unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
-{
-    int tlen;
-
-    if (*inp++ != 0x1) return NULL;
-    tlen = inp[0] + (inp[1]<<8);
-    inp += 2;          /* skip length field */
-        
-    if (chainpp) {
-        *chainpp = inp + tlen;
-    }  
-
-    if (lengthp) *lengthp = tlen;
-        
-    return inp;
-}
-
 /* set maskp to the mask part of the incoming path.
  * Mask is 11 bytes long (8.3 with the dot elided).
  * Returns true if succeeds with a valid name, otherwise it does
  * its best, but returns false.
  */
-int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
+int smb_Get8Dot3MaskFromPath(clientchar_t *maskp, clientchar_t *pathp)
 {
-    char *tp;
-    char *up;
+    clientchar_t *tp;
+    clientchar_t *up;
     int i;
     int tc;
     int valid8Dot3;
@@ -3601,7 +4096,7 @@ int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
     maskp[11] = '\0';
 
     /* find last backslash, or use whole thing if there is none */
-    tp = strrchr(pathp, '\\');
+    tp = cm_ClientStrRChr(pathp, '\\');
     if (!tp) 
         tp = pathp;
     else 
@@ -3646,17 +4141,17 @@ int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
     /* unreachable */
 }
 
-int smb_Match8Dot3Mask(char *unixNamep, char *maskp)
+int smb_Match8Dot3Mask(clientchar_t *unixNamep, clientchar_t *maskp)
 {
-    char umask[11];
+    clientchar_t umask[11];
     int valid;
     int i;
-    char tc1;
-    char tc2;
-    char *tp1;
-    char *tp2;
+    clientchar_t tc1;
+    clientchar_t tc2;
+    clientchar_t *tp1;
+    clientchar_t *tp2;
 
-    /* XXX redo this, calling smb_V3MatchMask with a converted mask */
+    /* XXX redo this, calling cm_MatchMask with a converted mask */
 
     valid = smb_Get8Dot3MaskFromPath(umask, unixNamep);
     if (!valid) 
@@ -3668,10 +4163,10 @@ int smb_Match8Dot3Mask(char *unixNamep, char *maskp)
     tp1 = umask;       /* real name, in mask format */
     tp2 = maskp;       /* mask, in mask format */
     for(i=0; i<11; i++) {
-        tc1 = *tp1++;  /* char from real name */
-        tc2 = *tp2++;  /* char from mask */
-        tc1 = (char) cm_foldUpper[(unsigned char)tc1];
-        tc2 = (char) cm_foldUpper[(unsigned char)tc2];
+        tc1 = *tp1++;  /* clientchar_t from real name */
+        tc2 = *tp2++;  /* clientchar_t from mask */
+        tc1 = (clientchar_t) cm_foldUpper[(clientchar_t)tc1];
+        tc2 = (clientchar_t) cm_foldUpper[(clientchar_t)tc2];
         if (tc1 == tc2) 
             continue;
         if (tc2 == '?' && tc1 != ' ') 
@@ -3685,11 +4180,11 @@ int smb_Match8Dot3Mask(char *unixNamep, char *maskp)
     return 1;
 }
 
-char *smb_FindMask(char *pathp)
+clientchar_t *smb_FindMask(clientchar_t *pathp)
 {
-    char *tp;
+    clientchar_t *tp;
         
-    tp = strrchr(pathp, '\\'); /* find last slash */
+    tp = cm_ClientStrRChr(pathp, '\\');        /* find last slash */
 
     if (tp) 
         return tp+1;   /* skip the slash */
@@ -3697,11 +4192,15 @@ char *smb_FindMask(char *pathp)
         return pathp;  /* no slash, return the entire path */
 }       
 
+/* SMB_COM_SEARCH for a volume label
+
+   (This is called from smb_ReceiveCoreSearchDir() and not an actual
+   dispatch function.) */
 long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    unsigned char *pathp;
+    clientchar_t *pathp;
     unsigned char *tp;
-    unsigned char mask[12];
+    clientchar_t mask[12];
     unsigned char *statBlockp;
     unsigned char initStatBlock[21];
     int statLen;
@@ -3710,11 +4209,10 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 
     /* pull pathname and stat block out of request */
     tp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(tp, (char **) &tp);
+    pathp = smb_ParseASCIIBlock(inp, tp, &tp,
+                                SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
     osi_assertx(pathp != NULL, "null path");
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
-    statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen);
+    statBlockp = smb_ParseVblBlock(tp, &tp, &statLen);
     osi_assertx(statBlockp != NULL, "null statBlock");
     if (statLen == 0) {
         statBlockp = initStatBlock;
@@ -3756,6 +4254,9 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
     *tp++ = 0;
     *tp++ = 0;
 
+    /* The filename is a UCHAR buffer that is ASCII even if Unicode
+       was negotiated. */
+
     /* finally, null-terminated 8.3 pathname, which we set to AFS */
     memset(tp, ' ', 13);
     strcpy(tp, "AFS");
@@ -3769,7 +4270,7 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 
 static long 
 smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
-                        char * tidPathp, char * relPathp,
+                        clientchar_t * tidPathp, clientchar_t * relPathp,
                         cm_user_t *userp, cm_req_t *reqp)
 {
     long code = 0;
@@ -3780,14 +4281,15 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
     char attr;
     smb_dirListPatch_t *patchp;
     smb_dirListPatch_t *npatchp;
-    char path[AFSPATHMAX];
+    clientchar_t path[AFSPATHMAX];
 
     for (patchp = *dirPatchespp; patchp; patchp =
          (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
 
         dptr = patchp->dptr;
 
-        snprintf(path, AFSPATHMAX, "%s\\%s", relPathp ? relPathp : "", patchp->dep->name);
+        cm_ClientStrPrintfN(path, AFSPATHMAX, _C("%s\\%s"),
+                            relPathp ? relPathp : _C(""), patchp->dep->name);
         reqp->relPathp = path;
         reqp->tidPathp = tidPathp;
 
@@ -3799,11 +4301,11 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
                 *dptr++ = SMB_ATTR_HIDDEN;
             continue;
         }
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
         code = cm_SyncOp(scp, NULL, userp, reqp, 0,
                           CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         if (code) {    
-            lock_ReleaseMutex(&scp->mx);
+            lock_ReleaseWrite(&scp->rw);
             cm_ReleaseSCache(scp);
             if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
                 *dptr++ = SMB_ATTR_HIDDEN;
@@ -3812,6 +4314,7 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
 
        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
+        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)
@@ -3834,7 +4337,7 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
         /* copy out file length */
         *((u_long *)dptr) = scp->length.LowPart;
         dptr += 4;
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseRead(&scp->rw);
         cm_ReleaseSCache(scp);
     }
         
@@ -3850,13 +4353,14 @@ smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
     return code;
 }
 
+/* SMB_COM_SEARCH */
 long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     int attribute;
     long nextCookie;
-    char *tp;
+    unsigned char *tp;
     long code = 0;
-    char *pathp;
+    clientchar_t *pathp;
     cm_dirEntry_t *dep = 0;
     int maxCount;
     smb_dirListPatch_t *dirListPatchesp;
@@ -3877,10 +4381,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     cm_pageHeader_t *pageHeaderp;
     cm_user_t *userp = NULL;
     int slotInPage;
-    char shortName[13];
-    char *actualName;
-    char *shortNameEnd;
-    char mask[12];
+    clientchar_t mask[12];
     int returnedNames;
     long nextEntryCookie;
     int numDirChunks;          /* # of 32 byte dir chunks in this entry */
@@ -3891,12 +4392,12 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     int starPattern;
     int rootPath = 0;
     int caseFold;
-    char *tidPathp = 0;
+    clientchar_t *tidPathp = 0;
     cm_req_t req;
     cm_fid_t fid;
     int fileType;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     maxCount = smb_GetSMBParm(inp, 0);
 
@@ -3905,9 +4406,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     caseFold = CM_FLAG_CASEFOLD;
 
     tp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(tp, &tp);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
+    pathp = smb_ParseASCIIBlock(inp, tp, &tp,
+                                SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
     inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
 
     /* bail out if request looks bad */
@@ -3930,8 +4430,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         if (attribute & 0x8)
             return smb_ReceiveCoreSearchVolume(vcp, inp, outp);
 
-        osi_Log2(smb_logp, "SMB receive search dir count %d [%s]",
-                  maxCount, osi_LogSaveString(smb_logp, pathp));
+        osi_Log2(smb_logp, "SMB receive search dir count %d [%S]",
+                 maxCount, osi_LogSaveClientString(smb_logp, pathp));
 
         if (*pathp == 0) {     /* null pathp, treat as root dir */
             if (!(attribute & SMB_ATTR_DIRECTORY))     /* exclude dirs */
@@ -3956,8 +4456,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         dsp = smb_FindDirSearch(inCookiep[12]);
         if (!dsp) {
             /* can't find dir search status; fatal error */
-            osi_Log3(smb_logp, "SMB receive search dir bad cookie: cookie %d nextCookie %u [%s]",
-                     inCookiep[12], nextCookie, osi_LogSaveString(smb_logp, pathp));
+            osi_Log3(smb_logp, "SMB receive search dir bad cookie: cookie %d nextCookie %u [%S]",
+                     inCookiep[12], nextCookie, osi_LogSaveClientString(smb_logp, pathp));
             return CM_ERROR_BADFD;
         }
         attribute = dsp->attribute;
@@ -3990,7 +4490,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         code = 0;
     } else {
         spacep = inp->spacep;
-        smb_StripLastComponent(spacep->data, NULL, pathp);
+        smb_StripLastComponent(spacep->wdata, NULL, pathp);
         code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
         if (code) {
             lock_ReleaseMutex(&dsp->mx);
@@ -3999,15 +4499,17 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
             smb_ReleaseDirSearch(dsp);
             return CM_ERROR_NOFILES;
         }
-        strcpy(dsp->tidPath, tidPathp ? tidPathp : "/");
-        strcpy(dsp->relPath, spacep->data);
+        cm_ClientStrCpy(dsp->tidPath, lengthof(dsp->tidPath), tidPathp ? tidPathp : _C("/"));
+        cm_ClientStrCpy(dsp->relPath, lengthof(dsp->relPath), spacep->wdata);
 
-        code = cm_NameI(cm_data.rootSCachep, spacep->data,
+        code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
                         caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
         if (code == 0) {
 #ifdef DFS_SUPPORT
             if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
-                int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->data);
+                int pnc;
+
+                pnc  = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, spacep->wdata);
                 cm_ReleaseSCache(scp);
                 lock_ReleaseMutex(&dsp->mx);
                 cm_ReleaseUser(userp);
@@ -4029,14 +4531,14 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
              * now.
              */
             cm_HoldSCache(scp);
-            lock_ObtainMutex(&scp->mx);
+            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;
             }
-            lock_ReleaseMutex(&scp->mx);
+            lock_ReleaseWrite(&scp->rw);
         }
     }
     lock_ReleaseMutex(&dsp->mx);
@@ -4054,11 +4556,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     smb_SetSMBParm(outp, 0, 0);
 
     /* get the directory size */
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code) {
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseWrite(&scp->rw);
         cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
         smb_DeleteDirSearch(dsp);
@@ -4080,6 +4582,10 @@ 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 shortName[13];
+        clientchar_t *shortNameEnd;
+
         /* make sure that curOffset.LowPart doesn't point to the first
          * 32 bytes in the 2nd through last dir page, and that it doesn't
          * point at the first 13 32-byte chunks in the first dir page,
@@ -4127,10 +4633,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                 buf_Release(bufferp);
                 bufferp = NULL;
             }  
-            lock_ReleaseMutex(&scp->mx);
-            lock_ObtainRead(&scp->bufCreateLock);
+            lock_ReleaseWrite(&scp->rw);
             code = buf_Get(scp, &thyper, &bufferp);
-            lock_ReleaseRead(&scp->bufCreateLock);
             lock_ObtainMutex(&dsp->mx);
 
             /* now, if we're doing a star match, do bulk fetching of all of 
@@ -4138,7 +4642,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
              */
             if (starPattern) {
                 smb_ApplyDirListPatches(&dirListPatchesp, dsp->tidPath, dsp->relPath, userp, &req);
-                lock_ObtainMutex(&scp->mx);
+                lock_ObtainWrite(&scp->rw);
                 if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
                      LargeIntegerGreaterThanOrEqualTo(thyper, 
                                                       scp->bulkStatProgress)) {
@@ -4153,7 +4657,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                         code = cm_TryBulkStat(scp, &thyper, userp, &req);
                 }
             } else {
-                lock_ObtainMutex(&scp->mx);
+                lock_ObtainWrite(&scp->rw);
             }
             lock_ReleaseMutex(&dsp->mx);
             if (code) {
@@ -4236,15 +4740,16 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         nextEntryCookie = curOffset.LowPart + (CM_DIR_CHUNKSIZE * numDirChunks);
 
         /* Compute 8.3 name if necessary */
-        actualName = dep->name;
+        actualName = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
         if (dep->fid.vnode != 0 && !cm_Is8Dot3(actualName)) {
-            cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
+            free(actualName);
+            cm_Gen8Dot3NameInt(dep->name, &dep->fid, shortName, &shortNameEnd);
             actualName = shortName;
         }
 
-        osi_Log3(smb_logp, "SMB search dir vn %d name %s (%s)",
-                  dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
-                  osi_LogSaveString(smb_logp, actualName));
+        osi_Log3(smb_logp, "SMB search dir vn %d name %s (%S)",
+                 dep->fid.vnode, osi_LogSaveString(smb_logp, dep->name),
+                 osi_LogSaveClientString(smb_logp, actualName));
 
         if (dep->fid.vnode != 0 && smb_Match8Dot3Mask(actualName, mask)) {
             /* this is one of the entries to use: it is not deleted
@@ -4263,10 +4768,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
             if (!(dsp->attribute & SMB_ATTR_DIRECTORY))  /* no directories */
             {
                 /* We have already done the cm_TryBulkStat above */
-                fid.cell = scp->fid.cell;
-                fid.volume = scp->fid.volume;
-                fid.vnode = ntohl(dep->fid.vnode);
-                fid.unique = ntohl(dep->fid.unique);
+                cm_SetFid(&fid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
                 fileType = cm_FindFileType(&fid);
                 osi_Log2(smb_logp, "smb_ReceiveCoreSearchDir: file %s "
                          "has filetype %d", osi_LogSaveString(smb_logp, dep->name),
@@ -4281,11 +4783,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
             *op++ = resByte;
             memcpy(op, mask, 11); op += 11;
-            *op++ = (char) dsp->cookie;        /* they say it must be non-zero */
-            *op++ = (char)(nextEntryCookie & 0xff);
-            *op++ = (char)((nextEntryCookie>>8) & 0xff);
-            *op++ = (char)((nextEntryCookie>>16) & 0xff);
-            *op++ = (char)((nextEntryCookie>>24) & 0xff);
+            *op++ = (unsigned char) dsp->cookie;       /* they say it must be non-zero */
+            *op++ = (unsigned char)(nextEntryCookie & 0xff);
+            *op++ = (unsigned char)((nextEntryCookie>>8) & 0xff);
+            *op++ = (unsigned char)((nextEntryCookie>>16) & 0xff);
+            *op++ = (unsigned char)((nextEntryCookie>>24) & 0xff);
             memcpy(op, &clientCookie, 4); op += 4;
 
             /* now we emit the attribute.  This is sort of tricky,
@@ -4304,10 +4806,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
             curPatchp = malloc(sizeof(*curPatchp));
             osi_QAdd((osi_queue_t **) &dirListPatchesp, &curPatchp->q);
             curPatchp->dptr = op;
-            curPatchp->fid.cell = scp->fid.cell;
-            curPatchp->fid.volume = scp->fid.volume;
-            curPatchp->fid.vnode = ntohl(dep->fid.vnode);
-            curPatchp->fid.unique = ntohl(dep->fid.unique);
+            cm_SetFid(&curPatchp->fid, scp->fid.cell, scp->fid.volume, ntohl(dep->fid.vnode), ntohl(dep->fid.unique));
 
             /* do hidden attribute here since name won't be around when applying
              * dir list patches
@@ -4329,9 +4828,11 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
              * it fits in 8.3 or the pattern wouldn't match, but it
              * never hurts to be sure.
              */
-            strncpy(op, actualName, 13);
+            cm_ClientStringToUtf8(actualName, -1, op, 13);
             if (smb_StoreAnsiFilenames)
                 CharToOem(op, op);
+            /* This is a UCHAR field, which is ASCII even if Unicode
+               is negotiated. */
 
             /* Uppercase if requested by client */
             if (!KNOWS_LONG_NAMES(inp))
@@ -4351,7 +4852,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     }          /* while copying data for dir listing */
 
     /* release the mutex */
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     if (bufferp) {
        buf_Release(bufferp);
        bufferp = NULL;
@@ -4389,8 +4890,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
      */
     temp -= 3;         /* deduct vbl block info */
     osi_assertx(temp == (43 * returnedNames), "unexpected data length");
-    origOp[1] = (char)(temp & 0xff);
-    origOp[2] = (char)((temp>>8) & 0xff);
+    origOp[1] = (unsigned char)(temp & 0xff);
+    origOp[2] = (unsigned char)((temp>>8) & 0xff);
     if (returnedNames == 0) 
         smb_DeleteDirSearch(dsp);
     smb_ReleaseDirSearch(dsp);
@@ -4399,31 +4900,33 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     return code;
 }      
 
+
 /* verify that this is a valid path to a directory.  I don't know why they
  * don't use the get file attributes call.
+ *
+ * SMB_COM_CHECK_DIRECTORY
  */
 long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    char *pathp;
+    clientchar_t *pathp;
     long code = 0;
     cm_scache_t *rootScp;
     cm_scache_t *newScp;
     cm_user_t *userp;
     unsigned int attrs;
     int caseFold;
-    char *tidPathp;
+    clientchar_t *tidPathp;
     cm_req_t req;
+    char * pdata;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
-    pathp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(pathp, NULL);
+    pdata = smb_GetSMBData(inp, NULL);
+    pathp = smb_ParseASCIIBlock(inp, pdata, NULL, SMB_STRF_ANSIPATH);
     if (!pathp)
         return CM_ERROR_BADFD;
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
-    osi_Log1(smb_logp, "SMB receive check path %s",
-             osi_LogSaveString(smb_logp, pathp));
+    osi_Log1(smb_logp, "SMB receive check path %S",
+             osi_LogSaveClientString(smb_logp, pathp));
         
     rootScp = cm_data.rootSCachep;
         
@@ -4458,12 +4961,12 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 #endif /* DFS_SUPPORT */
 
     /* now lock the vnode with a callback; returns with newScp locked */
-    lock_ObtainMutex(&newScp->mx);
+    lock_ObtainWrite(&newScp->rw);
     code = cm_SyncOp(newScp, NULL, userp, &req, PRSFS_LOOKUP,
                      CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
     if (code) {
        if (code != CM_ERROR_NOACCESS) {
-           lock_ReleaseMutex(&newScp->mx);
+           lock_ReleaseWrite(&newScp->rw);
            cm_ReleaseSCache(newScp);
            cm_ReleaseUser(userp);
            return code;
@@ -4477,16 +4980,17 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
     if (!(attrs & SMB_ATTR_DIRECTORY))
         code = CM_ERROR_NOTDIR;
 
-    lock_ReleaseMutex(&newScp->mx);
+    lock_ReleaseWrite(&newScp->rw);
 
     cm_ReleaseSCache(newScp);
     cm_ReleaseUser(userp);
     return code;
 }      
 
+/* SMB_COM_SET_INFORMATION */
 long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    char *pathp;
+    clientchar_t *pathp;
     long code = 0;
     cm_scache_t *rootScp;
     unsigned short attribute;
@@ -4495,21 +4999,20 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     afs_uint32 dosTime;
     cm_user_t *userp;
     int caseFold;
-    char *tidPathp;
+    clientchar_t *tidPathp;
+    char * datap;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     /* decode basic attributes we're passed */
     attribute = smb_GetSMBParm(inp, 0);
     dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
 
-    pathp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(pathp, NULL);
+    datap = smb_GetSMBData(inp, NULL);
+    pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
     if (!pathp)
         return CM_ERROR_BADSMB;
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
                
     osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
              dosTime, attribute);
@@ -4549,11 +5052,11 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
      * need the current status to determine what the new status is, in some
      * cases.
      */
-    lock_ObtainMutex(&newScp->mx);
+    lock_ObtainWrite(&newScp->rw);
     code = cm_SyncOp(newScp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
     if (code) {
-        lock_ReleaseMutex(&newScp->mx);
+        lock_ReleaseWrite(&newScp->rw);
         cm_ReleaseSCache(newScp);
         cm_ReleaseUser(userp);
         return code;
@@ -4563,7 +5066,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 
     /* Check for RO volume */
     if (newScp->flags & CM_SCACHEFLAG_RO) {
-        lock_ReleaseMutex(&newScp->mx);
+        lock_ReleaseWrite(&newScp->rw);
         cm_ReleaseSCache(newScp);
         cm_ReleaseUser(userp);
         return CM_ERROR_READONLY;
@@ -4585,7 +5088,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
         attr.unixModeBits = newScp->unixModeBits | 0222;
         attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
     }
-    lock_ReleaseMutex(&newScp->mx);
+    lock_ReleaseWrite(&newScp->rw);
 
     /* now call setattr */
     if (attr.mask)
@@ -4599,9 +5102,10 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     return code;
 }
 
+
 long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    char *pathp;
+    clientchar_t *pathp;
     long code = 0;
     cm_scache_t *rootScp;
     cm_scache_t *newScp, *dscp;
@@ -4609,26 +5113,24 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     int attrs;
     cm_user_t *userp;
     int caseFold;
-    char *tidPathp;
+    clientchar_t *tidPathp;
     cm_space_t *spacep;
-    char *lastComp;
+    clientchar_t *lastComp;
+    char * datap;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
-    pathp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(pathp, NULL);
+    datap = smb_GetSMBData(inp, NULL);
+    pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
     if (!pathp)
         return CM_ERROR_BADSMB;
         
     if (*pathp == 0)           /* null path */
-        pathp = "\\";
-    else
-        if (smb_StoreAnsiFilenames)
-            OemToChar(pathp,pathp);
+        pathp = _C("\\");
 
-    osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
-             osi_LogSaveString(smb_logp, pathp));
+    osi_Log1(smb_logp, "SMB receive getfile attributes path %S",
+             osi_LogSaveClientString(smb_logp, pathp));
 
     rootScp = cm_data.rootSCachep;
         
@@ -4661,16 +5163,17 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
      * http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/shell_basics/shell_basics_extending/custom.asp
      */
     spacep = inp->spacep;
-    smb_StripLastComponent(spacep->data, &lastComp, pathp);
+    smb_StripLastComponent(spacep->wdata, &lastComp, pathp);
 #ifndef SPECIAL_FOLDERS
-    if (lastComp && stricmp(lastComp, "\\desktop.ini") == 0) {
-        code = cm_NameI(rootScp, spacep->data,
+    if (lastComp && cm_ClientStrCmpIA(lastComp, _C("\\desktop.ini")) == 0) {
+        code = cm_NameI(rootScp, spacep->wdata,
                         caseFold | CM_FLAG_DIRSEARCH | CM_FLAG_FOLLOW,
                         userp, tidPathp, &req, &dscp);
         if (code == 0) {
 #ifdef DFS_SUPPORT
             if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
-                int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+                int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp,
+                                                          spacep->wdata);
                 if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
@@ -4716,11 +5219,11 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 #endif /* DFS_SUPPORT */
 
     /* now lock the vnode with a callback; returns with newScp locked */
-    lock_ObtainMutex(&newScp->mx);
+    lock_ObtainWrite(&newScp->rw);
     code = cm_SyncOp(newScp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
     if (code) {
-        lock_ReleaseMutex(&newScp->mx);
+        lock_ReleaseWrite(&newScp->rw);
         cm_ReleaseSCache(newScp);
         cm_ReleaseUser(userp);
         return code;
@@ -4757,7 +5260,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     smb_SetSMBParm(outp, 8, 0);
     smb_SetSMBParm(outp, 9, 0);
     smb_SetSMBDataLength(outp, 0);
-    lock_ReleaseMutex(&newScp->mx);
+    lock_ReleaseWrite(&newScp->rw);
 
     cm_ReleaseSCache(newScp);
     cm_ReleaseUser(userp);
@@ -4765,6 +5268,7 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
     return 0;
 }      
 
+/* SMB_COM_TREE_DISCONNECT */
 long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     smb_tid_t *tidp;
@@ -4775,19 +5279,20 @@ long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_
     tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
     if (tidp) {
        lock_ObtainWrite(&smb_rctLock);
-        tidp->delete = 1;
+        tidp->deleteOk = 1;
+        smb_ReleaseTID(tidp, TRUE);
         lock_ReleaseWrite(&smb_rctLock);
-        smb_ReleaseTID(tidp);
     }
 
     return 0;
 }
 
+/* SMB_COM_0PEN */
 long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     smb_fid_t *fidp;
-    char *pathp;
-    char *lastNamep;
+    clientchar_t *pathp;
+    clientchar_t *lastNamep;
     int share;
     int attribute;
     long code = 0;
@@ -4796,17 +5301,16 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     afs_uint32 dosTime;
     int caseFold;
     cm_space_t *spacep;
-    char *tidPathp;
+    clientchar_t *tidPathp;
+    char * datap;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
-    pathp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(pathp, NULL);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
-       
-    osi_Log1(smb_logp, "SMB receive open file [%s]", osi_LogSaveString(smb_logp, pathp));
+    datap = smb_GetSMBData(inp, NULL);
+    pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
+
+    osi_Log1(smb_logp, "SMB receive open file [%S]", osi_LogSaveClientString(smb_logp, pathp));
 
 #ifdef DEBUG_VERBOSE
     {
@@ -4822,8 +5326,8 @@ 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(spacep->data, &lastNamep, pathp);
-    if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
+    smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+    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).
          */
@@ -4894,9 +5398,9 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* save a pointer to the vnode */
     fidp->scp = scp;
     osi_Log2(smb_logp,"smb_ReceiveCoreOpen fidp 0x%p scp 0x%p", fidp, scp);
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     scp->flags |= CM_SCACHEFLAG_SMB_FID;
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
 
     /* and the user */
     cm_HoldUser(userp);
@@ -4911,7 +5415,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         fidp->flags |= (SMB_FID_OPENREAD_LISTDIR | SMB_FID_OPENWRITE);
     lock_ReleaseMutex(&fidp->mx);
 
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainRead(&scp->rw);
     smb_SetSMBParm(outp, 0, fidp->fid);
     smb_SetSMBParm(outp, 1, smb_Attributes(scp));
     smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
@@ -4922,7 +5426,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(&scp->mx);
+    lock_ReleaseRead(&scp->rw);
         
     /* notify open */
     cm_Open(scp, 0, userp);
@@ -4939,7 +5443,7 @@ typedef struct smb_unlinkRock {
     cm_user_t *userp;
     cm_req_t *reqp;
     smb_vc_t *vcp;
-    char *maskp;               /* pointer to the star pattern */
+    clientchar_t *maskp;               /* pointer to the star pattern */
     int flags;
     int any;
     cm_dirEntryList_t * matches;
@@ -4951,8 +5455,7 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
     smb_unlinkRock_t *rockp;
     int caseFold;
     int match;
-    char shortName[13];
-    char *matchName;
+    normchar_t matchName[MAX_PATH];
         
     rockp = vrockp;
 
@@ -4960,26 +5463,25 @@ 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;
 
-    matchName = dep->name;
-    match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
+    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+    match = cm_MatchMask(matchName, rockp->maskp, caseFold);
     if (!match &&
-         (rockp->flags & SMB_MASKFLAG_TILDE) &&
-         !cm_Is8Dot3(dep->name)) {
-        cm_Gen8Dot3Name(dep, shortName, NULL);
-        matchName = shortName;
+        (rockp->flags & SMB_MASKFLAG_TILDE) &&
+        !cm_Is8Dot3(matchName)) {
+        cm_Gen8Dot3Name(dep, matchName, NULL);
         /* 8.3 matches are always case insensitive */
-        match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
+        match = cm_MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
     }
     if (match) {
-        osi_Log1(smb_logp, "Found match %s",
-                 osi_LogSaveString(smb_logp, matchName));
+        osi_Log1(smb_logp, "Found match %S",
+                 osi_LogSaveClientString(smb_logp, matchName));
 
         cm_DirEntryListAdd(dep->name, &rockp->matches);
 
         rockp->any = 1;
 
         /* If we made a case sensitive exact match, we might as well quit now. */
-        if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
+        if (!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !cm_ClientStrCmp(matchName, rockp->maskp))
             code = CM_ERROR_STOPNOW;
         else
             code = 0;
@@ -4989,36 +5491,35 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
     return code;
 }
 
+/* SMB_COM_DELETE */
 long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     int attribute;
     long code = 0;
-    char *pathp;
-    char *tp;
+    clientchar_t *pathp;
+    unsigned char *tp;
     cm_space_t *spacep;
     cm_scache_t *dscp;
-    char *lastNamep;
+    clientchar_t *lastNamep;
     smb_unlinkRock_t rock;
     cm_user_t *userp;
     osi_hyper_t thyper;
     int caseFold;
-    char *tidPathp;
+    clientchar_t *tidPathp;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     attribute = smb_GetSMBParm(inp, 0);
         
     tp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(tp, &tp);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
+    pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
 
-    osi_Log1(smb_logp, "SMB receive unlink %s",
-             osi_LogSaveString(smb_logp, pathp));
+    osi_Log1(smb_logp, "SMB receive unlink %S",
+             osi_LogSaveClientString(smb_logp, pathp));
 
     spacep = inp->spacep;
-    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
     userp = smb_GetUserFromVCP(vcp, inp);
 
@@ -5029,7 +5530,7 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold, userp, tidPathp,
+    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold, userp, tidPathp,
                     &req, &dscp);
     if (code) {
         cm_ReleaseUser(userp);
@@ -5038,7 +5539,7 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
 #ifdef DFS_SUPPORT
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
-        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp,spacep->data);
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->wdata);
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
@@ -5055,8 +5556,8 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         lastNamep++;
 
     rock.any = 0;
-    rock.maskp = smb_FindMask(pathp);
-    rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+    rock.maskp = cm_ClientStringToNormStringAlloc(smb_FindMask(pathp), -1, NULL);
+    rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
 
     thyper.LowPart = 0;
     thyper.HighPart = 0;
@@ -5089,15 +5590,22 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_dirEntryList_t * entry;
 
         for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+            normchar_t normalizedName[MAX_PATH];
+
+            /* Note: entry->name is a non-normalized name */
 
             osi_Log1(smb_logp, "Unlinking %s",
                      osi_LogSaveString(smb_logp, entry->name));
-            code = cm_Unlink(dscp, entry->name, userp, &req);
+
+            cm_FsStringToNormString(entry->name, -1,
+                                    normalizedName, lengthof(normalizedName));
+
+            code = cm_Unlink(dscp, entry->name, normalizedName, userp, &req);
 
             if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                 smb_NotifyChange(FILE_ACTION_REMOVED,
                                  FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
-                                 dscp, entry->name, NULL, TRUE);
+                                 dscp, normalizedName, NULL, TRUE);
         }
     }
 
@@ -5107,21 +5615,24 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     cm_ReleaseSCache(dscp);
 
+    free(rock.maskp);
+
     if (code == 0 && !rock.any)
         code = CM_ERROR_NOSUCHFILE;
     return code;
 }       
 
 typedef struct smb_renameRock {
-    cm_scache_t *odscp;        /* old dir */
-    cm_scache_t *ndscp;        /* new dir */
-    cm_user_t *userp;  /* user */
-    cm_req_t *reqp;            /* request struct */
-    smb_vc_t *vcp;             /* virtual circuit */
-    char *maskp;               /* pointer to star pattern of old file name */
-    int flags;             /* tilde, casefold, etc */
-    char *newNamep;            /* ptr to the new file's name */
-    char oldName[MAX_PATH];
+    cm_scache_t *odscp;  /* old dir */
+    cm_scache_t *ndscp;  /* new dir */
+    cm_user_t *userp;    /* user */
+    cm_req_t *reqp;      /* request struct */
+    smb_vc_t *vcp;       /* virtual circuit */
+    normchar_t *maskp;   /* pointer to star pattern of old file name */
+    int flags;           /* tilde, casefold, etc */
+    clientchar_t *newNamep;     /* ptr to the new file's name */
+    fschar_t fsOldName[MAX_PATH]; /* raw FS name */
+    clientchar_t clOldName[MAX_PATH]; /* client name */
     int any;
 } smb_renameRock_t;
 
@@ -5131,27 +5642,29 @@ int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
     smb_renameRock_t *rockp;
     int caseFold;
     int match;
-    char shortName[13]="";
+    normchar_t matchName[MAX_PATH];
 
     rockp = (smb_renameRock_t *) vrockp;
 
+    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
     caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
     if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
         caseFold |= CM_FLAG_8DOT3;
 
-    match = smb_V3MatchMask(dep->name, rockp->maskp, caseFold);
+    match = cm_MatchMask(matchName, rockp->maskp, caseFold);
     if (!match &&
         (rockp->flags & SMB_MASKFLAG_TILDE) &&
-         !cm_Is8Dot3(dep->name)) {
-        cm_Gen8Dot3Name(dep, shortName, NULL);
-        match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
+        !cm_Is8Dot3(matchName)) {
+        cm_Gen8Dot3Name(dep, matchName, NULL);
+        match = cm_MatchMask(matchName, rockp->maskp, caseFold);
     }
 
     if (match) {
        rockp->any = 1;
-        strncpy(rockp->oldName, dep->name, sizeof(rockp->oldName)/sizeof(char) - 1);
-        rockp->oldName[sizeof(rockp->oldName)/sizeof(char) - 1] = '\0';
-            code = CM_ERROR_STOPNOW;
+        StringCbCopyA(rockp->fsOldName, sizeof(rockp->fsOldName), dep->name);
+        cm_ClientStrCpy(rockp->clOldName, lengthof(rockp->clOldName),
+                        matchName);
+        code = CM_ERROR_STOPNOW;
     } else {
        code = 0;
     }
@@ -5161,7 +5674,7 @@ int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
 
 
 long 
-smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, int attrs)
+smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t * newPathp, int attrs)
 {
     long code = 0;
     cm_space_t *spacep = NULL;
@@ -5170,12 +5683,12 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     cm_scache_t *newDscp = NULL;
     cm_scache_t *tmpscp= NULL;
     cm_scache_t *tmpscp2 = NULL;
-    char *oldLastNamep;
-    char *newLastNamep;
+    clientchar_t *oldLastNamep;
+    clientchar_t *newLastNamep;
     osi_hyper_t thyper;
     cm_user_t *userp;
     int caseFold;
-    char *tidPathp;
+    clientchar_t *tidPathp;
     DWORD filter;
     cm_req_t req;
 
@@ -5186,12 +5699,12 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
         return CM_ERROR_NOSUCHPATH;
     }
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
     spacep = inp->spacep;
-    smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
+    smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
 
     caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
-    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
+    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
                     userp, tidPathp, &req, &oldDscp);
     if (code) {
         cm_ReleaseUser(userp);
@@ -5200,7 +5713,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
         
 #ifdef DFS_SUPPORT
     if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
-        int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->data);
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->wdata);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseUser(userp);
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
@@ -5210,8 +5723,8 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     }
 #endif /* DFS_SUPPORT */
 
-    smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
-    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
+    smb_StripLastComponent(spacep->wdata, &newLastNamep, newPathp);
+    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
                     userp, tidPathp, &req, &newDscp);
 
     if (code) {
@@ -5222,7 +5735,7 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
 
 #ifdef DFS_SUPPORT
     if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
-        int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->data);
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->wdata);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseSCache(newDscp);
         cm_ReleaseUser(userp);
@@ -5258,10 +5771,11 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     rock.userp = userp;
     rock.reqp = &req;
     rock.vcp = vcp;
-    rock.maskp = oldLastNamep;
-    rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+    rock.maskp = cm_ClientStringToNormStringAlloc(oldLastNamep, -1, NULL);
+    rock.flags = ((cm_ClientStrChr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
     rock.newNamep = newLastNamep;
-    rock.oldName[0] = '\0';
+    rock.fsOldName[0] = '\0';
+    rock.clOldName[0] = '\0';
     rock.any = 0;
 
     /* Check if the file already exists; if so return error */
@@ -5269,13 +5783,13 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_BPLUS_NOMATCH) &&
         (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) 
     {
-        osi_Log2(smb_logp, "  lookup returns %ld for [%s]", code,
-                 osi_LogSaveString(smb_logp, newLastNamep));
+        osi_Log2(smb_logp, "  lookup returns %ld for [%S]", code,
+                 osi_LogSaveClientString(smb_logp, newLastNamep));
 
         /* Check if the old and the new names differ only in case. If so return
          * success, else return CM_ERROR_EXISTS 
          */
-        if (!code && oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
+        if (!code && oldDscp == newDscp && !cm_ClientStrCmpI(oldLastNamep, newLastNamep)) {
 
             /* This would be a success only if the old file is *as same as* the new file */
             code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH, userp, &req, &tmpscp2);
@@ -5300,6 +5814,9 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
         cm_ReleaseSCache(newDscp);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseUser(userp);
+
+        free(rock.maskp);
+        rock.maskp = NULL;
         return code; 
     }
 
@@ -5316,10 +5833,10 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     }
     osi_Log1(smb_logp, "smb_RenameProc returns %ld", code);
 
-    if (code == CM_ERROR_STOPNOW && rock.oldName[0] != '\0') {
-       code = cm_Rename(rock.odscp, rock.oldName,
+    if (code == CM_ERROR_STOPNOW && rock.fsOldName[0] != '\0') {
+       code = cm_Rename(rock.odscp, rock.fsOldName, rock.clOldName,
                          rock.ndscp, rock.newNamep, rock.userp,
-                         rock.reqp);   
+                         rock.reqp);
         /* if the call worked, stop doing the search now, since we
          * really only want to rename one file.
          */
@@ -5338,17 +5855,17 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
         if (oldDscp == newDscp) {
             if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
                 smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
-                                  filter, oldDscp, oldLastNamep,
-                                  newLastNamep, TRUE);
+                                 filter, oldDscp, rock.clOldName,
+                                 newLastNamep, TRUE);
         } else {
             if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH)
                 smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME,
-                                  filter, oldDscp, oldLastNamep,
+                                  filter, oldDscp, rock.clOldName,
                                   NULL, TRUE);
             if (newDscp->flags & CM_SCACHEFLAG_ANYWATCH)
                 smb_NotifyChange(FILE_ACTION_RENAMED_NEW_NAME,
-                                  filter, newDscp, newLastNamep,
-                                  NULL, TRUE);
+                                 filter, newDscp, newLastNamep,
+                                 NULL, TRUE);
         }
     }
 
@@ -5357,11 +5874,15 @@ smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, i
     cm_ReleaseUser(userp);
     cm_ReleaseSCache(oldDscp);
     cm_ReleaseSCache(newDscp);
+
+    free(rock.maskp);
+    rock.maskp = NULL;
+
     return code;
 }       
 
 long 
-smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp) 
+smb_Link(smb_vc_t *vcp, smb_packet_t *inp, clientchar_t * oldPathp, clientchar_t * newPathp) 
 {
     long code = 0;
     cm_space_t *spacep = NULL;
@@ -5370,11 +5891,11 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
     cm_scache_t *tmpscp= NULL;
     cm_scache_t *tmpscp2 = NULL;
     cm_scache_t *sscp = NULL;
-    char *oldLastNamep;
-    char *newLastNamep;
+    clientchar_t *oldLastNamep;
+    clientchar_t *newLastNamep;
     cm_user_t *userp;
     int caseFold;
-    char *tidPathp;
+    clientchar_t *tidPathp;
     DWORD filter;
     cm_req_t req;
 
@@ -5386,14 +5907,14 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
         return CM_ERROR_NOSUCHPATH;
     }
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD;
 
     spacep = inp->spacep;
-    smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
+    smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
     
-    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
+    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
                     userp, tidPathp, &req, &oldDscp);
     if (code) {
         cm_ReleaseUser(userp);
@@ -5402,7 +5923,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
         
 #ifdef DFS_SUPPORT
     if (oldDscp->fileType == CM_SCACHETYPE_DFSLINK) {
-        int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->data);
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(oldDscp, tidPathp, spacep->wdata);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseUser(userp);
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
@@ -5412,8 +5933,8 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
     }
 #endif /* DFS_SUPPORT */
 
-    smb_StripLastComponent(spacep->data, &newLastNamep, newPathp);
-    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold,
+    smb_StripLastComponent(spacep->wdata, &newLastNamep, newPathp);
+    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold,
                     userp, tidPathp, &req, &newDscp);
     if (code) {
         cm_ReleaseSCache(oldDscp);
@@ -5423,7 +5944,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
 
 #ifdef DFS_SUPPORT
     if (newDscp->fileType == CM_SCACHETYPE_DFSLINK) {
-        int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->data);
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(newDscp, tidPathp, spacep->wdata);
         cm_ReleaseSCache(newDscp);
         cm_ReleaseSCache(oldDscp);
         cm_ReleaseUser(userp);
@@ -5457,7 +5978,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
         newLastNamep++;
 
     /* now lookup the old name */
-    osi_Log1(smb_logp,"  looking up [%s]", osi_LogSaveString(smb_logp,oldLastNamep));
+    osi_Log1(smb_logp,"  looking up [%S]", osi_LogSaveClientString(smb_logp,oldLastNamep));
     code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH | CM_FLAG_CASEFOLD, userp, &req, &sscp);
     if (code) {
         cm_ReleaseSCache(oldDscp);
@@ -5471,8 +5992,8 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
     if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_BPLUS_NOMATCH) && 
         (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) 
     {
-        osi_Log2(smb_logp, "  lookup returns %ld for [%s]", code,
-                 osi_LogSaveString(smb_logp, newLastNamep));
+        osi_Log2(smb_logp, "  lookup returns %ld for [%S]", code,
+                 osi_LogSaveClientString(smb_logp, newLastNamep));
 
         /* if the existing link is to the same file, then we return success */
         if (!code) {
@@ -5494,7 +6015,7 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
     }
 
     /* now create the hardlink */
-    osi_Log1(smb_logp,"  Attempting to create new link [%s]", osi_LogSaveString(smb_logp, newLastNamep));
+    osi_Log1(smb_logp,"  Attempting to create new link [%S]", osi_LogSaveClientString(smb_logp, newLastNamep));
     code = cm_Link(newDscp, newLastNamep, sscp, 0, userp, &req);
     osi_Log1(smb_logp,"  Link returns 0x%x", code);
 
@@ -5516,25 +6037,22 @@ smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp)
     return code;
 }
 
+/* SMB_COM_RENAME */
 long 
 smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    char *oldPathp;
-    char *newPathp;
-    char *tp;
+    clientchar_t *oldPathp;
+    clientchar_t *newPathp;
+    unsigned char *tp;
     long code;
 
     tp = smb_GetSMBData(inp, NULL);
-    oldPathp = smb_ParseASCIIBlock(tp, &tp);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(oldPathp,oldPathp);
-    newPathp = smb_ParseASCIIBlock(tp, &tp);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(newPathp,newPathp);
+    oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+    newPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
 
-    osi_Log2(smb_logp, "smb rename [%s] to [%s]",
-             osi_LogSaveString(smb_logp, oldPathp),
-             osi_LogSaveString(smb_logp, newPathp));
+    osi_Log2(smb_logp, "smb rename [%S] to [%S]",
+             osi_LogSaveClientString(smb_logp, oldPathp),
+             osi_LogSaveClientString(smb_logp, newPathp));
 
     code = smb_Rename(vcp,inp,oldPathp,newPathp,0);
 
@@ -5548,7 +6066,7 @@ typedef struct smb_rmdirRock {
     cm_scache_t *dscp;
     cm_user_t *userp;
     cm_req_t *reqp;
-    char *maskp;               /* pointer to the star pattern */
+    normchar_t *maskp;         /* pointer to the star pattern */
     int flags;
     int any;
     cm_dirEntryList_t * matches;
@@ -5559,56 +6077,53 @@ int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper
     long code = 0;
     smb_rmdirRock_t *rockp;
     int match;
-    char shortName[13];
-    char *matchName;
+    normchar_t matchName[MAX_PATH];
         
     rockp = (smb_rmdirRock_t *) vrockp;
 
-    matchName = dep->name;
+    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
     if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
-        match = (cm_stricmp(matchName, rockp->maskp) == 0);
+        match = (cm_ClientStrCmpI(matchName, rockp->maskp) == 0);
     else
-        match = (strcmp(matchName, rockp->maskp) == 0);
+        match = (cm_ClientStrCmp(matchName, rockp->maskp) == 0);
     if (!match &&
          (rockp->flags & SMB_MASKFLAG_TILDE) &&
-         !cm_Is8Dot3(dep->name)) {
-        cm_Gen8Dot3Name(dep, shortName, NULL);
-        matchName = shortName;
-        match = (cm_stricmp(matchName, rockp->maskp) == 0);
+         !cm_Is8Dot3(matchName)) {
+        cm_Gen8Dot3Name(dep, matchName, NULL);
+        match = (cm_ClientStrCmpI(matchName, rockp->maskp) == 0);
     }       
 
     if (match) {
-            rockp->any = 1;
+        rockp->any = 1;
         cm_DirEntryListAdd(dep->name, &rockp->matches);
     }
 
     return 0;
 }
 
+
 long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     long code = 0;
-    char *pathp;
-    char *tp;
+    clientchar_t *pathp;
+    unsigned char *tp;
     cm_space_t *spacep;
     cm_scache_t *dscp;
-    char *lastNamep;
+    clientchar_t *lastNamep;
     smb_rmdirRock_t rock;
     cm_user_t *userp;
     osi_hyper_t thyper;
     int caseFold;
-    char *tidPathp;
+    clientchar_t *tidPathp;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     tp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(tp, &tp);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
+    pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
 
     spacep = inp->spacep;
-    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
     userp = smb_GetUserFromVCP(vcp, inp);
 
@@ -5619,7 +6134,7 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
+    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold | CM_FLAG_FOLLOW,
                     userp, tidPathp, &req, &dscp);
 
     if (code) {
@@ -5629,7 +6144,7 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         
 #ifdef DFS_SUPPORT
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
-        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->wdata);
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
@@ -5646,8 +6161,8 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         lastNamep++;
        
     rock.any = 0;
-    rock.maskp = lastNamep;
-    rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+    rock.maskp = cm_ClientStringToNormStringAlloc(lastNamep, -1, NULL);
+    rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
 
     thyper.LowPart = 0;
     thyper.HighPart = 0;
@@ -5669,15 +6184,19 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         cm_dirEntryList_t * entry;
 
         for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
+            clientchar_t clientName[MAX_PATH];
+
+            cm_FsStringToClientString(entry->name, -1, clientName, lengthof(clientName));
+
             osi_Log1(smb_logp, "Removing directory %s",
                      osi_LogSaveString(smb_logp, entry->name));
 
-            code = cm_RemoveDir(dscp, entry->name, userp, &req);
+            code = cm_RemoveDir(dscp, entry->name, clientName, userp, &req);
 
             if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                 smb_NotifyChange(FILE_ACTION_REMOVED,
                                  FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
-                                 dscp, entry->name, NULL, TRUE);
+                                 dscp, clientName, NULL, TRUE);
         }
     }
 
@@ -5689,9 +6208,14 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
     if (code == 0 && !rock.any)
         code = CM_ERROR_NOSUCHFILE;        
+
+    free(rock.maskp);
+    rock.maskp = NULL;
+
     return code;
 }
 
+/* SMB_COM_FLUSH */
 long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     unsigned short fid;
@@ -5700,7 +6224,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     long code = 0;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     fid = smb_GetSMBParm(inp, 0);
 
@@ -5728,7 +6252,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     userp = smb_GetUserFromVCP(vcp, inp);
 
     lock_ObtainMutex(&fidp->mx);
-    if (fidp->flags & SMB_FID_OPENWRITE) {
+    if ((fidp->flags & SMB_FID_OPENWRITE) && smb_AsyncStore != 2) {
        cm_scache_t * scp = fidp->scp;
        cm_HoldSCache(scp);
        lock_ReleaseMutex(&fidp->mx);
@@ -5747,50 +6271,62 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 }
 
 struct smb_FullNameRock {
-    char *name;
-    cm_scache_t *vnode;
-    char *fullName;
+    clientchar_t *name;
+    cm_scache_t  *vnode;
+    clientchar_t *fullName;
+    fschar_t     *originalName;
 };
 
 int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
                      osi_hyper_t *offp)
 {
-    char shortName[13];
+    normchar_t matchName[MAX_PATH];
     struct smb_FullNameRock *vrockp;
 
     vrockp = (struct smb_FullNameRock *)rockp;
 
-    if (!cm_Is8Dot3(dep->name)) {
+    cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+
+    if (!cm_Is8Dot3(matchName)) {
+        clientchar_t shortName[13];
+
         cm_Gen8Dot3Name(dep, shortName, NULL);
 
-        if (cm_stricmp(shortName, vrockp->name) == 0) {
-            vrockp->fullName = strdup(dep->name);
+        if (cm_ClientStrCmpIA(shortName, vrockp->name) == 0) {
+            vrockp->fullName = cm_ClientStrDup(matchName);
+            vrockp->originalName = cm_FsStrDup(dep->name);
             return CM_ERROR_STOPNOW;
         }
     }
-    if (cm_stricmp(dep->name, vrockp->name) == 0 &&
+    if (cm_ClientStrCmpI(matchName, vrockp->name) == 0 &&
         ntohl(dep->fid.vnode) == vrockp->vnode->fid.vnode &&
         ntohl(dep->fid.unique) == vrockp->vnode->fid.unique) {
-        vrockp->fullName = strdup(dep->name);
+        vrockp->fullName = cm_ClientStrDup(matchName);
+        vrockp->originalName = cm_FsStrDup(dep->name);
         return CM_ERROR_STOPNOW;
     }
     return 0;
 }
 
-void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, char *pathp,
-                  char **newPathp, cm_user_t *userp, cm_req_t *reqp)
+void smb_FullName(cm_scache_t *dscp, cm_scache_t *scp, clientchar_t *pathp,
+                  clientchar_t **newPathp, fschar_t ** originalPathp,
+                  cm_user_t *userp, cm_req_t *reqp)
 {
     struct smb_FullNameRock rock;
     long code = 0;
 
+    memset(&rock, 0, sizeof(rock));
     rock.name = pathp;
     rock.vnode = scp;
 
     code = cm_ApplyDir(dscp, smb_FullNameProc, &rock, NULL, userp, reqp, NULL); 
-    if (code == CM_ERROR_STOPNOW)
+    if (code == CM_ERROR_STOPNOW) {
         *newPathp = rock.fullName;
-    else
-        *newPathp = strdup(pathp);
+        *originalPathp = rock.originalName;
+    } else {
+        *newPathp = cm_ClientStrDup(pathp);
+        *originalPathp = cm_ClientStringToFsStringAlloc(pathp, -1, NULL);
+    }
 }
 
 long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
@@ -5798,10 +6334,9 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
     long code = 0;
     cm_req_t req;
     cm_scache_t *dscp = NULL;
-    char *pathp = NULL;
+    clientchar_t *pathp = NULL;
     cm_scache_t * scp = NULL;
     cm_scache_t *delscp = NULL;
-    int deleted = 0;
     int nullcreator = 0;
 
     osi_Log4(smb_logp, "smb_CloseFID Closing fidp 0x%x (fid=%d scp=0x%x vcp=0x%x)",
@@ -5820,15 +6355,15 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
        lock_ReleaseMutex(&fidp->mx);
     }
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     lock_ObtainWrite(&smb_rctLock);
-    if (fidp->delete) {
+    if (fidp->deleteOk) {
        osi_Log0(smb_logp, "  Fid already closed.");
        lock_ReleaseWrite(&smb_rctLock);
        return CM_ERROR_BADFD;
     }
-    fidp->delete = 1;
+    fidp->deleteOk = 1;
     lock_ReleaseWrite(&smb_rctLock);
 
     lock_ObtainMutex(&fidp->mx);
@@ -5838,7 +6373,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
     }
 
     if (fidp->NTopen_pathp) {
-       pathp = strdup(fidp->NTopen_pathp);
+       pathp = cm_ClientStrDup(fidp->NTopen_pathp);
     }
 
     if (fidp->scp) {
@@ -5863,9 +6398,11 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
             CompensateForSmbClientLastWriteTimeBugs(&dosTime);
             smb_UnixTimeFromDosUTime(&fidp->scp->clientModTime, dosTime);
         }
-       lock_ReleaseMutex(&fidp->mx);
-        code = cm_FSync(scp, userp, &req);
-       lock_ObtainMutex(&fidp->mx);
+        if (smb_AsyncStore != 2) {
+            lock_ReleaseMutex(&fidp->mx);
+            code = cm_FSync(scp, userp, &req);
+            lock_ObtainMutex(&fidp->mx);
+        }
     }
     else 
         code = 0;
@@ -5881,7 +6418,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
        /* CM_UNLOCK_BY_FID doesn't look at the process ID.  We pass
            in zero. */
         key = cm_GenerateKey(vcp->vcID, 0, fidp->fid);
-        lock_ObtainMutex(&scp->mx);
+        lock_ObtainWrite(&scp->rw);
 
         tcode = cm_SyncOp(scp, NULL, userp, &req, 0,
                           CM_SCACHESYNC_NEEDCALLBACK
@@ -5900,12 +6437,13 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
 
     post_syncopdone:
 
-        lock_ReleaseMutex(&scp->mx);
+        lock_ReleaseWrite(&scp->rw);
        lock_ObtainMutex(&fidp->mx);
     }
 
     if (fidp->flags & SMB_FID_DELONCLOSE) {
-        char *fullPathp;
+        clientchar_t *fullPathp = NULL;
+        fschar_t *originalNamep = NULL;
 
        lock_ReleaseMutex(&fidp->mx);
 
@@ -5914,27 +6452,30 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
             cm_HoldSCache(scp);
             delscp = scp;
         }
-        smb_FullName(dscp, delscp, pathp, &fullPathp, userp, &req);
+        smb_FullName(dscp, delscp, pathp, &fullPathp, &originalNamep, userp, &req);
         if (delscp->fileType == CM_SCACHETYPE_DIRECTORY) {
-            code = cm_RemoveDir(dscp, fullPathp, userp, &req);
+            code = cm_RemoveDir(dscp, originalNamep, fullPathp, userp, &req);
            if (code == 0) {
-               deleted = 1;
                if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
                    smb_NotifyChange(FILE_ACTION_REMOVED,
                                      FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_CREATION,
                                      dscp, fullPathp, NULL, TRUE);
            }
         } else {
-            code = cm_Unlink(dscp, fullPathp, userp, &req);
+            code = cm_Unlink(dscp, originalNamep, fullPathp, userp, &req);
            if (code == 0) {                            
-               deleted = 1;
                if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
                    smb_NotifyChange(FILE_ACTION_REMOVED,
                                      FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
                                      dscp, fullPathp, NULL, TRUE);
            }
         }
-        free(fullPathp);
+
+        if (fullPathp)
+            free(fullPathp);
+        if (originalNamep)
+            free(originalNamep);
+
        lock_ObtainMutex(&fidp->mx);
        fidp->flags &= ~SMB_FID_DELONCLOSE;
     }
@@ -5972,21 +6513,15 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
        cm_ReleaseSCache(dscp);
 
     if (delscp) {
-       if (deleted) {
-           lock_ObtainMutex(&delscp->mx);
-           if (deleted)
-               delscp->flags |= CM_SCACHEFLAG_DELETED;
-           lock_ReleaseMutex(&delscp->mx);
-       }
         cm_ReleaseSCache(delscp);
     }
 
     if (scp) {
-       lock_ObtainMutex(&scp->mx);
+       lock_ObtainWrite(&scp->rw);
         if (nullcreator && scp->creator == userp)
             scp->creator = NULL;
        scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
-       lock_ReleaseMutex(&scp->mx);
+       lock_ReleaseWrite(&scp->rw);
        cm_ReleaseSCache(scp);
     }
 
@@ -5996,6 +6531,7 @@ long smb_CloseFID(smb_vc_t *vcp, smb_fid_t *fidp, cm_user_t *userp,
     return code;
 }
 
+/* SMB_COM_CLOSE */
 long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     unsigned short fid;
@@ -6027,7 +6563,7 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 /*
  * smb_ReadData -- common code for Read, Read And X, and Raw Read
  */
-long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char *op,
        cm_user_t *userp, long *readp)
 {
     osi_hyper_t offset;
@@ -6038,20 +6574,35 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     osi_hyper_t thyper;
     osi_hyper_t lastByte;
     osi_hyper_t bufferOffset;
-    long bufIndex, nbytes;
+    long bufIndex;
+    afs_uint32 nbytes;
     int chunk;
     int sequential = (fidp->flags & SMB_FID_SEQUENTIAL);
     cm_req_t req;
 
-    cm_InitReq(&req);
+    osi_Log3(smb_logp, "smb_ReadData fid %d, off 0x%x, size 0x%x",
+              fidp->fid, offsetp->LowPart, count);
+
+    *readp = 0;
+
+    lock_ObtainMutex(&fidp->mx);
+    /* make sure we have a readable FD */
+    if (!(fidp->flags & SMB_FID_OPENREAD_LISTDIR)) {
+       osi_Log2(smb_logp, "smb_ReadData fid %d not OPENREAD_LISTDIR flags 0x%x",
+                 fidp->fid, fidp->flags);
+       lock_ReleaseMutex(&fidp->mx);
+        code = CM_ERROR_BADFDOP;
+        goto done2;
+    }
+    
+    smb_InitReq(&req);
 
     bufferp = NULL;
     offset = *offsetp;
 
-    lock_ObtainMutex(&fidp->mx);
     scp = fidp->scp;
     cm_HoldSCache(scp);
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
 
     if (offset.HighPart == 0) {
         chunk = offset.LowPart >> cm_logChunkSize;
@@ -6111,13 +6662,11 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                 buf_Release(bufferp);
                 bufferp = NULL;
             }
-            lock_ReleaseMutex(&scp->mx);
+            lock_ReleaseWrite(&scp->rw);
 
-            lock_ObtainRead(&scp->bufCreateLock);
             code = buf_Get(scp, &thyper, &bufferp);
-            lock_ReleaseRead(&scp->bufCreateLock);
 
-            lock_ObtainMutex(&scp->mx);
+            lock_ObtainWrite(&scp->rw);
             if (code) goto done;
             bufferOffset = thyper;
 
@@ -6165,38 +6714,40 @@ long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     } /* while 1 */
 
   done:
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     if (bufferp)
         buf_Release(bufferp);
 
     if (code == 0 && sequential)
-        cm_ConsiderPrefetch(scp, &lastByte, userp, &req);
+        cm_ConsiderPrefetch(scp, &lastByte, *readp, userp, &req);
 
     cm_ReleaseSCache(scp);
 
+  done2:
+    osi_Log3(smb_logp, "smb_ReadData fid %d returns 0x%x read %d bytes",
+              fidp->fid, code, *readp);
     return code;
 }
 
 /*
  * smb_WriteData -- common code for Write and Raw Write
  */
-long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
+long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, afs_uint32 count, char *op,
        cm_user_t *userp, long *writtenp)
 {
-    osi_hyper_t offset;
+    osi_hyper_t offset = *offsetp;
     long code = 0;
     long written = 0;
-    cm_scache_t *scp;
+    cm_scache_t *scp = NULL;
     osi_hyper_t fileLength;    /* file's length at start of write */
     osi_hyper_t minLength;     /* don't read past this */
     afs_uint32 nbytes;         /* # of bytes to transfer this iteration */
-    cm_buf_t *bufferp;
+    cm_buf_t *bufferp = NULL;
     osi_hyper_t thyper;                /* hyper tmp variable */
     osi_hyper_t bufferOffset;
     afs_uint32 bufIndex;               /* index in buffer where our data is */
-    int doWriteBack;
-    osi_hyper_t writeBackOffset;/* offset of region to write back when
-                                 * I/O is done */
+    int doWriteBack = 0;
+    osi_hyper_t writeBackOffset;/* offset of region to write back when I/O is done */
     DWORD filter = 0;
     cm_req_t req;
 
@@ -6205,12 +6756,6 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
     *writtenp = 0;
 
-    cm_InitReq(&req);
-
-    bufferp = NULL;
-    doWriteBack = 0;
-    offset = *offsetp;
-
     lock_ObtainMutex(&fidp->mx);
     /* make sure we have a writable FD */
     if (!(fidp->flags & SMB_FID_OPENWRITE)) {
@@ -6218,14 +6763,16 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                  fidp->fid, fidp->flags);
        lock_ReleaseMutex(&fidp->mx);
         code = CM_ERROR_BADFDOP;
-        goto done;
+        goto done2;
     }
     
+    smb_InitReq(&req);
+
     scp = fidp->scp;
     cm_HoldSCache(scp);
     lock_ReleaseMutex(&fidp->mx);
 
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     /* start by looking up the file's end */
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK
@@ -6257,15 +6804,23 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     /* now, if the new position (thyper) and the old (offset) are in
      * different storeback windows, remember to store back the previous
      * storeback window when we're done with the write.
+     *
+     * the purpose of this logic is to slow down the CIFS client 
+     * in order to avoid the client disconnecting during the CLOSE
+     * operation if there are too many dirty buffers left to write
+     * than can be accomplished during 45 seconds.  This used to be
+     * based upon cm_chunkSize but we desire cm_chunkSize to be large
+     * so that we can read larger amounts of data at a time.
      */
-    if ((thyper.LowPart & (-cm_chunkSize)) !=
-         (offset.LowPart & (-cm_chunkSize))) {
+    if (smb_AsyncStore == 1 && 
+         (thyper.LowPart & ~(smb_AsyncStoreSize-1)) !=
+         (offset.LowPart & ~(smb_AsyncStoreSize-1))) {
         /* they're different */
         doWriteBack = 1;
         writeBackOffset.HighPart = offset.HighPart;
-        writeBackOffset.LowPart = offset.LowPart & (-cm_chunkSize);
+        writeBackOffset.LowPart = offset.LowPart & ~(smb_AsyncStoreSize-1);
     }
-        
+
     *writtenp = count;
 
     /* now, copy the data one buffer at a time, until we've filled the
@@ -6292,14 +6847,12 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                 buf_Release(bufferp);
                 bufferp = NULL;
             }  
-            lock_ReleaseMutex(&scp->mx);
+            lock_ReleaseWrite(&scp->rw);
 
-            lock_ObtainRead(&scp->bufCreateLock);
             code = buf_Get(scp, &thyper, &bufferp);
-            lock_ReleaseRead(&scp->bufCreateLock);
 
             lock_ObtainMutex(&bufferp->mx);
-            lock_ObtainMutex(&scp->mx);
+            lock_ObtainWrite(&scp->rw);
             if (code) goto done;
 
             bufferOffset = thyper;
@@ -6338,7 +6891,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                                                                                ConvertLongToLargeInteger(count)),
                                                                minLength))) {
                     if (count < cm_data.buf_blockSize
-                         && bufferp->dataVersion == -1)
+                         && bufferp->dataVersion == CM_BUF_VERSION_BAD)
                         memset(bufferp->datap, 0,
                                 cm_data.buf_blockSize);
                     bufferp->dataVersion = scp->dataVersion;
@@ -6350,9 +6903,9 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
                 lock_ReleaseMutex(&bufferp->mx);
                 code = cm_GetBuffer(scp, bufferp, NULL, userp,
                                      &req);
-                lock_ReleaseMutex(&scp->mx);
+                lock_ReleaseWrite(&scp->rw);
                 lock_ObtainMutex(&bufferp->mx);
-                lock_ObtainMutex(&scp->mx);
+                lock_ObtainWrite(&scp->rw);
                 if (code) break;
             }
             if (code) {
@@ -6375,15 +6928,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
 
         /* now copy the data */
        memcpy(bufferp->datap + bufIndex, op, nbytes);
-        buf_SetDirty(bufferp, bufIndex, nbytes);
-
-        /* and record the last writer */
-        if (bufferp->userp != userp) {
-            cm_HoldUser(userp);
-            if (bufferp->userp) 
-                cm_ReleaseUser(bufferp->userp);
-            bufferp->userp = userp;
-        }
+        buf_SetDirty(bufferp, bufIndex, nbytes, userp);
 
         /* adjust counters, pointers, etc. */
         op += nbytes;
@@ -6395,7 +6940,7 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     } /* while 1 */
 
   done:
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
 
     if (bufferp) {
         lock_ReleaseMutex(&bufferp->mx);
@@ -6411,27 +6956,37 @@ long smb_WriteData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op,
     }       
     lock_ReleaseMutex(&fidp->mx);
 
-    if (code == 0 && doWriteBack) {
-        long code2;
-        lock_ObtainMutex(&scp->mx);
-        osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
-                  fidp->fid);
-        code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
-        osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns 0x%x",
-                  fidp->fid, code2);
-        lock_ReleaseMutex(&scp->mx);
-        cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
-                            writeBackOffset.HighPart, cm_chunkSize, 0, userp);
-       /* cm_SyncOpDone is called at the completion of cm_BkgStore */
+    if (code == 0) {
+        if (smb_AsyncStore > 0) {
+            if (doWriteBack) {
+                long code2;
+
+                lock_ObtainWrite(&scp->rw);
+                osi_Log1(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE",
+                          fidp->fid);
+                code2 = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
+                osi_Log2(smb_logp, "smb_WriteData fid %d calling cm_SyncOp ASYNCSTORE returns 0x%x",
+                          fidp->fid, code2);
+                lock_ReleaseWrite(&scp->rw);
+                cm_QueueBKGRequest(scp, cm_BkgStore, writeBackOffset.LowPart,
+                                    writeBackOffset.HighPart, 
+                                    smb_AsyncStoreSize, 0, userp);
+                /* cm_SyncOpDone is called at the completion of cm_BkgStore */
+            }
+        } else {
+            cm_BufWrite(scp, offsetp, *writtenp, 0, userp, &req);
+        }
     }
 
     cm_ReleaseSCache(scp);
 
+  done2:
     osi_Log3(smb_logp, "smb_WriteData fid %d returns 0x%x written %d bytes",
               fidp->fid, code, *writtenp);
     return code;
 }
 
+/* SMB_COM_WRITE */
 long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     unsigned short fd;
@@ -6441,6 +6996,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     long written = 0, total_written = 0;
     unsigned pid;
     smb_fid_t *fidp;
+    smb_t* smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp;
     cm_attr_t truncAttr;       /* attribute struct used for truncating file */
@@ -6488,7 +7044,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LARGE_INTEGER LOffset;
         LARGE_INTEGER LLength;
 
-        pid = ((smb_t *) inp)->pid;
+        pid = smbp->pid;
         key = cm_GenerateKey(vcp->vcID, pid, fd);
 
         LOffset.HighPart = offset.HighPart;
@@ -6496,9 +7052,9 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LLength.HighPart = 0;
         LLength.LowPart = count;
 
-        lock_ObtainMutex(&fidp->scp->mx);
+        lock_ObtainWrite(&fidp->scp->rw);
         code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
-        lock_ReleaseMutex(&fidp->scp->mx);
+        lock_ReleaseWrite(&fidp->scp->rw);
 
         if (code) {
            osi_Log1(smb_logp, "smb_ReceiveCoreWrite lock check failure 0x%x", code);
@@ -6512,7 +7068,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        osi_Log1(smb_logp, "smb_ReceiveCoreWrite truncation to length 0x%x", offset.LowPart);
         
-        cm_InitReq(&req);
+        smb_InitReq(&req);
 
         truncAttr.mask = CM_ATTRMASK_LENGTH;
         truncAttr.length.LowPart = offset.LowPart;
@@ -6635,6 +7191,7 @@ long smb_ReceiveCoreWriteRawDummy(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
     return 0;
 }
 
+/* SMB_COM_WRITE_RAW */
 long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, raw_write_cont_t *rwcp)
 {
     osi_hyper_t offset;
@@ -6642,6 +7199,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     long totalCount;
     unsigned short fd;
     smb_fid_t *fidp;
+    smb_t *smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp;
     char *op;
@@ -6707,7 +7265,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         LARGE_INTEGER LOffset;
         LARGE_INTEGER LLength;
 
-        pid = ((smb_t *) inp)->pid;
+        pid = smbp->pid;
         key = cm_GenerateKey(vcp->vcID, pid, fd);
 
         LOffset.HighPart = offset.HighPart;
@@ -6715,9 +7273,9 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         LLength.HighPart = 0;
         LLength.LowPart = count;
 
-        lock_ObtainMutex(&fidp->scp->mx);
+        lock_ObtainWrite(&fidp->scp->rw);
         code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
-        lock_ReleaseMutex(&fidp->scp->mx);
+        lock_ReleaseWrite(&fidp->scp->rw);
 
         if (code) {
             smb_ReleaseFID(fidp);
@@ -6812,6 +7370,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     return 0;
 }
 
+/* SMB_COM_READ */
 long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     osi_hyper_t offset;
@@ -6819,6 +7378,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     unsigned short fd;
     unsigned pid;
     smb_fid_t *fidp;
+    smb_t *smbp = (smb_t*) inp;
     long code = 0;
     cm_user_t *userp;
     char *op;
@@ -6855,7 +7415,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LARGE_INTEGER LOffset, LLength;
         cm_key_t key;
 
-        pid = ((smb_t *) inp)->pid;
+        pid = smbp->pid;
         key = cm_GenerateKey(vcp->vcID, pid, fd);
 
         LOffset.HighPart = 0;
@@ -6863,9 +7423,9 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LLength.HighPart = 0;
         LLength.LowPart = count;
         
-        lock_ObtainMutex(&fidp->scp->mx);
+        lock_ObtainWrite(&fidp->scp->rw);
         code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
-        lock_ReleaseMutex(&fidp->scp->mx);
+        lock_ReleaseWrite(&fidp->scp->rw);
     }
     if (code) {
         smb_ReleaseFID(fidp);
@@ -6908,23 +7468,24 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     return code;
 }
 
+/* SMB_COM_CREATE_DIRECTORY */
 long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    char *pathp;
+    clientchar_t *pathp;
     long code = 0;
     cm_space_t *spacep;
-    char *tp;
+    unsigned char *tp;
     cm_user_t *userp;
     cm_scache_t *dscp;                 /* dir we're dealing with */
     cm_scache_t *scp;                  /* file we're creating */
     cm_attr_t setAttr;
     int initialModeBits;
-    char *lastNamep;
+    clientchar_t *lastNamep;
     int caseFold;
-    char *tidPathp;
+    clientchar_t *tidPathp;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     scp = NULL;
         
@@ -6932,15 +7493,13 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     initialModeBits = 0777;
         
     tp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(tp, &tp);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
+    pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
 
-    if (strcmp(pathp, "\\") == 0)
+    if (cm_ClientStrCmp(pathp, _C("\\")) == 0)
         return CM_ERROR_EXISTS;
 
     spacep = inp->spacep;
-    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
     userp = smb_GetUserFromVCP(vcp, inp);
 
@@ -6952,7 +7511,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         return CM_ERROR_NOSUCHPATH;
     }
 
-    code = cm_NameI(cm_data.rootSCachep, spacep->data,
+    code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
                     caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH,
                     userp, tidPathp, &req, &dscp);
 
@@ -6963,7 +7522,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         
 #ifdef DFS_SUPPORT
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
-        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->wdata);
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
@@ -6991,7 +7550,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         
     setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
     setAttr.clientModTime = time(NULL);
-    code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req);
+    code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req, NULL);
     if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
         smb_NotifyChange(FILE_ACTION_ADDED,
                          FILE_NOTIFY_CHANGE_DIR_NAME,
@@ -7013,7 +7572,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
     return 0;
 }
 
-BOOL smb_IsLegalFilename(char *filename)
+BOOL smb_IsLegalFilename(clientchar_t *filename)
 {
     /* 
      *  Find the longest substring of filename that does not contain
@@ -7021,18 +7580,19 @@ BOOL smb_IsLegalFilename(char *filename)
      *  than the length of the whole string, then one or more of the
      *  illegal chars is in filename. 
      */
-    if (strcspn(filename, illegalChars) < strlen(filename))
+    if (cm_ClientStrCSpn(filename, illegalChars) < cm_ClientStrLen(filename))
         return FALSE;
 
     return TRUE;
-}        
+}
 
+/* SMB_COM_CREATE and SMB_COM_CREATE_NEW */
 long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-    char *pathp;
+    clientchar_t *pathp;
     long code = 0;
     cm_space_t *spacep;
-    char *tp;
+    unsigned char *tp;
     int excl;
     cm_user_t *userp;
     cm_scache_t *dscp;                 /* dir we're dealing with */
@@ -7041,14 +7601,14 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     int initialModeBits;
     smb_fid_t *fidp;
     int attributes;
-    char *lastNamep;
+    clientchar_t *lastNamep;
     int caseFold;
     afs_uint32 dosTime;
-    char *tidPathp;
+    clientchar_t *tidPathp;
     cm_req_t req;
     int created = 0;                   /* the file was new */
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
 
     scp = NULL;
     excl = (inp->inCom == 0x03)? 0 : 1;
@@ -7062,12 +7622,10 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        initialModeBits &= ~0222;
         
     tp = smb_GetSMBData(inp, NULL);
-    pathp = smb_ParseASCIIBlock(tp, &tp);
-    if (smb_StoreAnsiFilenames)
-        OemToChar(pathp,pathp);
+    pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
 
     spacep = inp->spacep;
-    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
     userp = smb_GetUserFromVCP(vcp, inp);
 
@@ -7078,7 +7636,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_ReleaseUser(userp);
         return CM_ERROR_NOSUCHPATH;
     }
-    code = cm_NameI(cm_data.rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW,
+    code = cm_NameI(cm_data.rootSCachep, spacep->wdata, caseFold | CM_FLAG_FOLLOW,
                     userp, tidPathp, &req, &dscp);
 
     if (code) {
@@ -7088,7 +7646,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
 #ifdef DFS_SUPPORT
     if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
-        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->data);
+        int pnc = cm_VolStatus_Notify_DFS_Mapping(dscp, tidPathp, spacep->wdata);
         cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
@@ -7109,7 +7667,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (!smb_IsLegalFilename(lastNamep))
         return CM_ERROR_BADNTFILENAME;
 
-    osi_Log1(smb_logp, "SMB receive create [%s]", osi_LogSaveString( smb_logp, pathp ));
+    osi_Log1(smb_logp, "SMB receive create [%S]", osi_LogSaveClientString( smb_logp, pathp ));
 #ifdef DEBUG_VERBOSE
     {
         char *hexp;
@@ -7207,9 +7765,9 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     /* save a pointer to the vnode */
     fidp->scp = scp;
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     scp->flags |= CM_SCACHEFLAG_SMB_FID;
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     
     /* and the user */
     fidp->userp = userp;
@@ -7226,6 +7784,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     return 0;
 }
 
+/* SMB_COM_SEEK */
 long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
     long code = 0;
@@ -7238,7 +7797,7 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     cm_user_t *userp;
     cm_req_t req;
 
-    cm_InitReq(&req);
+    smb_InitReq(&req);
         
     fd = smb_GetSMBParm(inp, 0);
     whence = smb_GetSMBParm(inp, 1);
@@ -7270,7 +7829,7 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     scp = fidp->scp;
     cm_HoldSCache(scp);
     lock_ReleaseMutex(&fidp->mx);
-    lock_ObtainMutex(&scp->mx);
+    lock_ObtainWrite(&scp->rw);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code == 0) {
@@ -7293,7 +7852,7 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         smb_SetSMBParm(outp, 1, (new_offset.LowPart>>16) & 0xffff);
         smb_SetSMBDataLength(outp, 0);
     }
-    lock_ReleaseMutex(&scp->mx);
+    lock_ReleaseWrite(&scp->rw);
     smb_ReleaseFID(fidp);
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
@@ -7394,30 +7953,36 @@ 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);
 
             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",myCrt_Dispatch(inp->inCom),vcp,vcp->lana,vcp->lsn);
+                osi_Log4(smb_logp,"Dispatch %s vcp 0x%p lana %d lsn %d",
+                         opName,vcp,vcp->lana,vcp->lsn);
                 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);
+                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);
+                     smb_LogPacket(inp);
 #endif /* LOG_PACKET */
             }   
 
+            newTime = GetTickCount();
+            osi_Log2(smb_logp, "Dispatch %s duration %d ms", opName, newTime - oldTime);
+
             if (oldGen != sessionGen) {
-                newTime = GetTickCount();
                LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION, 
                         newTime - oldTime, ncbp->ncb_length);
-               osi_Log2(smb_logp, "Pkt straddled session startup, "
-                          "took %d ms, ncb length %d", newTime - oldTime, ncbp->ncb_length);
+               osi_Log3(smb_logp, "Request %s straddled session startup, "
+                          "took %d ms, ncb length %d", opName, newTime - oldTime, ncbp->ncb_length);
             }
-        }
-        else {
+
+            FreeSMBStrings(inp);
+        } else {
             /* bad opcode, fail the request, after displaying it */
             osi_Log1(smb_logp, "Received bad SMB req 0x%X", inp->inCom);
 #ifdef LOG_PACKET
@@ -7732,11 +8297,12 @@ void smb_Server(VOID *parmp)
     UCHAR rc;
     smb_vc_t *vcp = NULL;
     smb_t *smbp;
+    extern void rx_StartClientThread(void);
 
     rx_StartClientThread();
 
-    outncbp = GetNCB();
-    outbufp = GetPacket();
+    outncbp = smb_GetNCB();
+    outbufp = smb_GetPacket();
     outbufp->ncbp = outncbp;
 
     while (1) {
@@ -7826,12 +8392,12 @@ void smb_Server(VOID *parmp)
                    lock_ObtainWrite(&smb_globalLock);
                    dead_sessions[vcp->session] = TRUE;
                    lock_ReleaseWrite(&smb_globalLock);
-                   smb_CleanupDeadVC(vcp);
-                   smb_ReleaseVC(vcp);
-                   vcp = NULL;
                 } else {
                    lock_ReleaseMutex(&vcp->mx);
                }
+                smb_CleanupDeadVC(vcp);
+                smb_ReleaseVC(vcp);
+                vcp = NULL;
             }
             goto doneWithNCB;
 
@@ -7858,31 +8424,33 @@ void smb_Server(VOID *parmp)
         default:
             /* A weird error code.  Log it, sleep, and continue. */
             vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
-           if (vcp) 
+           if (vcp) {
                lock_ObtainMutex(&vcp->mx);
-            if (vcp && vcp->errorCount++ > 3) {
-                osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
-               if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
-                   osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
-                            vcp, vcp->usersp);
-                   vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
-                   lock_ReleaseMutex(&vcp->mx);
-                   lock_ObtainWrite(&smb_globalLock);
-                   dead_sessions[vcp->session] = TRUE;
-                   lock_ReleaseWrite(&smb_globalLock);
-                   smb_CleanupDeadVC(vcp);
-                   smb_ReleaseVC(vcp);
-                   vcp = NULL;
-               } else {
-                   lock_ReleaseMutex(&vcp->mx);
-               }
-               goto doneWithNCB;
-            }
-            else {
-               if (vcp)
+                if (vcp->errorCount++ > 3) {
+                    osi_Log2(smb_logp, "session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
+                    if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+                        osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
+                                 vcp, vcp->usersp);
+                        vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
+                        lock_ReleaseMutex(&vcp->mx);
+                        lock_ObtainWrite(&smb_globalLock);
+                        dead_sessions[vcp->session] = TRUE;
+                        lock_ReleaseWrite(&smb_globalLock);
+                    } else {
+                        lock_ReleaseMutex(&vcp->mx);
+                    }
+                    smb_CleanupDeadVC(vcp);
+                    smb_ReleaseVC(vcp);
+                    vcp = NULL;
+                    goto doneWithNCB;
+                }
+                else {
                    lock_ReleaseMutex(&vcp->mx);
-                thrd_Sleep(1000);
-               thrd_SetEvent(SessionEvents[idx_session]);
+                    smb_ReleaseVC(vcp);
+                    vcp = NULL;
+                    Sleep(10);
+                    thrd_SetEvent(SessionEvents[idx_session]);
+                }
             }
            continue;
         }
@@ -7937,8 +8505,10 @@ void smb_Server(VOID *parmp)
         smbp = (smb_t *)bufp->data;
         outbufp->flags = 0;
 
+#ifndef NOTRACE
         __try
         {
+#endif
             if (smbp->com == 0x1d) {
                 /* Special handling for Write Raw */
                 raw_write_cont_t rwc;
@@ -7976,9 +8546,11 @@ void smb_Server(VOID *parmp)
                 /* TODO: what else needs to be serialized? */
                 smb_DispatchPacket(vcp, bufp, outbufp, ncbp, NULL);
             }
+#ifndef NOTRACE        
         }
         __except( smb_ServerExceptionFilter() ) {
         }
+#endif
 
         smb_concurrentCalls--;
 
@@ -7987,6 +8559,10 @@ void smb_Server(VOID *parmp)
     }
     if (vcp)
         smb_ReleaseVC(vcp);
+    if (outbufp)
+        smb_FreePacket(outbufp);
+    if (outncbp)
+        smb_FreeNCB(outncbp);
 }
 
 /*
@@ -8016,12 +8592,12 @@ void InitNCBslot(int idx)
 {
     struct smb_packet *bufp;
     EVENT_HANDLE retHandle;
-    int i;
+    afs_uint32 i;
     char eventName[MAX_PATH];
 
     osi_assertx( idx < (sizeof(NCBs) / sizeof(NCBs[0])), "invalid index" );
 
-    NCBs[idx] = GetNCB();
+    NCBs[idx] = smb_GetNCB();
     sprintf(eventName,"NCBavails[%d]", idx);
     NCBavails[idx] = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
@@ -8036,7 +8612,7 @@ void InitNCBslot(int idx)
         osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
     for (i=0; i<smb_NumServerThreads; i++)
         NCBreturns[i][idx] = retHandle;
-    bufp = GetPacket();
+    bufp = smb_GetPacket();
     bufp->spacep = cm_GetSpace();
     bufs[idx] = bufp;
 }
@@ -8048,7 +8624,7 @@ void smb_Listener(void *parmp)
     long code = 0;
     long len;
     long i;
-    int  session, thread;
+    afs_uint32  session, thread;
     smb_vc_t *vcp = NULL;
     int flags = 0;
     char rname[NCBNAMSZ+1];
@@ -8057,12 +8633,12 @@ void smb_Listener(void *parmp)
     INT_PTR lana = (INT_PTR) parmp;
     char eventName[MAX_PATH];
 
-    sprintf(eventName,"smb_Listener_lana_%d", (char)lana);
+    sprintf(eventName,"smb_Listener_lana_%d", (unsigned char)lana);
     ListenerShutdown[lana] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
     if ( GetLastError() == ERROR_ALREADY_EXISTS )
         thrd_ResetEvent(ListenerShutdown[lana]);
 
-    ncbp = GetNCB();
+    ncbp = smb_GetNCB();
 
     /* retrieve computer name */
     GetComputerName(cname, &cnamelen);
@@ -8206,7 +8782,7 @@ void smb_Listener(void *parmp)
            }
            
            lock_ObtainMutex(&vcp->mx);
-           strcpy(vcp->rname, rname);
+            cm_Utf8ToUtf16(rname, -1, vcp->rname, lengthof(vcp->rname));
            vcp->flags |= flags;
            lock_ReleaseMutex(&vcp->mx);
 
@@ -8244,7 +8820,7 @@ void smb_Listener(void *parmp)
 
         if (session >= SESSION_MAX - 1  || numNCBs >= NCB_MAX - 1) {
             unsigned long code = CM_ERROR_ALLBUSY;
-            smb_packet_t * outp = GetPacket();
+            smb_packet_t * outp = smb_GetPacket();
             unsigned char *outWctp;
             smb_t *smbp;
             
@@ -8277,6 +8853,7 @@ void smb_Listener(void *parmp)
                 smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
                 smbp->rcls = errClass;
             }
+
             smb_SendPacket(vcp, outp);
             smb_FreePacket(outp);
 
@@ -8344,7 +8921,7 @@ void smb_Listener(void *parmp)
     }  /* dispatch while loop */
 
 exit_thread:
-    FreeNCB(ncbp);
+    smb_FreeNCB(ncbp);
     thrd_SetEvent(ListenerShutdown[lana]);
     return;
 }
@@ -8403,7 +8980,7 @@ void smb_LanAdapterChange(int locked) {
              strcmp(cm_NetbiosName, NetbiosName) ) {
             change = 1;
         } else {
-            NCB *ncbp = GetNCB();
+            NCB *ncbp = smb_GetNCB();
             ncbp->ncb_command = NCBENUM;
             ncbp->ncb_buffer = (PUCHAR)&temp_list;
             ncbp->ncb_length = sizeof(temp_list);
@@ -8420,7 +8997,7 @@ void smb_LanAdapterChange(int locked) {
                     }
                 }
             }
-           FreeNCB(ncbp);
+           smb_FreeNCB(ncbp);
         }
     } 
 
@@ -8455,7 +9032,7 @@ int smb_NetbiosInit(int locked)
         return 0;
     }
     /* setup the NCB system */
-    ncbp = GetNCB();
+    ncbp = smb_GetNCB();
 
     /* Call lanahelper to get Netbios name, lan adapter number and gateway flag */
     if (SUCCEEDED(code = lana_GetUncServerNameEx(cm_NetbiosName, &lanaNum, &isGateway, LANA_NETBIOS_NAME_FULL))) {
@@ -8485,6 +9062,8 @@ int smb_NetbiosInit(int locked)
     strcpy(smb_localNamep, cm_NetbiosName);
     afsi_log("smb_localNamep is >%s<", smb_localNamep);
 
+    /* Also copy the value to the client character encoded string */
+    cm_Utf8ToClientString(cm_NetbiosName, -1, cm_NetbiosNameC, MAX_NB_NAME_LENGTH);
 
     if (smb_LANadapter == LANA_INVALID) {
         ncbp->ncb_command = NCBENUM;
@@ -8605,7 +9184,7 @@ int smb_NetbiosInit(int locked)
     }
         
     /* we're done with the NCB now */
-    FreeNCB(ncbp);
+    smb_FreeNCB(ncbp);
 
     afsi_log("smb_NetbiosInit smb_LANadapter=%d",smb_LANadapter);
     if (lana_list.length > 0)
@@ -8725,7 +9304,7 @@ void smb_StopListeners(int locked)
 #endif
                                   );
 
-    ncbp = GetNCB();
+    ncbp = smb_GetNCB();
 
     /* Unregister the SMB name */
     for (l = 0; l < lana_list.length; l++) {
@@ -8742,7 +9321,7 @@ void smb_StopListeners(int locked)
     /* force a re-evaluation of the network adapters */
     lana_list.length = 0;
     smb_LANadapter = LANA_INVALID;
-    FreeNCB(ncbp);
+    smb_FreeNCB(ncbp);
     if (!locked)
         lock_ReleaseMutex(&smb_StartedLock);
 }
@@ -9073,10 +9652,10 @@ void smb_Init(osi_log_t *logp, int useV3,
          * It is actually the domain for local logins, and we are acting as
          * a local SMB server. 
          */
-        bufsize = sizeof(smb_ServerDomainName) - 1;
-        GetComputerName(smb_ServerDomainName, &bufsize);
+        bufsize = lengthof(smb_ServerDomainName) - 1;
+        GetComputerNameW(smb_ServerDomainName, &bufsize);
         smb_ServerDomainNameLength = bufsize + 1; /* bufsize doesn't include terminator */
-        afsi_log("Setting SMB server domain name to [%s]", smb_ServerDomainName);
+        afsi_log("Setting SMB server domain name to [%S]", smb_ServerDomainName);
     }
 
     /* Start listeners, waiters, servers, and daemons */
@@ -9118,13 +9697,13 @@ void smb_Shutdown(void)
 {
     NCB *ncbp;
     long code = 0;
-    int i;
+    afs_uint32 i;
     smb_vc_t *vcp;
 
     /*fprintf(stderr, "Entering smb_Shutdown\n");*/
         
     /* setup the NCB system */
-    ncbp = GetNCB();
+    ncbp = smb_GetNCB();
 
     /* Block new sessions by setting shutdown flag */
     smbShutdownFlag = 1;
@@ -9204,9 +9783,9 @@ void smb_Shutdown(void)
                 if (fidp->scp != NULL) {
                     scp = fidp->scp;
                     fidp->scp = NULL;
-                   lock_ObtainMutex(&scp->mx);
+                   lock_ObtainWrite(&scp->rw);
                    scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
-                   lock_ReleaseMutex(&scp->mx);
+                   lock_ReleaseWrite(&scp->rw);
                    osi_Log2(smb_logp,"smb_Shutdown fidp 0x%p scp 0x%p", fidp, scp);
                     cm_ReleaseSCache(scp);
                 }
@@ -9220,14 +9799,12 @@ void smb_Shutdown(void)
             if (tidp->userp) {
                 cm_user_t *userp = tidp->userp;
                 tidp->userp = NULL;
-                lock_ReleaseWrite(&smb_rctLock);
                 cm_ReleaseUser(userp);
-                lock_ObtainWrite(&smb_rctLock);
             }
         }
     }
     lock_ReleaseWrite(&smb_rctLock);
-    FreeNCB(ncbp);
+    smb_FreeNCB(ncbp);
     TlsFree(smb_TlsRequestSlot);
 }
 
@@ -9235,6 +9812,7 @@ void smb_Shutdown(void)
 char *smb_GetSharename()
 {
     char *name;
+    size_t len;
 
     /* Make sure we have been properly initialized. */
     if (smb_localNamep == NULL)
@@ -9243,16 +9821,18 @@ char *smb_GetSharename()
     /* Allocate space for \\<servername>\<sharename>, plus the
      * terminator.
      */
-    name = malloc(strlen(smb_localNamep) + strlen("ALL") + 4);
-    sprintf(name, "\\\\%s\\%s", smb_localNamep, "ALL");
+    len = (strlen(smb_localNamep) + strlen("ALL") + 4) * sizeof(char);
+    name = malloc(len);
+    snprintf(name, len, "\\\\%s\\%s", smb_localNamep, "ALL");
     return name;
-}   
+}
 
 
 #ifdef LOG_PACKET
 void smb_LogPacket(smb_packet_t *packet)
 {
     BYTE *vp, *cp;
+    smb_t * smbp;
     unsigned length, paramlen, datalen, i, j;
     char buf[81];
     char hex[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
@@ -9261,11 +9841,12 @@ void smb_LogPacket(smb_packet_t *packet)
 
     osi_Log0(smb_logp, "*** SMB packet dump ***");
 
+    smbp = (smb_t *) packet->data;
     vp = (BYTE *) packet->data;
 
-    datalen = *((WORD*)(vp + (paramlen = ((unsigned)*(vp+20)) << 1)));
-    length = paramlen + 2 + datalen;
-
+    paramlen = smbp->wct * 2;
+    datalen = *((WORD *) (smbp->vdata + paramlen));
+    length = sizeof(*smbp) + paramlen + 1 + datalen;
 
     for (i=0;i < length; i+=16)
     {
@@ -9329,7 +9910,7 @@ int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
     {
         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",
+        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);
       
@@ -9338,10 +9919,10 @@ int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
 
         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", 
+            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, 
-                     fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL", 
-                     fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+                    fidp->NTopen_pathp ? fidp->NTopen_pathp : _C("NULL"), 
+                    fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : _C("NULL"));
             WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
         }
       
@@ -9359,7 +9940,7 @@ int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
     {
         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",
+        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);
       
@@ -9368,10 +9949,10 @@ int smb_DumpVCP(FILE *outputFile, char *cookie, int lock)
 
         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", 
+            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, 
-                     fidp->NTopen_pathp ? fidp->NTopen_pathp : "NULL", 
-                     fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : "NULL");
+                    fidp->NTopen_pathp ? fidp->NTopen_pathp : _C("NULL"), 
+                    fidp->NTopen_wholepathp ? fidp->NTopen_wholepathp : _C("NULL"));
             WriteFile(outputFile, output, (DWORD)strlen(output), &zilch, NULL);
         }