Windows: Fix test for setting FILE_ATTR_READONLY
[openafs.git] / src / WINNT / afsd / smb3.c
index ba54a81..3440e94 100644 (file)
@@ -29,6 +29,7 @@
 #include <WINNT\afsreg.h>
 
 #include "smb.h"
+#include "msrpc.h"
 #include <strsafe.h>
 
 extern osi_hyper_t hzero;
@@ -114,10 +115,10 @@ unsigned long smb_ExtAttributes(cm_scache_t *scp)
      * turns out to be impolitic in NT.  See defect 10007.
      */
 #ifdef notdef
-    if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
+    if ((scp->unixModeBits & 0200) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
         attrs |= SMB_ATTR_READONLY;            /* Read-only */
 #else
-    if ((scp->unixModeBits & 0222) == 0)
+    if ((scp->unixModeBits & 0200) == 0)
         attrs |= SMB_ATTR_READONLY;            /* Read-only */
 #endif
 
@@ -144,8 +145,6 @@ void OutputDebugF(clientchar_t * format, ...) {
     va_start( args, format );
     cm_ClientStrPrintfV(vbuffer, lengthof(vbuffer), format, args);
     osi_Log1(smb_logp, "%S", osi_LogSaveClientString(smb_logp, vbuffer));
-    cm_ClientStrCat(vbuffer, lengthof(vbuffer), _C("\n"));
-    OutputDebugStringW(vbuffer);
 }
 
 void OutputDebugHexDump(unsigned char * buffer, int len) {
@@ -159,8 +158,6 @@ void OutputDebugHexDump(unsigned char * buffer, int len) {
         if(!(i%16)) {
             if(i) {
                 osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
-                StringCchCatA(buf, lengthof(buf), "\r\n");
-                OutputDebugString(buf);
             }
             StringCchPrintfA(buf, lengthof(buf), "%5x", i);
             memset(buf+5,' ',80);
@@ -180,8 +177,6 @@ void OutputDebugHexDump(unsigned char * buffer, int len) {
     }    
     if(i) {
         osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, buf));
-        StringCchCatA(buf, lengthof(buf), "\r\n");
-        OutputDebugString(buf);
     }   
 }
 
@@ -686,11 +681,39 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     clientchar_t usern[SMB_MAX_USERNAME_LENGTH];
     char *secBlobOut = NULL;
     int  secBlobOutLength = 0;
+    int  maxBufferSize = 0;
+    int  maxMpxCount = 0;
+    int  vcNumber = 0;
 
     /* Check for bad conns */
     if (vcp->flags & SMB_VCFLAG_REMOTECONN)
         return CM_ERROR_REMOTECONN;
 
+    /* maxBufferSize */
+    maxBufferSize = smb_GetSMBParm(inp, 2);
+    maxMpxCount = smb_GetSMBParm(inp, 3);
+    vcNumber = smb_GetSMBParm(inp, 4);
+
+    osi_Log3(smb_logp, "SESSION_SETUP_ANDX with MaxBufferSize=%d, MaxMpxCount=%d, VCNumber=%d",
+             maxBufferSize, maxMpxCount, vcNumber);
+
+    if (maxMpxCount > smb_maxMpxRequests) {
+        LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_MAX_MPX_COUNT, maxMpxCount, smb_maxMpxRequests);
+        osi_Log2(smb_logp, "MaxMpxCount for client is too large (Client=%d, Server=%d)",
+                 maxMpxCount, smb_maxMpxRequests);
+    }
+
+    if (maxBufferSize < SMB_PACKETSIZE) {
+        LogEvent(EVENTLOG_INFORMATION_TYPE, MSG_SMB_MAX_BUFFER_SIZE, maxBufferSize, SMB_PACKETSIZE);
+        osi_Log2(smb_logp, "MaxBufferSize for client is too small (Client=%d, Server=%d)",
+                 maxBufferSize, SMB_PACKETSIZE);
+    }
+
+    if (vcNumber == 0) {
+        osi_Log0(smb_logp, "Resetting all VCs");
+        smb_MarkAllVCsDead(vcp);
+    }
+
     if (vcp->flags & SMB_VCFLAG_USENT) {
         if (smb_authType == SMB_AUTH_EXTENDED) {
             /* extended authentication */
@@ -1243,7 +1266,11 @@ void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
             free(t2p->parmsp);
         if (t2p->datap)
             free(t2p->datap);
-    }       
+    }
+    if (t2p->name) {
+       free(t2p->name);
+       t2p->name = NULL;
+    }
     while (t2p->stringsp) {
         cm_space_t * ns;
 
@@ -1348,6 +1375,30 @@ void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp
     smbp->uid = t2p->uid;
     smbp->res[0] = t2p->res[0];
 
+    if (t2p->error_code) {
+       if (vcp->flags & SMB_VCFLAG_STATUS32) {
+           unsigned long NTStatus;
+
+           smb_MapNTError(t2p->error_code, &NTStatus);
+
+           smbp->rcls = (unsigned char) (NTStatus & 0xff);
+           smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff);
+           smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff);
+           smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff);
+           smbp->flg2 |= SMB_FLAGS2_32BIT_STATUS;
+       }
+       else {
+           unsigned short errCode;
+           unsigned char errClass;
+
+           smb_MapCoreError(t2p->error_code, vcp, &errCode, &errClass);
+
+           smbp->rcls = errClass;
+           smbp->errLow = (unsigned char) (errCode & 0xff);
+           smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff);
+       }
+    }
+
     totalLength = 1 + t2p->totalData + t2p->totalParms;
 
     /* now add the core parameters (tran2 info) to the packet */
@@ -1377,7 +1428,81 @@ void smb_SendTran2Packet(smb_vc_t *vcp, smb_tran2Packet_t *t2p, smb_packet_t *tp
         
     /* next, send the datagram */
     smb_SendPacket(vcp, tp);
-}   
+}
+
+/* TRANS_SET_NMPIPE_STATE */
+long smb_nmpipeSetState(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+    smb_fid_t *fidp;
+    int fd;
+    int pipeState = 0x0100;    /* default */
+    smb_tran2Packet_t *outp = NULL;
+
+    fd = p->pipeParam;
+    if (p->totalParms > 0)
+       pipeState = p->parmsp[0];
+
+    osi_Log2(smb_logp, "smb_nmpipeSetState for fd[%d] with state[0x%x]", fd, pipeState);
+
+    fidp = smb_FindFID(vcp, fd, 0);
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_nmpipeSetState Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
+       return CM_ERROR_BADFD;
+    }
+    lock_ObtainMutex(&fidp->mx);
+    if (pipeState & 0x8000)
+       fidp->flags |= SMB_FID_BLOCKINGPIPE;
+    if (pipeState & 0x0100)
+       fidp->flags |= SMB_FID_MESSAGEMODEPIPE;
+    lock_ReleaseMutex(&fidp->mx);
+
+    outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, 0);
+    smb_SendTran2Packet(vcp, outp, op);
+    smb_FreeTran2Packet(outp);
+
+    smb_ReleaseFID(fidp);
+
+    return 0;
+}
+
+long smb_nmpipeTransact(smb_vc_t * vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+    smb_fid_t *fidp;
+    int fd;
+    int is_rpc = 0;
+
+    long code = 0;
+
+    fd = p->pipeParam;
+
+    osi_Log3(smb_logp, "smb_nmpipeTransact for fd[%d] %d bytes in, %d max bytes out",
+            fd, p->totalData, p->maxReturnData);
+
+    fidp = smb_FindFID(vcp, fd, 0);
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_nmpipeTransact Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
+       return CM_ERROR_BADFD;
+    }
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_RPC) {
+       is_rpc = 1;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+
+    if (is_rpc) {
+       code = smb_RPCNmpipeTransact(fidp, vcp, p, op);
+       smb_ReleaseFID(fidp);
+    } else {
+       /* We only deal with RPC pipes */
+        osi_Log2(smb_logp, "smb_nmpipeTransact Not a RPC vcp 0x%p fid %d",
+                 vcp, fd);
+       code = CM_ERROR_BADFD;
+    }
+
+    return code;
+}
 
 
 /* SMB_COM_TRANSACTION and SMB_COM_TRANSACTION_SECONDARY */
@@ -1426,11 +1551,26 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         dataOffset = smb_GetSMBParm(inp, 12);
         parmCount = smb_GetSMBParm(inp, 9);
         dataCount = smb_GetSMBParm(inp, 11);
+       asp->setupCount = smb_GetSMBParmByte(inp, 13);
         asp->maxReturnParms = smb_GetSMBParm(inp, 2);
         asp->maxReturnData = smb_GetSMBParm(inp, 3);
 
         osi_Log3(smb_logp, "SMB3 received Trans init packet total data %d, cur data %d, max return data %d",
                   totalData, dataCount, asp->maxReturnData);
+
+       if (asp->setupCount == 2) {
+           clientchar_t * pname;
+
+           asp->pipeCommand = smb_GetSMBParm(inp, 14);
+           asp->pipeParam = smb_GetSMBParm(inp, 15);
+           pname = smb_ParseString(inp, inp->wctp + 35, NULL, 0);
+           if (pname) {
+               asp->name = cm_ClientStrDup(pname);
+           }
+
+           osi_Log2(smb_logp, "  Named Pipe command id [%d] with name [%S]",
+                    asp->pipeCommand, osi_LogSaveClientString(smb_logp, asp->name));
+       }
     }
     else {
         parmDisp = smb_GetSMBParm(inp, 4);
@@ -1442,7 +1582,7 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         osi_Log2(smb_logp, "SMB3 received Trans aux packet parms %d, data %d",
                  parmCount, dataCount);
-    }   
+    }
 
     /* now copy the parms and data */
     if ( asp->totalParms > 0 && parmCount != 0 )
@@ -1458,27 +1598,91 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     asp->curParms += parmCount;
 
     /* finally, if we're done, remove the packet from the queue and dispatch it */
-    if (asp->totalParms > 0 &&
-        asp->curParms > 0 &&
+    if (((asp->totalParms > 0 && asp->curParms > 0)
+        || asp->setupCount == 2) &&
         asp->totalData <= asp->curData &&
         asp->totalParms <= asp->curParms) {
+
         /* we've received it all */
         lock_ObtainWrite(&smb_globalLock);
         osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
         lock_ReleaseWrite(&smb_globalLock);
 
-        /* now dispatch it */
-        rapOp = asp->parmsp[0];
+       switch(asp->setupCount) {
+       case 0:
+           {                   /* RAP */
+               rapOp = asp->parmsp[0];
 
-        if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES && smb_rapDispatchTable[rapOp].procp) {
-            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
-            code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
-            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return  code 0x%x vcp[%x] lana[%d] lsn[%d]",code,vcp,vcp->lana,vcp->lsn);
-        }
-        else {
-            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
-            code = CM_ERROR_BADOP;
-        }
+               if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES &&
+                    smb_rapDispatchTable[rapOp].procp) {
+
+                   osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",
+                            myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
+
+                   code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
+
+                   osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return  code 0x%x vcp[%x] lana[%d] lsn[%d]",
+                            code,vcp,vcp->lana,vcp->lsn);
+               }
+               else {
+                   osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]",
+                            rapOp, vcp, vcp->lana, vcp->lsn);
+
+                   code = CM_ERROR_BADOP;
+               }
+           }
+           break;
+
+       case 2:
+           {                   /* Named pipe operation */
+               osi_Log2(smb_logp, "Named Pipe: %s with name [%S]",
+                        myCrt_NmpipeDispatch(asp->pipeCommand),
+                        osi_LogSaveClientString(smb_logp, asp->name));
+
+               code = CM_ERROR_BADOP;
+
+               switch (asp->pipeCommand) {
+               case SMB_TRANS_SET_NMPIPE_STATE:
+                   code = smb_nmpipeSetState(vcp, asp, outp);
+                   break;
+
+               case SMB_TRANS_RAW_READ_NMPIPE:
+                   break;
+
+               case SMB_TRANS_QUERY_NMPIPE_STATE:
+                   break;
+
+               case SMB_TRANS_QUERY_NMPIPE_INFO:
+                   break;
+
+               case SMB_TRANS_PEEK_NMPIPE:
+                   break;
+
+               case SMB_TRANS_TRANSACT_NMPIPE:
+                   code = smb_nmpipeTransact(vcp, asp, outp);
+                   break;
+
+               case SMB_TRANS_RAW_WRITE_NMPIPE:
+                   break;
+
+               case SMB_TRANS_READ_NMPIPE:
+                   break;
+
+               case SMB_TRANS_WRITE_NMPIPE:
+                   break;
+
+               case SMB_TRANS_WAIT_NMPIPE:
+                   break;
+
+               case SMB_TRANS_CALL_NMPIPE:
+                   break;
+               }
+           }
+           break;
+
+       default:
+           code = CM_ERROR_BADOP;
+       }
 
         /* if an error is returned, we're supposed to send an error packet,
          * otherwise the dispatched function already did the data sending.
@@ -1827,7 +2031,7 @@ long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack
     } else {
         userp = smb_GetTran2User(vcp, p);
         if (!userp) {
-            osi_Log1(smb_logp,"ReceiveTran2GetDfsReferral unable to resolve user [%d]", p->uid);
+            osi_Log1(smb_logp,"ReceiveRAPNetShareGetInfo unable to resolve user [%d]", p->uid);
             return CM_ERROR_BADSMB;
         }   
         code = cm_NameI(cm_data.rootSCachep, shareName,
@@ -2116,6 +2320,7 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     int dataCount;
     int firstPacket;
     long code = 0;
+    DWORD oldTime, newTime;
 
     /* We sometimes see 0 word count.  What to do? */
     if (*inp->wctp == 0) {
@@ -2188,6 +2393,8 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
         lock_ReleaseWrite(&smb_globalLock);
 
+        oldTime = GetTickCount();
+
         /* now dispatch it */
         if ( asp->opcode >= 0 && asp->opcode < 20 && smb_tran2DispatchTable[asp->opcode].procp) {
             osi_Log4(smb_logp,"AFS Server - Dispatch-2 %s vcp[%p] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
@@ -2207,6 +2414,46 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             smb_SendTran2Error(vcp, asp, outp, code);
         }
 
+        newTime = GetTickCount();
+        if (newTime - oldTime > 45000) {
+            smb_user_t *uidp;
+            smb_fid_t *fidp;
+            clientchar_t *treepath = NULL;  /* do not free */
+            clientchar_t *pathname = NULL;
+            cm_fid_t afid = {0,0,0,0,0};
+
+            uidp = smb_FindUID(vcp, asp->uid, 0);
+            smb_LookupTIDPath(vcp, asp->tid, &treepath);
+            fidp = smb_FindFID(vcp, inp->fid, 0);
+
+            if (fidp) {
+                lock_ObtainMutex(&fidp->mx);
+                if (fidp->NTopen_pathp)
+                    pathname = fidp->NTopen_pathp;
+                if (fidp->scp)
+                    afid = fidp->scp->fid;
+            } else {
+                if (inp->stringsp->wdata)
+                    pathname = inp->stringsp->wdata;
+            }
+
+            afsi_log("Request %s duration %d ms user 0x%x \"%S\" pid 0x%x mid 0x%x tid 0x%x \"%S\" path? \"%S\" afid (%d.%d.%d.%d)", 
+                      myCrt_2Dispatch(asp->opcode), newTime - oldTime,
+                      asp->uid, uidp ? uidp->unp->name : NULL,
+                      asp->pid, asp->mid, asp->tid,
+                      treepath,
+                      pathname, 
+                      afid.cell, afid.volume, afid.vnode, afid.unique);
+
+            if (fidp)
+                lock_ReleaseMutex(&fidp->mx);
+
+            if (uidp)
+                smb_ReleaseUID(uidp);
+            if (fidp)
+                smb_ReleaseFID(fidp);
+        }
+
         /* free the input tran 2 packet */
         smb_FreeTran2Packet(asp);
     }
@@ -2248,6 +2495,8 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     clientchar_t *tidPathp;
     cm_req_t req;
     int created = 0;
+    BOOL is_rpc = FALSE;
+    BOOL is_ipc = FALSE;
 
     smb_InitReq(&req);
 
@@ -2275,19 +2524,45 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     
     outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
 
+    code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
+    if (code == CM_ERROR_TIDIPC) {
+       is_ipc = TRUE;
+        osi_Log0(smb_logp, "Tran2Open received IPC TID");
+    }
+
     spacep = cm_GetSpace();
+    /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
-    if (lastNamep && 
-        (cm_ClientStrCmpI(lastNamep,  _C(SMB_IOCTL_FILENAME)) == 0 ||
-         cm_ClientStrCmpI(lastNamep,  _C("\\srvsvc")) == 0 ||
-         cm_ClientStrCmpI(lastNamep,  _C("\\wkssvc")) == 0 ||
-         cm_ClientStrCmpI(lastNamep,  _C("\\ipc$")) == 0)) {
+    if (lastNamep &&
+
         /* special case magic file name for receiving IOCTL requests
          * (since IOCTL calls themselves aren't getting through).
          */
+        (cm_ClientStrCmpI(lastNamep,  _C(SMB_IOCTL_FILENAME)) == 0 ||
+
+        /* Or an RPC endpoint (is_rpc = TRUE assignment is intentional)*/
+        (is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)))) {
+
+       unsigned short file_type = 0;
+       unsigned short device_state = 0;
+
         fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-        smb_SetupIoctlFid(fidp, spacep);
+
+       if (is_rpc) {
+           code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+           osi_Log2(smb_logp, "smb_ReceiveTran2Open Creating RPC Fid [%d] code [%d]",
+                     fidp->fid, code);
+           if (code) {
+               smb_ReleaseFID(fidp);
+               smb_FreeTran2Packet(outp);
+               osi_Log1(smb_logp, "smb_SetupRPCFid() failure code [%d]", code);
+               return code;
+           }
+       } else {
+           smb_SetupIoctlFid(fidp, spacep);
+           osi_Log1(smb_logp, "smb_ReceiveTran2Open Creating IOCTL Fid [%d]", fidp->fid);
+       }
 
         /* copy out remainder of the parms */
         parmSlot = 0;
@@ -2299,8 +2574,8 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
             outp->parmsp[parmSlot++] = 0;       /* len */
             outp->parmsp[parmSlot++] = 0x7fff;
             outp->parmsp[parmSlot++] = openMode;
-            outp->parmsp[parmSlot++] = 0;       /* file type 0 ==> normal file or dir */
-            outp->parmsp[parmSlot++] = 0;       /* IPC junk */
+            outp->parmsp[parmSlot++] = file_type;
+            outp->parmsp[parmSlot++] = device_state;
         }   
         /* and the final "always present" stuff */
         outp->parmsp[parmSlot++] = 1;           /* openAction found existing file */
@@ -2325,6 +2600,30 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         return 0;
     }
 
+#ifndef DFS_SUPPORT
+    if (is_ipc) {
+        osi_Log1(smb_logp, "Tran2Open rejecting IPC TID vcp %p", vcp);
+       smb_FreeTran2Packet(outp);
+       return CM_ERROR_BADFD;
+    }
+#endif
+
+    if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+        clientchar_t * hexp;
+
+        hexp = cm_GetRawCharsAlloc(pathp, -1);
+        osi_Log1(smb_logp, "Tran2Open rejecting invalid name. [%S]",
+                 osi_LogSaveClientString(smb_logp, hexp));
+        if (hexp)
+            free(hexp);
+#else
+        osi_Log0(smb_logp, "Tran2Open rejecting invalid name");
+#endif
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADNTFILENAME;
+    }
+
 #ifdef DEBUG_VERBOSE
     {
         char *hexp, *asciip;
@@ -2343,21 +2642,6 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         return CM_ERROR_BADSMB;
     }
 
-    code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
-    if (code == CM_ERROR_TIDIPC) {
-        /* Attempt to use a TID allocated for IPC.  The client
-         * is probably looking for DCE RPC end points which we
-         * don't support OR it could be looking to make a DFS
-         * referral request. 
-         */
-        osi_Log0(smb_logp, "Tran2Open received IPC TID");
-#ifndef DFS_SUPPORT
-        cm_ReleaseUser(userp);
-        smb_FreeTran2Packet(outp);
-        return CM_ERROR_NOSUCHPATH;
-#endif
-    }
-
     dscp = NULL;
     code = cm_NameI(cm_data.rootSCachep, pathp,
                      CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
@@ -2384,7 +2668,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
             if ( WANTS_DFS_PATHNAMES(p) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
-                return CM_ERROR_BADSHARENAME;
+                return CM_ERROR_NOSUCHPATH;
         }
 #endif /* DFS_SUPPORT */
 
@@ -2405,6 +2689,9 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
             return code;
         }
     } else {
+        /* macintosh is expensive to program for it */
+        cm_FreeSpace(spacep);
+
 #ifdef DFS_SUPPORT
         if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
             int pnc = cm_VolStatus_Notify_DFS_Mapping(scp, tidPathp, lastNamep);
@@ -2414,12 +2701,9 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
             if ( WANTS_DFS_PATHNAMES(p) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
-                return CM_ERROR_BADSHARENAME;
+                return CM_ERROR_NOSUCHPATH;
         }
 #endif /* DFS_SUPPORT */
-
-        /* macintosh is expensive to program for it */
-        cm_FreeSpace(spacep);
     }
         
     /* if we get here, if code is 0, the file exists and is represented by
@@ -2469,7 +2753,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         osi_assertx(dscp != NULL && scp == NULL, "null dsc || non-null sc");
         openAction = 2;        /* created file */
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
-        smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
+        cm_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
         code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
                           &req);
         if (code == 0) {
@@ -2575,7 +2859,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     lock_ObtainRead(&scp->rw);
     if (extraInfo) {
         outp->parmsp[parmSlot++] = smb_Attributes(scp);
-        smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+        cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
         outp->parmsp[parmSlot++] = (unsigned short)(dosTime & 0xffff);
         outp->parmsp[parmSlot++] = (unsigned short)((dosTime>>16) & 0xffff);
         outp->parmsp[parmSlot++] = (unsigned short) (scp->length.LowPart & 0xffff);
@@ -2644,7 +2928,7 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
     case SMB_INFO_VOLUME: 
         /* volume info */
         qi.u.volumeInfo.vsn = 1234;  /* Volume serial number */
-        qi.u.volumeInfo.vnCount = 4; /* Number of characters in label (AFS\0)*/
+        qi.u.volumeInfo.vnCount = 3; /* Number of characters in label (AFS\0)*/
 
         /* we're supposed to pad it out with zeroes to the end */
         memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
@@ -2663,7 +2947,8 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
         }
 
         qi.u.FSvolumeInfo.vsn = 1234;
-        qi.u.FSvolumeInfo.vnCount = 8; /* This is always in Unicode */
+        qi.u.FSvolumeInfo.vnCount = 6; /* This is always in Unicode */
+        memset(&qi.u.FSvolumeInfo.label, 0, sizeof(qi.u.FSvolumeInfo.label));
         memcpy(qi.u.FSvolumeInfo.label, L"AFS", sizeof(L"AFS"));
         break;
 
@@ -2693,6 +2978,7 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
         /* attributes, defined in WINNT.H:
          *     FILE_CASE_SENSITIVE_SEARCH      0x1
          *     FILE_CASE_PRESERVED_NAMES       0x2
+         *      FILE_UNICODE_ON_DISK            0x4
         *      FILE_VOLUME_QUOTAS              0x10
          *     <no name defined>               0x4000
          *        If bit 0x4000 is not set, Windows 95 thinks
@@ -2702,14 +2988,9 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
         qi.u.FSattributeInfo.attributes = 0x4003;
         /* The maxCompLength is supposed to be in bytes */
 #ifdef SMB_UNICODE
-        if ((vcp->flags & SMB_VCFLAG_USEUNICODE) == SMB_VCFLAG_USEUNICODE)
-            qi.u.FSattributeInfo.maxCompLength = MAX_PATH * sizeof(wchar_t);
-        else {
-#endif
-        qi.u.FSattributeInfo.maxCompLength = MAX_PATH;
-#ifdef SMB_UNICODE
-        }
+        qi.u.FSattributeInfo.attributes |= 0x04;
 #endif
+        qi.u.FSattributeInfo.maxCompLength = 255;
         smb_UnparseString(op, qi.u.FSattributeInfo.FSname, _C("AFS"), &sz, SMB_STRF_IGNORENUL);
         qi.u.FSattributeInfo.FSnameLength = sz;
 
@@ -2763,7 +3044,11 @@ int cm_GetShortNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *vrockp,
 
     rockp = vrockp;
 
-    cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(clientchar_t));
+    if (cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(clientchar_t)) == 0) {
+        osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+                 osi_LogSaveString(smb_logp, dep->name));
+        return 0;
+    }
 
     /* compare both names and vnodes, though probably just comparing vnodes
      * would be safe enough.
@@ -2792,6 +3077,7 @@ long cm_GetShortName(clientchar_t *pathp, cm_user_t *userp, cm_req_t *reqp,
     osi_hyper_t thyper;
 
     spacep = cm_GetSpace();
+    /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
     code = cm_NameI(cm_data.rootSCachep, spacep->wdata,
@@ -2877,15 +3163,18 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         responseSize = sizeof(qpi.u.QPfileAllInfo);
     else if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO) 
         responseSize = sizeof(qpi.u.QPfileAltNameInfo);
+    else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO)
+        responseSize = sizeof(qpi.u.QPfileStreamInfo);
     else {
-        osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+        osi_Log2(smb_logp, "Bad Tran2QPathInfo op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
         return 0;
     }
+    memset(&qpi, 0, sizeof(qpi));
 
     pathp = smb_ParseStringT2Parm(p, (char *) (&p->parmsp[3]), NULL, SMB_STRF_ANSIPATH);
-    osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path %S", infoLevel,
+    osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path \"%S\"", infoLevel,
               osi_LogSaveClientString(smb_logp, pathp));
 
     outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
@@ -2894,7 +3183,6 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         outp->totalParms = 2;
     else
         outp->totalParms = 0;
-    outp->totalData = responseSize;
         
     /* now, if we're at infoLevel 6, we're only being asked to check
      * the syntax, so we just OK things now.  In particular, we're *not*
@@ -2915,12 +3203,16 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
     if(code) {
+        osi_Log1(smb_logp, "ReceiveTran2QPathInfo tid path lookup failure 0x%x", code);
         cm_ReleaseUser(userp);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHPATH);
         smb_FreeTran2Packet(outp);
         return 0;
     }
 
+    osi_Log1(smb_logp, "T2 QPathInfo tidPathp \"%S\"",
+              osi_LogSaveClientString(smb_logp, tidPathp));
+
     /*
      * XXX Strange hack XXX
      *
@@ -2937,6 +3229,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
      */
     if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         spacep = cm_GetSpace();
+        /* smb_StripLastComponent will strip "::$DATA" if present */
         smb_StripLastComponent(spacep->wdata, &lastComp, pathp);
 #ifndef SPECIAL_FOLDERS
         /* Make sure that lastComp is not NULL */
@@ -2955,7 +3248,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                         if ( WANTS_DFS_PATHNAMES(p) || pnc )
                             code = CM_ERROR_PATH_NOT_COVERED;
                         else
-                            code = CM_ERROR_BADSHARENAME;
+                            code = CM_ERROR_NOSUCHPATH;
                     } else
 #endif /* DFS_SUPPORT */
                     if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
@@ -3004,7 +3297,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         if ( WANTS_DFS_PATHNAMES(p) || pnc )
             code = CM_ERROR_PATH_NOT_COVERED;
         else
-            code = CM_ERROR_BADSHARENAME;
+            code = CM_ERROR_NOSUCHPATH;
         smb_SendTran2Error(vcp, p, opx, code);
         smb_FreeTran2Packet(outp);
         return 0;
@@ -3039,17 +3332,15 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
         smb_UnparseString(opx, qpi.u.QPfileAltNameInfo.fileName, shortName, &len, SMB_STRF_IGNORENUL);
        qpi.u.QPfileAltNameInfo.fileNameLength = len;
-
-        goto done;
+        responseSize = sizeof(unsigned long) + len;
     }
     else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
         smb_UnparseString(opx, qpi.u.QPfileNameInfo.fileName, lastComp, &len, SMB_STRF_IGNORENUL);
        qpi.u.QPfileNameInfo.fileNameLength = len;
-
-        goto done;
+        responseSize = sizeof(unsigned long) + len;
     }
     else if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
-        smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+        cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
        qpi.u.QPstandardInfo.creationDateTime = dosTime;
        qpi.u.QPstandardInfo.lastAccessDateTime = dosTime;
        qpi.u.QPstandardInfo.lastWriteDateTime = dosTime;
@@ -3060,7 +3351,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        qpi.u.QPstandardInfo.eaSize = 0;
     }
     else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
-        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
         qpi.u.QPfileBasicInfo.creationTime = ft;
         qpi.u.QPfileBasicInfo.lastAccessTime = ft;
         qpi.u.QPfileBasicInfo.lastWriteTime = ft;
@@ -3097,7 +3388,13 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         qpi.u.QPfileEaInfo.eaSize = 0;
     }
     else if (infoLevel == SMB_QUERY_FILE_ALL_INFO) {
-        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+       smb_fid_t * fidp;
+
+        lock_ReleaseRead(&scp->rw);
+        scp_rw_held = 0;
+        fidp = smb_FindFIDByScache(vcp, scp);
+
+        cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
         qpi.u.QPfileAllInfo.creationTime = ft;
         qpi.u.QPfileAllInfo.lastAccessTime = ft;
         qpi.u.QPfileAllInfo.lastWriteTime = ft;
@@ -3112,12 +3409,25 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
            ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
              scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
              scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
-       qpi.u.QPfileAllInfo.indexNumber.HighPart = scp->fid.cell;
-       qpi.u.QPfileAllInfo.indexNumber.LowPart  = scp->fid.volume;
+       qpi.u.QPfileAllInfo.indexNumber.HighPart = scp->fid.vnode;
+       qpi.u.QPfileAllInfo.indexNumber.LowPart  = scp->fid.unique;
        qpi.u.QPfileAllInfo.eaSize = 0;
-       qpi.u.QPfileAllInfo.accessFlags = 0;
-       qpi.u.QPfileAllInfo.indexNumber2.HighPart = scp->fid.vnode;
-       qpi.u.QPfileAllInfo.indexNumber2.LowPart  = scp->fid.unique;
+        qpi.u.QPfileAllInfo.accessFlags = 0;
+        if (fidp) {
+           lock_ObtainMutex(&fidp->mx);
+            if (fidp->flags & SMB_FID_OPENDELETE)
+                qpi.u.QPfileAllInfo.accessFlags |= DELETE;
+            if (fidp->flags & SMB_FID_OPENREAD_LISTDIR)
+                qpi.u.QPfileAllInfo.accessFlags |= AFS_ACCESS_READ|AFS_ACCESS_EXECUTE;
+            if (fidp->flags & SMB_FID_OPENWRITE)
+                qpi.u.QPfileAllInfo.accessFlags |= AFS_ACCESS_WRITE;
+            if (fidp->flags & SMB_FID_DELONCLOSE)
+                qpi.u.QPfileAllInfo.deletePending = 1;
+           lock_ReleaseMutex(&fidp->mx);
+           smb_ReleaseFID(fidp);
+        }
+       qpi.u.QPfileAllInfo.indexNumber2.HighPart = scp->fid.cell;
+       qpi.u.QPfileAllInfo.indexNumber2.LowPart  = scp->fid.volume;
        qpi.u.QPfileAllInfo.currentByteOffset.HighPart = 0;
        qpi.u.QPfileAllInfo.currentByteOffset.LowPart = 0;
        qpi.u.QPfileAllInfo.mode = 0;
@@ -3125,7 +3435,27 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
         smb_UnparseString(opx, qpi.u.QPfileAllInfo.fileName, lastComp, &len, SMB_STRF_IGNORENUL);
        qpi.u.QPfileAllInfo.fileNameLength = len;
+        responseSize -= (sizeof(qpi.u.QPfileAllInfo.fileName) - len);
+    }
+    else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO) {
+        size_t len = 0;
+        /* For now we have no streams */
+        qpi.u.QPfileStreamInfo.nextEntryOffset = 0;
+        if (scp->fileType == CM_SCACHETYPE_FILE) {
+            qpi.u.QPfileStreamInfo.streamSize = scp->length;
+            qpi.u.QPfileStreamInfo.streamAllocationSize = scp->length;
+            smb_UnparseString(opx, qpi.u.QPfileStreamInfo.fileName, L"::$DATA", &len, SMB_STRF_IGNORENUL);
+            qpi.u.QPfileStreamInfo.streamNameLength = len;
+            responseSize -= (sizeof(qpi.u.QPfileStreamInfo.fileName) - len);
+        } else {
+            qpi.u.QPfileStreamInfo.streamSize.QuadPart = 0;
+            qpi.u.QPfileStreamInfo.streamAllocationSize.QuadPart = 0;
+            smb_UnparseString(opx, qpi.u.QPfileStreamInfo.fileName, L"", &len, SMB_STRF_IGNORENUL);
+            qpi.u.QPfileStreamInfo.streamNameLength = 0;
+            responseSize = 0;
+        }
     }
+    outp->totalData = responseSize;
 
     /* send and free the packets */
   done:
@@ -3159,7 +3489,6 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     return CM_ERROR_BADOP;
 #else
     long code = 0;
-    smb_fid_t *fidp;
     unsigned short infoLevel;
     clientchar_t * pathp;
     smb_tran2Packet_t *outp;
@@ -3178,7 +3507,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     if (infoLevel != SMB_INFO_STANDARD && 
        infoLevel != SMB_INFO_QUERY_EA_SIZE &&
        infoLevel != SMB_INFO_QUERY_ALL_EAS) {
-        osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+        osi_Log2(smb_logp, "Bad Tran2SetPathInfo op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
         smb_SendTran2Error(vcp, p, opx, 
                            infoLevel == SMB_INFO_QUERY_ALL_EAS ? CM_ERROR_EAS_NOT_SUPPORTED : CM_ERROR_BAD_LEVEL);
@@ -3225,6 +3554,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     */
     if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         spacep = cm_GetSpace();
+        /* smb_StripLastComponent will strip "::$DATA" if present */
         smb_StripLastComponent(spacep->wdata, &lastComp, pathp);
 #ifndef SPECIAL_FOLDERS
         /* Make sure that lastComp is not NULL */
@@ -3243,7 +3573,7 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                         if ( WANTS_DFS_PATHNAMES(p) || pnc )
                             code = CM_ERROR_PATH_NOT_COVERED;
                         else
-                            code = CM_ERROR_BADSHARENAME;
+                            code = CM_ERROR_NOSUCHPATH;
                     } else
 #endif /* DFS_SUPPORT */
                     if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
@@ -3281,25 +3611,6 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         return 0;
     }
 
-    fidp = smb_FindFIDByScache(vcp, scp);
-    if (!fidp) {
-        cm_ReleaseSCache(scp);
-        cm_ReleaseUser(userp);
-       smb_SendTran2Error(vcp, p, opx, code);
-        return 0;
-    }
-
-    lock_ObtainMutex(&fidp->mx);
-    if (!(fidp->flags & SMB_FID_OPENWRITE)) {
-       lock_ReleaseMutex(&fidp->mx);
-        cm_ReleaseSCache(scp);
-        smb_ReleaseFID(fidp);
-        cm_ReleaseUser(userp);
-        smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS);
-        return 0;
-    }
-    lock_ReleaseMutex(&fidp->mx);
-
     outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, 0);
 
     outp->totalParms = 2;
@@ -3322,29 +3633,24 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         }
        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
-       lock_ReleaseWrite(&scp->rw);
-       lock_ObtainMutex(&fidp->mx);
-       lock_ObtainRead(&scp->rw);
-
         /* prepare for setattr call */
         attr.mask = CM_ATTRMASK_LENGTH;
         attr.length.LowPart = spi->u.QPstandardInfo.dataSize;
         attr.length.HighPart = 0;
 
        if (spi->u.QPstandardInfo.lastWriteDateTime != 0) {
-           smb_UnixTimeFromSearchTime(&attr.clientModTime, spi->u.QPstandardInfo.lastWriteDateTime);
+           cm_UnixTimeFromSearchTime(&attr.clientModTime, spi->u.QPstandardInfo.lastWriteDateTime);
             attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
-            fidp->flags |= SMB_FID_MTIMESETDONE;
         }
                
         if (spi->u.QPstandardInfo.attributes != 0) {
-            if ((scp->unixModeBits & 0222)
+            if ((scp->unixModeBits & 0200)
                  && (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) != 0) {
                 /* make a writable file read-only */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
                 attr.unixModeBits = scp->unixModeBits & ~0222;
             }
-            else if ((scp->unixModeBits & 0222) == 0
+            else if ((scp->unixModeBits & 0200) == 0
                       && (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) == 0) {
                 /* make a read-only file writable */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
@@ -3352,7 +3658,6 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
             }
         }
         lock_ReleaseRead(&scp->rw);
-       lock_ReleaseMutex(&fidp->mx);
 
         /* call setattr */
         if (attr.mask)
@@ -3368,7 +3673,6 @@ long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
   done:
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
-    smb_ReleaseFID(fidp);
     if (code == 0) 
         smb_SendTran2Packet(vcp, outp, opx);
     else 
@@ -3403,16 +3707,21 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     fidp = smb_FindFID(vcp, fid, 0);
 
     if (fidp == NULL) {
+        osi_Log2(smb_logp, "Tran2QFileInfo Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
         return 0;
     }
 
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
         smb_CloseFID(vcp, fidp, NULL, 0);
         smb_ReleaseFID(fidp);
         return 0;
     }
+    lock_ReleaseMutex(&fidp->mx);
 
     infoLevel = p->parmsp[1];
     if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) 
@@ -3423,14 +3732,17 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         responseSize = sizeof(qfi.u.QFeaInfo);
     else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) 
         responseSize = sizeof(qfi.u.QFfileNameInfo);
+    else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO)
+        responseSize = sizeof(qfi.u.QFfileStreamInfo);
     else {
-        osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+        osi_Log2(smb_logp, "Bad Tran2QFileInfo op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
         smb_ReleaseFID(fidp);
         return 0;
     }
     osi_Log2(smb_logp, "T2 QFileInfo type 0x%x fid %d", infoLevel, fid);
+    memset(&qfi, 0, sizeof(qfi));
 
     outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
 
@@ -3438,7 +3750,6 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         outp->totalParms = 2;
     else
         outp->totalParms = 0;
-    outp->totalData = responseSize;
 
     userp = smb_GetTran2User(vcp, p);
     if (!userp) {
@@ -3468,7 +3779,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
      * Marshall the output data.
      */
     if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
-        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
         qfi.u.QFbasicInfo.creationTime = ft;
         qfi.u.QFbasicInfo.lastAccessTime = ft;
         qfi.u.QFbasicInfo.lastWriteTime = ft;
@@ -3503,9 +3814,28 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        lock_ReleaseMutex(&fidp->mx);
 
         smb_UnparseString(opx, qfi.u.QFfileNameInfo.fileName, name, &len, SMB_STRF_IGNORENUL);
-        outp->totalData = len + 4;     /* this is actually what we want to return */
+        responseSize = len + 4;        /* this is actually what we want to return */
         qfi.u.QFfileNameInfo.fileNameLength = len;
     }
+    else if (infoLevel == SMB_QUERY_FILE_STREAM_INFO) {
+        size_t len = 0;
+
+        if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+            scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+            scp->fileType == CM_SCACHETYPE_INVALID) {
+            /* Do not return the alternate streams for directories */
+            responseSize = 0;
+        } else {
+            /* For now we have no alternate streams */
+            qfi.u.QFfileStreamInfo.nextEntryOffset = 0;
+            qfi.u.QFfileStreamInfo.streamSize = scp->length;
+            qfi.u.QFfileStreamInfo.streamAllocationSize = scp->length;
+            smb_UnparseString(opx, qfi.u.QFfileStreamInfo.fileName, L"::$DATA", &len, SMB_STRF_IGNORENUL);
+            qfi.u.QFfileStreamInfo.streamNameLength = len;
+            responseSize -= (sizeof(qfi.u.QFfileStreamInfo.fileName) - len);
+        }
+    }
+    outp->totalData = responseSize;
 
     /* send and free the packets */
   done:
@@ -3546,21 +3876,16 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     fidp = smb_FindFID(vcp, fid, 0);
 
     if (fidp == NULL) {
+        osi_Log2(smb_logp, "Tran2SetFileInfo Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
         return 0;
     }
 
-    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
-        smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
-        smb_CloseFID(vcp, fidp, NULL, 0);
-        smb_ReleaseFID(fidp);
-        return 0;
-    }
-
     infoLevel = p->parmsp[1];
     osi_Log2(smb_logp,"ReceiveTran2SetFileInfo type 0x%x fid %d", infoLevel, fid);
     if (infoLevel > SMB_SET_FILE_END_OF_FILE_INFO || infoLevel < SMB_SET_FILE_BASIC_INFO) {
-        osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+        osi_Log2(smb_logp, "Bad Tran2SetFileInfo op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_BAD_LEVEL);
         smb_ReleaseFID(fidp);
@@ -3568,6 +3893,14 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     }
 
     lock_ObtainMutex(&fidp->mx);
+    if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHFILE);
+        smb_CloseFID(vcp, fidp, NULL, 0);
+        smb_ReleaseFID(fidp);
+        return 0;
+    }
+
     if (infoLevel == SMB_SET_FILE_DISPOSITION_INFO && 
        !(fidp->flags & SMB_FID_OPENDELETE)) {
        osi_Log3(smb_logp,"smb_ReceiveTran2SetFileInfo !SMB_FID_OPENDELETE fidp 0x%p scp 0x%p fidp->flags 0x%x", 
@@ -3642,19 +3975,19 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) && 
              lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
             attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
-            smb_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
+            cm_UnixTimeFromLargeSearchTime(&attr.clientModTime, &lastMod);
             fidp->flags |= SMB_FID_MTIMESETDONE;
         }
                
         attribute = sfi->u.QFbasicInfo.attributes;
         if (attribute != 0) {
-            if ((scp->unixModeBits & 0222)
+            if ((scp->unixModeBits & 0200)
                  && (attribute & SMB_ATTR_READONLY) != 0) {
                 /* make a writable file read-only */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
                 attr.unixModeBits = scp->unixModeBits & ~0222;
             }
-            else if ((scp->unixModeBits & 0222) == 0
+            else if ((scp->unixModeBits & 0200) == 0
                       && (attribute & SMB_ATTR_READONLY) == 0) {
                 /* make a read-only file writable */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
@@ -3837,15 +4170,21 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             /* 
              * We have a requested path.  Check to see if it is something 
              * we know about.
-                        *
-                        * But be careful because the name that we might be searching
-                        * for might be a known name with the final character stripped
-                        * off.  If we 
+             *
+             * But be careful because the name that we might be searching
+             * for might be a known name with the final character stripped
+             * off.
              */
             code = cm_NameI(cm_data.rootSCachep, &requestFileName[nbnLen+2],
                             CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
                             userp, NULL, &req, &scp);
-            if (code == 0) {
+            if (code == 0 ||
+                code == CM_ERROR_ALLDOWN ||
+                code == CM_ERROR_ALLBUSY ||
+                code == CM_ERROR_ALLOFFLINE ||
+                code == CM_ERROR_NOSUCHCELL ||
+                code == CM_ERROR_NOSUCHVOLUME ||
+                code == CM_ERROR_NOACCESS) {
                 /* Yes it is. */
                 found = 1;
                 cm_ClientStrCpy(referralPath, lengthof(referralPath), requestFileName);
@@ -3872,6 +4211,7 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                         cm_ReleaseSCache(scp);
                         scp = 0;
                     }
+                    /* smb_StripLastComponent will strip "::$DATA" if present */
                     smb_StripLastComponent(pathName, &lastComponent, temp);
 
                     code = cm_NameI(cm_data.rootSCachep, pathName,
@@ -3956,6 +4296,8 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             for ( i=0;i<=refLen; i++ )
                 sp[i+idx] = referralPath[i];
 #endif
+        } else {
+            code = CM_ERROR_NOSUCHPATH;
         } 
     } else {
         code = CM_ERROR_NOSUCHPATH;
@@ -4127,17 +4469,22 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
                 switch (scp->fileType) {
                 case CM_SCACHETYPE_DIRECTORY:
                 case CM_SCACHETYPE_MOUNTPOINT:
-                case CM_SCACHETYPE_SYMLINK:
                 case CM_SCACHETYPE_INVALID:
                     fa->extFileAttributes = SMB_ATTR_DIRECTORY;
                     break;
+                case CM_SCACHETYPE_SYMLINK:
+                    if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+                        fa->extFileAttributes = SMB_ATTR_DIRECTORY;
+                    else
+                        fa->extFileAttributes = SMB_ATTR_NORMAL;
+                    break;
                 default:
                     /* if we get here we either have a normal file
                      * or we have a file for which we have never 
                      * received status info.  In this case, we can
                      * check the even/odd value of the entry's vnode.
-                     * even means it is to be treated as a directory
-                     * and odd means it is to be treated as a file.
+                     * odd means it is to be treated as a directory
+                     * and even means it is to be treated as a file.
                      */
                     if (mustFake && (scp->fid.vnode & 0x1))
                         fa->extFileAttributes = SMB_ATTR_DIRECTORY;
@@ -4162,10 +4509,15 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
                 switch (scp->fileType) {
                 case CM_SCACHETYPE_DIRECTORY:
                 case CM_SCACHETYPE_MOUNTPOINT:
-                case CM_SCACHETYPE_SYMLINK:
                 case CM_SCACHETYPE_INVALID:
                     fa->attributes = SMB_ATTR_DIRECTORY;
                     break;
+                case CM_SCACHETYPE_SYMLINK:
+                    if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+                        fa->attributes = SMB_ATTR_DIRECTORY;
+                    else
+                        fa->attributes = SMB_ATTR_NORMAL;
+                    break;
                 default:
                     /* if we get here we either have a normal file
                      * or we have a file for which we have never 
@@ -4219,7 +4571,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
             smb_V3FileAttrsLong * fa = (smb_V3FileAttrsLong *) patchp->dptr;
 
             /* get filetime */
-            smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+            cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
 
             fa->creationTime = ft;
             fa->lastAccessTime = ft;
@@ -4232,7 +4584,9 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
 
             /* Copy attributes */
             lattr = smb_ExtAttributes(scp);
-            if (code == CM_ERROR_NOSUCHPATH && scp->fileType == CM_SCACHETYPE_SYMLINK ||
+            if ((code == CM_ERROR_NOSUCHPATH && 
+                (scp->fileType == CM_SCACHETYPE_SYMLINK && 
+                cm_TargetPerceivedAsDirectory(scp->mountPointStringp))) ||
                 code == CM_ERROR_PATH_NOT_COVERED && scp->fileType == CM_SCACHETYPE_DFSLINK) {
                 if (lattr == SMB_ATTR_NORMAL)
                     lattr = SMB_ATTR_DIRECTORY;
@@ -4252,7 +4606,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp, smb_dirListPatch_t **dirPatchespp,
             smb_V3FileAttrsShort * fa = (smb_V3FileAttrsShort *) patchp->dptr;
 
             /* get dos time */
-            smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
+            cm_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
 
             fa->creationDateTime = MAKELONG(HIWORD(dosTime), LOWORD(dosTime));
             fa->lastAccessDateTime = fa->creationDateTime;
@@ -4462,6 +4816,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
 
     /* try to get the vnode for the path name next */
     spacep = cm_GetSpace();
+    /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, NULL, pathp);
     code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
     if (code) {
@@ -4491,7 +4846,7 @@ long smb_T2SearchDirSingle(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op
         if ( WANTS_DFS_PATHNAMES(p) || pnc )
            code = CM_ERROR_PATH_NOT_COVERED;
        else
-           code = CM_ERROR_BADSHARENAME;
+           code = CM_ERROR_NOSUCHPATH;
        smb_SendTran2Error(vcp, p, opx, code);
        smb_FreeTran2Packet(outp);
        return 0;
@@ -4982,6 +5337,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         code = 0;
     } else {
         spacep = cm_GetSpace();
+        /* smb_StripLastComponent will strip "::$DATA" if present */
         smb_StripLastComponent(spacep->wdata, NULL, pathp);
         code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
         if (code) {
@@ -5011,7 +5367,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 if ( WANTS_DFS_PATHNAMES(p) || pnc )
                     code = CM_ERROR_PATH_NOT_COVERED;
                 else
-                    code = CM_ERROR_BADSHARENAME;
+                    code = CM_ERROR_NOSUCHPATH;
                 smb_SendTran2Error(vcp, p, opx, code);
                 smb_FreeTran2Packet(outp);
                 lock_ReleaseMutex(&dsp->mx);
@@ -5150,7 +5506,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 bufferp = NULL;
             }       
             lock_ReleaseWrite(&scp->rw);
-            code = buf_Get(scp, &thyper, &bufferp);
+            code = buf_Get(scp, &thyper, &req, &bufferp);
             lock_ObtainWrite(&scp->rw);
             if (code) {
                 osi_Log2(smb_logp, "T2 search dir buf_Get scp %x failed %d", scp, code);
@@ -5238,8 +5594,13 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         if (dep->fid.vnode == 0) 
             goto nextEntry;             /* This entry is not in use */
 
-        cm_FsStringToClientString(dep->name, -1, cfileName, lengthof(cfileName));
-        cm_ClientStringToNormString(cfileName, -1, normName, lengthof(normName));
+        if (cm_FsStringToClientString(dep->name, -1, cfileName, lengthof(cfileName)) == 0 ||
+            cm_ClientStringToNormString(cfileName, -1, normName, lengthof(normName)) == 0) {
+
+            osi_Log1(smb_logp, "Skipping entry [%s].  Can't convert or normalize FS String",
+                     osi_LogSaveString(smb_logp, dep->name));
+            goto nextEntry;
+        }
 
         /* Need 8.3 name? */
         NeedShortName = 0;
@@ -5581,6 +5942,8 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     clientchar_t *tidPathp;
     cm_req_t req;
     int created = 0;
+    BOOL is_rpc = FALSE;
+    BOOL is_ipc = FALSE;
 
     smb_InitReq(&req);
 
@@ -5603,24 +5966,48 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     pathp = smb_ParseASCIIBlock(inp, smb_GetSMBData(inp, NULL), NULL,
                                 SMB_STRF_ANSIPATH);
+    if (!pathp)
+        return CM_ERROR_BADSMB;
+
+    code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+    if (code) {
+       if (code == CM_ERROR_TIDIPC) {
+           is_ipc = TRUE;
+       } else {
+           return CM_ERROR_NOSUCHPATH;
+       }
+    }
 
     spacep = inp->spacep;
+    /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
 
     if (lastNamep && 
-        (cm_ClientStrCmpIA(lastNamep,  _C(SMB_IOCTL_FILENAME)) == 0 ||
-         cm_ClientStrCmpIA(lastNamep,  _C("\\srvsvc")) == 0 ||
-         cm_ClientStrCmpIA(lastNamep,  _C("\\wkssvc")) == 0 ||
-         cm_ClientStrCmpIA(lastNamep,  _C("ipc$")) == 0)) {
+
         /* special case magic file name for receiving IOCTL requests
          * (since IOCTL calls themselves aren't getting through).
          */
-#ifdef NOTSERVICE
-        osi_Log0(smb_logp, "IOCTL Open");
-#endif
+        (cm_ClientStrCmpIA(lastNamep,  _C(SMB_IOCTL_FILENAME)) == 0 ||
+
+        /* Or an RPC endpoint (is_rpc = TRUE assignment is intentional) */
+         (is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)))) {
+
+       unsigned short file_type = 0;
+       unsigned short device_state = 0;
 
         fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-        smb_SetupIoctlFid(fidp, spacep);
+       if (is_rpc) {
+           code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+           osi_Log1(smb_logp, "OpenAndX Setting up RPC on fid[%d]", fidp->fid);
+           if (code) {
+               osi_Log1(smb_logp, "smb_SetupRPCFid failure code [%d]", code);
+               smb_ReleaseFID(fidp);
+               return code;
+           }
+       } else {
+           smb_SetupIoctlFid(fidp, spacep);
+           osi_Log1(smb_logp, "OpenAndX Setting up IOCTL on fid[%d]", fidp->fid);
+       }
 
         /* set inp->fid so that later read calls in same msg can find fid */
         inp->fid = fidp->fid;
@@ -5635,9 +6022,9 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* len */
             smb_SetSMBParm(outp, parmSlot, 0x7fff); parmSlot++;
             smb_SetSMBParm(outp, parmSlot, openMode); parmSlot++;
-            smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* file type 0 ==> normal file or dir */
-            smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* IPC junk */
-        }   
+            smb_SetSMBParm(outp, parmSlot, file_type); parmSlot++;
+            smb_SetSMBParm(outp, parmSlot, device_state); parmSlot++;
+        }
         /* and the final "always present" stuff */
         smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
         /* next write out the "unique" ID */
@@ -5651,6 +6038,28 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         return 0;
     }
 
+#ifndef DFS_SUPPORT
+    if (is_ipc) {
+       osi_Log0(smb_logp, "NTOpenX rejecting IPC TID");
+       return CM_ERROR_BADFD;
+    }
+#endif
+
+    if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+        clientchar_t * hexp;
+
+        hexp = cm_GetRawCharsAlloc(pathp, -1);
+        osi_Log1(smb_logp, "NTOpenX rejecting invalid name. [%S]",
+                 osi_LogSaveClientString(smb_logp, hexp));
+        if (hexp)
+            free(hexp);
+#else
+        osi_Log0(smb_logp, "NTOpenX rejecting invalid name");
+#endif
+        return CM_ERROR_BADNTFILENAME;
+    }
+
 #ifdef DEBUG_VERBOSE
     {
        char *hexp, *asciip;
@@ -5663,11 +6072,6 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     userp = smb_GetUserFromVCP(vcp, inp);
 
     dscp = NULL;
-    code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
-    if (code) {
-        cm_ReleaseUser(userp);
-        return CM_ERROR_NOSUCHPATH;
-    }
     code = cm_NameI(cm_data.rootSCachep, pathp,
                     CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                     userp, tidPathp, &req, &scp);
@@ -5680,7 +6084,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         if ( WANTS_DFS_PATHNAMES(inp) || pnc )
             return CM_ERROR_PATH_NOT_COVERED;
         else
-            return CM_ERROR_BADSHARENAME;
+            return CM_ERROR_NOSUCHPATH;
     }
 #endif /* DFS_SUPPORT */
 
@@ -5702,7 +6106,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
-                return CM_ERROR_BADSHARENAME;
+                return CM_ERROR_NOSUCHPATH;
         }
 #endif /* DFS_SUPPORT */
         /* otherwise, scp points to the parent directory.  Do a lookup,
@@ -5931,16 +6335,19 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fid = smb_ChainFID(fid, inp);
 
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "V3LockingX Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
        return CM_ERROR_BADFD;
-    
+    }
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_CloseFID(vcp, fidp, NULL, 0);
         smb_ReleaseFID(fidp);
         return CM_ERROR_NOSUCHFILE;
     }
 
-    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL) {
         osi_Log0(smb_logp, "smb_ReceiveV3Locking BadFD");
        lock_ReleaseMutex(&fidp->mx);
@@ -5957,7 +6364,6 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     userp = smb_GetUserFromVCP(vcp, inp);
 
-
     lock_ObtainWrite(&scp->rw);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK
@@ -6004,7 +6410,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             for (wlRequest = smb_allWaitingLocks; wlRequest; wlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q))
             {
                 for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
-                    if (wl->key == key && LargeIntegerEqualTo(wl->LOffset, LOffset) && 
+                    if (cm_KeyEquals(&wl->key, &key, 0) && LargeIntegerEqualTo(wl->LOffset, LOffset) && 
                         LargeIntegerEqualTo(wl->LLength, LLength)) {
                         wl->state = SMB_WAITINGLOCKSTATE_CANCELLED;
                         goto found_lock_request;
@@ -6025,7 +6431,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         key = cm_GenerateKey(vcp->vcID, pid, fidp->fid);
 
-        code = cm_Unlock(scp, LockType, LOffset, LLength, key, userp, &req);
+        code = cm_Unlock(scp, LockType, LOffset, LLength, key, 0, userp, &req);
 
         if (code) 
             goto done;
@@ -6048,7 +6454,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                            userp, &req, &lockp);
        }
 
-        if (code == CM_ERROR_WOULDBLOCK && Timeout != 0) {
+        if (code == CM_ERROR_LOCK_NOT_GRANTED && Timeout != 0) {
             smb_waitingLock_t * wLock;
 
             /* Put on waiting list */
@@ -6147,7 +6553,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
                 wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
 
-                ul_code = cm_Unlock(scp, LockType, wl->LOffset, wl->LLength, wl->key, userp, &req);
+                ul_code = cm_Unlock(scp, LockType, wl->LOffset, wl->LLength, wl->key, 0, userp, &req);
                 
                 if(ul_code != 0) {
                     osi_Log1(smb_logp, "smb_ReceiveV3Locking cm_Unlock returns code %d", ul_code);
@@ -6217,16 +6623,19 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     fid = smb_ChainFID(fid, inp);
         
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "V3GetAttributes Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
        return CM_ERROR_BADFD;
-    
+    }
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_CloseFID(vcp, fidp, NULL, 0);
         smb_ReleaseFID(fidp);
         return CM_ERROR_NOSUCHFILE;
     }
 
-    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL) {
        lock_ReleaseMutex(&fidp->mx);
        smb_ReleaseFID(fidp);
@@ -6256,7 +6665,7 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
      * call provides the date first, not the time, as returned in the
      * searchTime variable.  So we take the high-order bits first.
      */
-    smb_SearchTimeFromUnixTime(&searchTime, scp->clientModTime);
+    cm_SearchTimeFromUnixTime(&searchTime, scp->clientModTime);
     smb_SetSMBParm(outp, 0, (searchTime >> 16) & 0xffff);      /* ctime */
     smb_SetSMBParm(outp, 1, searchTime & 0xffff);
     smb_SetSMBParm(outp, 2, (searchTime >> 16) & 0xffff);      /* atime */
@@ -6307,16 +6716,19 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     fid = smb_ChainFID(fid, inp);
         
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "V3SetAttributes Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
        return CM_ERROR_BADFD;
-    
+    }
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_CloseFID(vcp, fidp, NULL, 0);
         smb_ReleaseFID(fidp);
         return CM_ERROR_NOSUCHFILE;
     }
 
-    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL) {
        lock_ReleaseMutex(&fidp->mx);
        smb_ReleaseFID(fidp);
@@ -6329,7 +6741,6 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         
     userp = smb_GetUserFromVCP(vcp, inp);
         
-        
     /* now prepare to call cm_setattr.  This message only sets various times,
      * and AFS only implements mtime, and we'll set the mtime if that's
      * requested.  The others we'll ignore.
@@ -6337,7 +6748,7 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     searchTime = smb_GetSMBParm(inp, 5) | (smb_GetSMBParm(inp, 6) << 16);
         
     if (searchTime != 0) {
-        smb_UnixTimeFromSearchTime(&unixTime, searchTime);
+        cm_UnixTimeFromSearchTime(&unixTime, searchTime);
 
         if ( unixTime != -1 ) {
             attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
@@ -6346,7 +6757,7 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
 
             osi_Log1(smb_logp, "SMB receive V3SetAttributes [fid=%ld]", fid);
         } else {
-            osi_Log1(smb_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
+            osi_Log1(smb_logp, "**cm_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
         }
     }
     else 
@@ -6368,6 +6779,7 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_fid_t *fidp;
     smb_t *smbp = (smb_t*) inp;
     long code = 0;
+    cm_scache_t *scp;
     cm_user_t *userp;
     char *op;
     int inDataBlockCount;
@@ -6388,7 +6800,7 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             osi_Log0(smb_logp, "smb_ReceiveV3WriteX offset requires largefile support");
             /* we shouldn't have received this op if we didn't specify
                largefile support */
-            return CM_ERROR_BADOP;
+            return CM_ERROR_INVAL;
         }
 #endif
     }
@@ -6401,23 +6813,43 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
-    if (!fidp)
+    if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveV3WriteX Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
         return CM_ERROR_BADFD;
-        
+    }
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_CloseFID(vcp, fidp, NULL, 0);
         smb_ReleaseFID(fidp);
         return CM_ERROR_NOSUCHFILE;
     }
 
-    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL) {
        lock_ReleaseMutex(&fidp->mx);
         code = smb_IoctlV3Write(fidp, vcp, inp, outp);
        smb_ReleaseFID(fidp);
        return code;
     }
+
+    if (fidp->flags & SMB_FID_RPC) {
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_RPCV3Write(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
+    }
+
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_BADFDOP;
+    }
+
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
     lock_ReleaseMutex(&fidp->mx);
+
     userp = smb_GetUserFromVCP(vcp, inp);
 
     /* special case: 0 bytes transferred means there is no data
@@ -6429,7 +6861,6 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         cm_key_t key;
         LARGE_INTEGER LOffset;
         LARGE_INTEGER LLength;
-        cm_scache_t * scp;
 
         pid = smbp->pid;
         key = cm_GenerateKey(vcp->vcID, pid, fd);
@@ -6439,7 +6870,6 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         LLength.HighPart = 0;
         LLength.LowPart = count;
 
-        scp = fidp->scp;
         lock_ObtainWrite(&scp->rw);
         code = cm_LockCheckWrite(scp, LOffset, LLength, key);
         lock_ReleaseWrite(&scp->rw);
@@ -6460,8 +6890,10 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
      */
     lock_ObtainMutex(&fidp->mx);
     if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
-        fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
-        fidp->scp->clientModTime = time(NULL);
+        lock_ObtainWrite(&fidp->scp->rw);
+        scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+        scp->clientModTime = time(NULL);
+        lock_ReleaseWrite(&fidp->scp->rw);
     }
     lock_ReleaseMutex(&fidp->mx);
 
@@ -6487,6 +6919,8 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_SetSMBDataLength(outp, 0);
 
  done:
+
+    cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
 
@@ -6504,12 +6938,13 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_fid_t *fidp;
     smb_t *smbp = (smb_t*) inp;
     long code = 0;
+    cm_scache_t *scp;
     cm_user_t *userp;
     cm_key_t key;
     char *op;
         
-    fd = smb_GetSMBParm(inp, 2);
-    count = smb_GetSMBParm(inp, 5);
+    fd = smb_GetSMBParm(inp, 2); /* File ID */
+    count = smb_GetSMBParm(inp, 5); /* MaxCount */
     offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
 
     if (*inp->wctp == 12) {
@@ -6540,31 +6975,62 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp) {
+        osi_Log2(smb_logp, "smb_ReceiveV3Read Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fd);
         return CM_ERROR_BADFD;
     }
 
+    lock_ObtainMutex(&fidp->mx);
+
+    if (fidp->flags & SMB_FID_IOCTL) {
+       lock_ReleaseMutex(&fidp->mx);
+       inp->fid = fd;
+        code = smb_IoctlV3Read(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
+    }
+
+    if (fidp->flags & SMB_FID_RPC) {
+       lock_ReleaseMutex(&fidp->mx);
+       inp->fid = fd;
+        code = smb_RPCV3Read(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
+    }
+
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_CloseFID(vcp, fidp, NULL, 0);
         smb_ReleaseFID(fidp);
         return CM_ERROR_NOSUCHFILE;
     }
 
+    if (!fidp->scp) {
+        lock_ReleaseMutex(&fidp->mx);
+        smb_ReleaseFID(fidp);
+        return CM_ERROR_BADFDOP;
+    }
+
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
+
+    lock_ReleaseMutex(&fidp->mx);
+
     pid = smbp->pid;
     key = cm_GenerateKey(vcp->vcID, pid, fd);
     {
         LARGE_INTEGER LOffset, LLength;
-        cm_scache_t *scp;
 
         LOffset.HighPart = offset.HighPart;
         LOffset.LowPart = offset.LowPart;
         LLength.HighPart = 0;
         LLength.LowPart = count;
 
-        scp = fidp->scp;
         lock_ObtainWrite(&scp->rw);
         code = cm_LockCheckRead(scp, LOffset, LLength, key);
         lock_ReleaseWrite(&scp->rw);
     }
+    cm_ReleaseSCache(scp);
 
     if (code) {
         smb_ReleaseFID(fidp);
@@ -6574,15 +7040,6 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* set inp->fid so that later read calls in same msg can find fid */
     inp->fid = fd;
 
-    lock_ObtainMutex(&fidp->mx);
-    if (fidp->flags & SMB_FID_IOCTL) {
-       lock_ReleaseMutex(&fidp->mx);
-        code = smb_IoctlV3Read(fidp, vcp, inp, outp);
-       smb_ReleaseFID(fidp);
-       return code;
-    }
-    lock_ReleaseMutex(&fidp->mx);
-
     userp = smb_GetUserFromVCP(vcp, inp);
 
     /* 0 and 1 are reserved for request chaining, were setup by our caller,
@@ -6647,6 +7104,12 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 #define FILE_RANDOM_ACCESS        0x0800
 #define FILE_DELETE_ON_CLOSE      0x1000
 #define FILE_OPEN_BY_FILE_ID      0x2000
+#define FILE_OPEN_FOR_BACKUP_INTENT             0x00004000
+#define FILE_NO_COMPRESSION                     0x00008000
+#define FILE_RESERVE_OPFILTER                   0x00100000
+#define FILE_OPEN_REPARSE_POINT                 0x00200000
+#define FILE_OPEN_NO_RECALL                     0x00400000
+#define FILE_OPEN_FOR_FREE_SPACE_QUERY          0x00800000
 
 /* SMB_COM_NT_CREATE_ANDX */
 long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
@@ -6689,7 +7152,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     cm_req_t req;
     int created = 0;
     int prefetch = 0;
+    int checkDoneRequired = 0;
     cm_lock_data_t *ldp = NULL;
+    BOOL is_rpc = FALSE;
+    BOOL is_ipc = FALSE;
 
     smb_InitReq(&req);
 
@@ -6755,23 +7221,57 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     realPathp[nameLength/sizeof(clientchar_t)] = 0;
 
     spacep = inp->spacep;
+    /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
 
     osi_Log1(smb_logp,"NTCreateX for [%S]",osi_LogSaveClientString(smb_logp,realPathp));
     osi_Log4(smb_logp,"... da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
     osi_Log3(smb_logp,"... share=[%x] flags=[%x] lastNamep=[%S]", shareAccess, flags, osi_LogSaveClientString(smb_logp,(lastNamep?lastNamep:_C("null"))));
 
-       if (lastNamep && 
-            (cm_ClientStrCmpIA(lastNamep,  _C(SMB_IOCTL_FILENAME)) == 0 ||
-             cm_ClientStrCmpIA(lastNamep,  _C("\\srvsvc")) == 0 ||
-             cm_ClientStrCmpIA(lastNamep,  _C("\\wkssvc")) == 0 ||
-             cm_ClientStrCmpIA(lastNamep,  _C("ipc$")) == 0)) {
-        /* special case magic file name for receiving IOCTL requests
-         * (since IOCTL calls themselves aren't getting through).
-         */
+    if (baseFid == 0) {
+       baseFidp = NULL;
+        baseDirp = cm_data.rootSCachep;
+        code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
+        if (code == CM_ERROR_TIDIPC) {
+            /* Attempt to use a TID allocated for IPC.  The client
+             * is probably looking for DCE RPC end points which we
+             * don't support OR it could be looking to make a DFS
+             * referral request.
+             */
+            osi_Log0(smb_logp, "NTCreateX received IPC TID");
+           is_ipc = TRUE;
+        }
+    }
+
+    osi_Log1(smb_logp, "NTCreateX tidPathp=[%S]", (tidPathp==NULL)?_C("null"): osi_LogSaveClientString(smb_logp,tidPathp));
+
+    if (lastNamep &&
+
+       ((is_ipc && MSRPC_IsWellKnownService(lastNamep) && (is_rpc = TRUE)) ||
+
+        /* special case magic file name for receiving IOCTL requests
+         * (since IOCTL calls themselves aren't getting through).
+         */
+        cm_ClientStrCmpIA(lastNamep,  _C(SMB_IOCTL_FILENAME)) == 0)) {
+
+       unsigned short file_type = 0;
+       unsigned short device_state = 0;
+
         fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-        smb_SetupIoctlFid(fidp, spacep);
-        osi_Log1(smb_logp,"NTCreateX Setting up IOCTL on fid[%d]",fidp->fid);
+
+       if (is_rpc) {
+           code = smb_SetupRPCFid(fidp, lastNamep, &file_type, &device_state);
+           osi_Log1(smb_logp, "NTCreateX Setting up RPC on fid[%d]", fidp->fid);
+           if (code) {
+               osi_Log1(smb_logp, "smb_SetupRPCFid() failure code [%d]", code);
+               smb_ReleaseFID(fidp);
+               free(realPathp);
+               return code;
+           }
+       } else {
+           smb_SetupIoctlFid(fidp, spacep);
+           osi_Log1(smb_logp, "NTCreateX Setting up IOCTL on fid[%d]", fidp->fid);
+       }
 
         /* set inp->fid so that later read calls in same msg can find fid */
         inp->fid = fidp->fid;
@@ -6791,8 +7291,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         sz.HighPart = 0x7fff; sz.LowPart = 0;
         smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* alen */
         smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* len */
-        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
-        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */
+        smb_SetSMBParm(outp, parmSlot, file_type); parmSlot++; /* filetype */
+        smb_SetSMBParm(outp, parmSlot, device_state); parmSlot++;      /* dev state */
         smb_SetSMBParmByte(outp, parmSlot, 0); /* is a dir? */
         smb_SetSMBDataLength(outp, 0);
 
@@ -6802,16 +7302,30 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         return 0;
     }
 
-#ifdef DEBUG_VERBOSE
-    {
-       char *hexp, *asciip;
-       asciip = (lastNamep? lastNamep : realPathp);
-       hexp = osi_HexifyString( asciip );
-       DEBUG_EVENT2("AFS", "NTCreateX H[%s] A[%s]", hexp, asciip);
-       free(hexp);
+#ifndef DFS_SUPPORT
+    if (is_ipc) {
+       osi_Log0(smb_logp, "NTCreateX rejecting IPC TID");
+       free(realPathp);
+       return CM_ERROR_BADFD;
     }
 #endif
 
+    if (!cm_IsValidClientString(realPathp)) {
+#ifdef DEBUG
+        clientchar_t * hexp;
+
+        hexp = cm_GetRawCharsAlloc(realPathp, -1);
+        osi_Log1(smb_logp, "NTCreateX rejecting invalid name. [%S]",
+                 osi_LogSaveClientString(smb_logp, hexp));
+        if (hexp)
+           free(hexp);
+#else
+        osi_Log0(smb_logp, "NTCreateX rejecting invalid name");
+#endif
+        free(realPathp);
+        return CM_ERROR_BADNTFILENAME;
+    }
+
     userp = smb_GetUserFromVCP(vcp, inp);
     if (!userp) {
        osi_Log1(smb_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
@@ -6819,37 +7333,20 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        return CM_ERROR_INVAL;
     }
 
-    if (baseFid == 0) {
-       baseFidp = NULL;
-        baseDirp = cm_data.rootSCachep;
-        code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
-        if (code == CM_ERROR_TIDIPC) {
-            /* Attempt to use a TID allocated for IPC.  The client
-             * is probably looking for DCE RPC end points which we
-             * don't support OR it could be looking to make a DFS
-             * referral request. 
-             */
-            osi_Log0(smb_logp, "NTCreateX received IPC TID");
-#ifndef DFS_SUPPORT
-            free(realPathp);
-            cm_ReleaseUser(userp);
-            return CM_ERROR_NOSUCHFILE;
-#endif /* DFS_SUPPORT */
-        }
-    } else {
+    if (baseFidp != 0) {
         baseFidp = smb_FindFID(vcp, baseFid, 0);
         if (!baseFidp) {
             osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid);
+           cm_ReleaseUser(userp);
             free(realPathp);
-            cm_ReleaseUser(userp);
             return CM_ERROR_INVAL;
-        }       
+        }
 
         if (baseFidp->scp && (baseFidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
             free(realPathp);
-            cm_ReleaseUser(userp);
            smb_CloseFID(vcp, baseFidp, NULL, 0);
             smb_ReleaseFID(baseFidp);
+           cm_ReleaseUser(userp);
             return CM_ERROR_NOSUCHPATH;
         }
 
@@ -6857,8 +7354,6 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         tidPathp = NULL;
     }
 
-    osi_Log1(smb_logp, "NTCreateX tidPathp=[%S]", (tidPathp==NULL)?_C("null"): osi_LogSaveClientString(smb_logp,tidPathp));
-
     /* compute open mode */
     fidflags = 0;
     if (desiredAccess & DELETE)
@@ -6873,6 +7368,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        fidflags |= SMB_FID_SEQUENTIAL;
     if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
        fidflags |= SMB_FID_RANDOM;
+    if (createOptions & FILE_OPEN_REPARSE_POINT)
+        osi_Log0(smb_logp, "NTCreateX Open Reparse Point");
     if (smb_IsExecutableFileName(lastNamep))
         fidflags |= SMB_FID_EXECUTABLE;
 
@@ -6904,7 +7401,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
-                    return CM_ERROR_BADSHARENAME;
+                    return CM_ERROR_NOSUCHPATH;
             }
 #endif /* DFS_SUPPORT */
             code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
@@ -6938,7 +7435,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
-                return CM_ERROR_BADSHARENAME;
+                return CM_ERROR_NOSUCHPATH;
         }
 #endif /* DFS_SUPPORT */
         /* we might have scp but not dscp */
@@ -6978,7 +7475,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                         return CM_ERROR_PATH_NOT_COVERED;
                     else
-                        return CM_ERROR_BADSHARENAME;
+                        return CM_ERROR_NOSUCHPATH;
                 }
 #endif /* DFS_SUPPORT */
 
@@ -7081,6 +7578,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (code == 0 && !treeCreate) {
         code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
         if (code) {
+            cm_CheckNTOpenDone(scp, userp, &req, &ldp);
             if (dscp)
                 cm_ReleaseSCache(dscp);
             if (scp)
@@ -7089,6 +7587,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             free(realPathp);
             return code;
         }
+        checkDoneRequired = 1;
 
        if (createDisp == FILE_CREATE) {
             /* oops, file shouldn't be there */
@@ -7126,6 +7625,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     scp = targetScp;
                    code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
                    if (code) {
+                        cm_CheckNTOpenDone(scp, userp, &req, &ldp);
                        if (dscp)
                            cm_ReleaseSCache(dscp);
                        if (scp)
@@ -7290,7 +7790,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     if (code) {
         /* something went wrong creating or truncating the file */
-       if (ldp)
+       if (checkDoneRequired)
            cm_CheckNTOpenDone(scp, userp, &req, &ldp);
         if (scp) 
             cm_ReleaseSCache(scp);
@@ -7314,15 +7814,17 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 * we'll just use the symlink anyway.
                 */
                 osi_Log2(smb_logp, "symlink vp %x to vp %x", scp, targetScp);
-               if (ldp)
+               if (checkDoneRequired) {
                    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+                    checkDoneRequired = 0;
+                }
                 cm_ReleaseSCache(scp);
                 scp = targetScp;
             }
         }
 
         if (scp->fileType != CM_SCACHETYPE_FILE) {
-           if (ldp)
+           if (checkDoneRequired)
                cm_CheckNTOpenDone(scp, userp, &req, &ldp);
             if (dscp)
                 cm_ReleaseSCache(dscp);
@@ -7335,7 +7837,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     /* (only applies to single component case) */
     if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
-       if (ldp)
+       if (checkDoneRequired)
            cm_CheckNTOpenDone(scp, userp, &req, &ldp);
         cm_ReleaseSCache(scp);
         if (dscp)
@@ -7384,7 +7886,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         lock_ReleaseWrite(&scp->rw);
 
         if (code) {
-           if (ldp)
+           if (checkDoneRequired)
                cm_CheckNTOpenDone(scp, userp, &req, &ldp);
             cm_ReleaseSCache(scp);
             if (dscp)
@@ -7394,13 +7896,15 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
            smb_CloseFID(vcp, fidp, NULL, 0);
            smb_ReleaseFID(fidp);
             free(realPathp);
-            return code;
+            return CM_ERROR_SHARING_VIOLATION;
         }
     }
 
     /* Now its safe to release the file server lock obtained by cm_CheckNTOpen() */
-    if (ldp)
+    if (checkDoneRequired) {
        cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+        checkDoneRequired = 0;
+    }
 
     lock_ObtainMutex(&fidp->mx);
     /* save a pointer to the vnode */
@@ -7438,39 +7942,82 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* set inp->fid so that later read calls in same msg can find fid */
     inp->fid = fidp->fid;
 
-    /* out parms */
-    parmSlot = 2;
     lock_ObtainRead(&scp->rw);
-    smb_SetSMBParmByte(outp, parmSlot, 0);     /* oplock */
-    smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
-    smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
-    smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
-    smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
-    smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
-    smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
-    smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
-    smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
-    parmSlot += 2;
-    smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
-    smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
-    smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* filetype */
-    smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* dev state */
-    smb_SetSMBParmByte(outp, parmSlot,
-                        (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
-                        scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
-                        scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
-    smb_SetSMBDataLength(outp, 0);
+
+    /*
+     * Always send the standard response.  Sending the extended
+     * response results in the Explorer Shell being unable to
+     * access directories at random times.
+     */
+    if (1 /*!extendedRespRequired */) {
+        /* out parms */
+        parmSlot = 2;
+        smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
+        smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+        smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
+        cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+        smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
+        parmSlot += 2;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
+        smb_SetSMBParm(outp, parmSlot, NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS);
+        parmSlot++;    /* dev state */
+        smb_SetSMBParmByte(outp, parmSlot,
+                            (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+                              scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+                              scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
+        smb_SetSMBDataLength(outp, 0);
+    } else {
+        /* out parms */
+        parmSlot = 2;
+        smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */
+        smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
+        smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2;
+        cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4;
+        smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp));
+        parmSlot += 2;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+        smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4;
+        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */
+        smb_SetSMBParm(outp, parmSlot, NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS);
+        parmSlot++;    /* dev state */
+        smb_SetSMBParmByte(outp, parmSlot,
+                            (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+                              scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+                              scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
+        /* Setting the GUID results in a failure with cygwin */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Maxmimal access rights */
+        smb_SetSMBParmLong(outp, parmSlot, 0x001f01ff); parmSlot += 2;
+        /* Guest access rights */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBDataLength(outp, 0);
+    }
 
     if ((fidp->flags & SMB_FID_EXECUTABLE) && 
-        LargeIntegerGreaterThanZero(fidp->scp->length) && 
+        LargeIntegerGreaterThanZero(scp->length) && 
         !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
         prefetch = 1;
     }
     lock_ReleaseRead(&scp->rw);
 
     if (prefetch)
-        cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
-                           fidp->scp->length.LowPart, fidp->scp->length.HighPart, 
+        cm_QueueBKGRequest(scp, cm_BkgPrefetch, 0, 0,
+                           scp->length.LowPart, scp->length.HighPart, 
                            userp);
 
 
@@ -7540,6 +8087,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     int created = 0;
     int prefetch = 0;
     cm_lock_data_t *ldp = NULL;
+    int checkDoneRequired = 0;
 
     smb_InitReq(&req);
 
@@ -7601,6 +8149,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     memcpy(realPathp, pathp, nameLength);
     realPathp[nameLength/sizeof(clientchar_t)] = 0;
     spacep = cm_GetSpace();
+    /* smb_StripLastComponent will strip "::$DATA" if present */
     smb_StripLastComponent(spacep->wdata, &lastNamep, realPathp);
 
     osi_Log1(smb_logp,"NTTranCreate %S",osi_LogSaveStringW(smb_logp,realPathp));
@@ -7613,15 +8162,21 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
      * Will add it if necessary.
      */
 
-#ifdef DEBUG_VERBOSE
-    {
-        char *hexp, *asciip;
-        asciip = (lastNamep? lastNamep : realPathp);
-        hexp = osi_HexifyString( asciip );
-        DEBUG_EVENT2("AFS", "NTTranCreate H[%s] A[%s]", hexp, asciip);
+    if (!cm_IsValidClientString(realPathp)) {
+#ifdef DEBUG
+        clientchar_t * hexp;
+
+        hexp = cm_GetRawCharsAlloc(realPathp, -1);
+        osi_Log1(smb_logp, "NTTranCreate rejecting invalid name. [%S]",
+                 osi_LogSaveClientString(smb_logp, hexp));
+        if (hexp)
         free(hexp);
-    }
+#else
+        osi_Log0(smb_logp, "NTTranCreate rejecting invalid name.");
 #endif
+        free(realPathp);
+        return CM_ERROR_BADNTFILENAME;
+    }
 
     userp = smb_GetUserFromVCP(vcp, inp);
     if (!userp) {
@@ -7650,7 +8205,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     } else {
         baseFidp = smb_FindFID(vcp, baseFid, 0);
         if (!baseFidp) {
-           osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+            osi_Log2(smb_logp, "NTTranCreate Unknown SMB Fid vcp 0x%p fid %d",
+                      vcp, baseFid);
             free(realPathp);
             cm_ReleaseUser(userp);
             return CM_ERROR_BADFD;
@@ -7682,6 +8238,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        fidflags |= SMB_FID_SEQUENTIAL;
     if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
        fidflags |= SMB_FID_RANDOM;
+    if (createOptions & FILE_OPEN_REPARSE_POINT)
+        osi_Log0(smb_logp, "NTTranCreate Open Reparse Point");
     if (smb_IsExecutableFileName(lastNamep))
         fidflags |= SMB_FID_EXECUTABLE;
 
@@ -7710,7 +8268,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                 if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
-                    return CM_ERROR_BADSHARENAME;
+                    return CM_ERROR_NOSUCHPATH;
             }
 #endif /* DFS_SUPPORT */
             code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
@@ -7744,7 +8302,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
             if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
-                return CM_ERROR_BADSHARENAME;
+                return CM_ERROR_NOSUCHPATH;
         }
 #endif /* DFS_SUPPORT */
     }
@@ -7769,7 +8327,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                 if ( WANTS_DFS_PATHNAMES(inp) || pnc )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
-                    return CM_ERROR_BADSHARENAME;
+                    return CM_ERROR_NOSUCHPATH;
             }
 #endif /* DFS_SUPPORT */
         } else
@@ -7824,6 +8382,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     if (code == 0) {
         code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
         if (code) {     
+            cm_CheckNTOpenDone(scp, userp, &req, &ldp);
             if (dscp) 
                 cm_ReleaseSCache(dscp);
             cm_ReleaseSCache(scp);
@@ -7831,6 +8390,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
             free(realPathp);
             return code;
         }
+        checkDoneRequired = 1;
 
         if (createDisp == FILE_CREATE) {
             /* oops, file shouldn't be there */
@@ -7866,6 +8426,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                     scp = targetScp;
                    code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req, &ldp);
                    if (code) {
+                        cm_CheckNTOpenDone(scp, userp, &req, &ldp);
                        if (dscp)
                            cm_ReleaseSCache(dscp);
                        if (scp)
@@ -7968,7 +8529,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
     if (code) {
         /* something went wrong creating or truncating the file */
-       if (ldp)
+       if (checkDoneRequired)
            cm_CheckNTOpenDone(scp, userp, &req, &ldp);
        if (scp) 
             cm_ReleaseSCache(scp);
@@ -7991,15 +8552,17 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                 */
                 osi_Log2(smb_logp, "symlink vp %x to vp %x",
                           scp, targetScp);
-               if (ldp)
+               if (checkDoneRequired) {
                    cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+                    checkDoneRequired = 0;
+                }
                 cm_ReleaseSCache(scp);
                 scp = targetScp;
             }
         }
 
         if (scp->fileType != CM_SCACHETYPE_FILE) {
-           if (ldp)
+           if (checkDoneRequired)
                cm_CheckNTOpenDone(scp, userp, &req, &ldp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
@@ -8009,7 +8572,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     }
 
     if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
-       if (ldp)
+       if (checkDoneRequired)
            cm_CheckNTOpenDone(scp, userp, &req, &ldp);
         cm_ReleaseSCache(scp);
         cm_ReleaseUser(userp);
@@ -8054,7 +8617,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         lock_ReleaseWrite(&scp->rw);
 
         if (code) {
-           if (ldp)
+           if (checkDoneRequired)
                cm_CheckNTOpenDone(scp, userp, &req, &ldp);
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
@@ -8067,8 +8630,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     }
 
     /* Now its safe to drop the file server lock obtained by cm_CheckNTOpen() */
-    if (ldp)
+    if (checkDoneRequired) {
        cm_CheckNTOpenDone(scp, userp, &req, &ldp);
+        checkDoneRequired = 0;
+    }
 
     lock_ObtainMutex(&fidp->mx);
     /* save a pointer to the vnode */
@@ -8140,7 +8705,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         *((USHORT *)outData) = fidp->fid; outData += 2;        /* fid */
         *((ULONG *)outData) = openAction; outData += 4;
         *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
-        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
         *((FILETIME *)outData) = ft; outData += 8;     /* creation time */
         *((FILETIME *)outData) = ft; outData += 8;     /* last access time */
         *((FILETIME *)outData) = ft; outData += 8;     /* last write time */
@@ -8149,7 +8714,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
         *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
         *((USHORT *)outData) = 0; outData += 2;        /* filetype */
-        *((USHORT *)outData) = 0; outData += 2;        /* dev state */
+        *((USHORT *)outData) = NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS;
+        outData += 2;  /* dev state */
         *((USHORT *)outData) = ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
                                scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
                                scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
@@ -8189,7 +8755,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         *((USHORT *)outData) = fidp->fid; outData += 2;        /* fid */
         *((ULONG *)outData) = openAction; outData += 4;
         *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
-        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
         *((FILETIME *)outData) = ft; outData += 8;     /* creation time */
         *((FILETIME *)outData) = ft; outData += 8;     /* last access time */
         *((FILETIME *)outData) = ft; outData += 8;     /* last write time */
@@ -8198,26 +8764,28 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
         *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
         *((USHORT *)outData) = 0; outData += 2;        /* filetype */
-        *((USHORT *)outData) = 0; outData += 2;        /* dev state */
+        *((USHORT *)outData) = NO_REPARSETAG|NO_SUBSTREAMS|NO_EAS;
+        outData += 2;  /* dev state */
         *((USHORT *)outData) = ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
                                scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
                                scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
         outData += 1;  /* is a dir? */
-        memset(outData,0,24); outData += 24; /* Volume ID and file ID */
+        /* Setting the GUID results in failures with cygwin */
+        memset(outData,0,24); outData += 24; /* GUID */
         *((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
         *((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
     }
 
     if ((fidp->flags & SMB_FID_EXECUTABLE) && 
-         LargeIntegerGreaterThanZero(fidp->scp->length) && 
+         LargeIntegerGreaterThanZero(scp->length) && 
          !(scp->flags & CM_SCACHEFLAG_PREFETCHING)) {
         prefetch = 1;
     }
     lock_ReleaseRead(&scp->rw);
 
     if (prefetch)
-        cm_QueueBKGRequest(fidp->scp, cm_BkgPrefetch, 0, 0,
-                           fidp->scp->length.LowPart, fidp->scp->length.HighPart, 
+        cm_QueueBKGRequest(scp, cm_BkgPrefetch, 0, 0,
+                           scp->length.LowPart, scp->length.HighPart, 
                            userp);
 
     osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
@@ -8247,15 +8815,21 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
 
     fidp = smb_FindFID(vcp, fid, 0);
     if (!fidp) {
-        osi_Log1(smb_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
+        osi_Log2(smb_logp, "NotifyChange Unknown SMB Fid vcp 0x%p fid %d",
+                 vcp, fid);
         return CM_ERROR_BADFD;
     }
 
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->scp && (fidp->scp->flags & CM_SCACHEFLAG_DELETED)) {
+        lock_ReleaseMutex(&fidp->mx);
         smb_CloseFID(vcp, fidp, NULL, 0);
         smb_ReleaseFID(fidp);
         return CM_ERROR_NOSUCHFILE;
     }
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
 
     /* Create a copy of the Directory Watch Packet to use when sending the
      * notification if in the future a matching change is detected.
@@ -8274,7 +8848,6 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
     smb_Directory_Watches = savedPacketp;
     lock_ReleaseMutex(&smb_Dir_Watch_Lock);
 
-    scp = fidp->scp;
     osi_Log3(smb_logp,"smb_ReceiveNTTranNotifyChange fidp 0x%p scp 0x%p file \"%S\"", 
              fidp, scp, osi_LogSaveClientString(smb_logp, fidp->NTopen_wholepathp));
     osi_Log3(smb_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d",
@@ -8310,6 +8883,7 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
     else
         scp->flags |= CM_SCACHEFLAG_WATCHED;
     lock_ReleaseWrite(&scp->rw);
+    cm_ReleaseSCache(scp);
     smb_ReleaseFID(fidp);
 
     outp->flags |= SMB_PACKETFLAG_NOSEND;
@@ -8439,7 +9013,7 @@ long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         osi_Log0(smb_logp, "SMB NT Transact Set Quota - not implemented");
         break;
     }
-    return CM_ERROR_INVAL;
+    return CM_ERROR_BADOP;
 }
 
 /*
@@ -8521,9 +9095,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
             osi_Log1(smb_logp," skipping fidp->scp[%x]", fidp->scp);
             lastWatch = watch;
             watch = watch->nextp;
-            lock_ReleaseMutex(&smb_Dir_Watch_Lock);
             smb_ReleaseFID(fidp);
-            lock_ObtainMutex(&smb_Dir_Watch_Lock);
             continue;
         }
 
@@ -8562,9 +9134,6 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
         else
             lastWatch->nextp = nextWatch;
 
-        /* The watch is off the list, its ours now, safe to drop the lock */
-        lock_ReleaseMutex(&smb_Dir_Watch_Lock);
-
         /* Turn off WATCHED flag in dscp */
         lock_ObtainWrite(&dscp->rw);
         if (wtree)
@@ -8667,7 +9236,6 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
         smb_FreePacket(watch);
 
         smb_ReleaseFID(fidp);
-        lock_ObtainMutex(&smb_Dir_Watch_Lock);
         watch = nextWatch;
     }
     lock_ReleaseMutex(&smb_Dir_Watch_Lock);
@@ -8713,12 +9281,14 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
                 scp = fidp->scp;
                osi_Log2(smb_logp,"smb_ReceiveNTCancel fidp 0x%p scp 0x%p", fidp, scp);
-                lock_ObtainWrite(&scp->rw);
-                if (watchtree)
-                    scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
-                else
-                    scp->flags &= ~CM_SCACHEFLAG_WATCHED;
-                lock_ReleaseWrite(&scp->rw);
+                if (scp) {
+                    lock_ObtainWrite(&scp->rw);
+                   if (watchtree)
+                        scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
+                    else
+                       scp->flags &= ~CM_SCACHEFLAG_WATCHED;
+                    lock_ReleaseWrite(&scp->rw);
+                }
                 smb_ReleaseFID(fidp);
             } else {
                 osi_Log2(smb_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
@@ -8773,7 +9343,11 @@ long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     tp = smb_GetSMBData(inp, NULL);
     oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, 0);
+    if (!oldPathp)
+        return CM_ERROR_BADSMB;
     newPathp = smb_ParseASCIIBlock(inp, tp, &tp, 0);
+    if (!newPathp)
+        return CM_ERROR_BADSMB;
 
     osi_Log3(smb_logp, "NTRename for [%S]->[%S] type [%s]",
              osi_LogSaveClientString(smb_logp, oldPathp),