smb-8dot3-pattern-matching-20040401
[openafs.git] / src / WINNT / afsd / smb3.c
index 4e72c9d..6dce167 100644 (file)
@@ -1,16 +1,18 @@
-/* 
- * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
- *
- * (C) COPYRIGHT IBM CORPORATION 1987, 1988
- * LICENSED MATERIALS - PROPERTY OF IBM
- *
- *
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
  */
 
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#endif /* !DJGPP */
 #include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
@@ -23,8 +25,6 @@
 
 #include "smb.h"
 
-extern smb_vc_t *dead_vcp;
-
 extern osi_hyper_t hzero;
 
 smb_packet_t *smb_Directory_Watches = NULL;
@@ -40,14 +40,16 @@ smb_tran2Packet_t *smb_tran2AssemblyQueuep;
 cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp)
 {
        smb_user_t *uidp;
-        cm_user_t *up;
+        cm_user_t *up = NULL;
         
         uidp = smb_FindUID(vcp, inp->uid, 0);
         if (!uidp) return NULL;
         
        lock_ObtainMutex(&uidp->mx);
-        up = uidp->userp;
-        cm_HoldUser(up);
+        if (uidp->unp) {
+          up = uidp->unp->userp;
+          cm_HoldUser(up);
+        }
        lock_ReleaseMutex(&uidp->mx);
 
         smb_ReleaseUID(uidp);
@@ -66,7 +68,7 @@ unsigned long smb_ExtAttributes(cm_scache_t *scp)
 
        if (scp->fileType == CM_SCACHETYPE_DIRECTORY
            || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
-               attrs = 0x10;
+               attrs = SMB_ATTR_DIRECTORY;
        else
                attrs = 0;
        /*
@@ -77,10 +79,10 @@ unsigned long smb_ExtAttributes(cm_scache_t *scp)
        if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
 #endif
        if ((scp->unixModeBits & 0222) == 0)
-               attrs |= 1;             /* Read-only */
+               attrs |= SMB_ATTR_READONLY;             /* Read-only */
 
        if (attrs == 0)
-               attrs = 0x80;           /* FILE_ATTRIBUTE_NORMAL */
+               attrs = SMB_ATTR_NORMAL;                /* FILE_ATTRIBUTE_NORMAL */
 
        return attrs;
 }
@@ -105,119 +107,90 @@ unsigned char *smb_ParseString(unsigned char *inp, char **chainpp)
 
 long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       char *tp;
-       char *usern, *pwd, *pwdx;
-       smb_user_t *uidp, *dead_uidp;
-       unsigned short newUid;
-       unsigned long caps;
-       cm_user_t *userp;
-       char *s1 = " ";
-
-       /* Check for bad conns */
-       if (vcp->flags & SMB_VCFLAG_REMOTECONN)
-               return CM_ERROR_REMOTECONN;
-
-       /* For NT LM 0.12 and up, get capabilities */
-       if (vcp->flags & SMB_VCFLAG_USENT) {
-               caps = smb_GetSMBParm(inp, 11);
-               if (caps & 0x40)
-                       vcp->flags |= SMB_VCFLAG_STATUS32;
-               /* for now, ignore other capability bits */
-       }
-
-       /* Parse the data */
-       tp = smb_GetSMBData(inp, NULL);
-       if (vcp->flags & SMB_VCFLAG_USENT)
-               pwdx = smb_ParseString(tp, &tp);
-       pwd = smb_ParseString(tp, &tp);
-       usern = smb_ParseString(tp, &tp);
-
-       /* Create a new UID and cm_user_t structure */
-       userp = cm_NewUser();
-       lock_ObtainMutex(&vcp->mx);
-       newUid = vcp->uidCounter++;
-       lock_ReleaseMutex(&vcp->mx);
-
-       /* Create a new smb_user_t structure and connect them up */
-       uidp = smb_FindUID(vcp, newUid, SMB_FLAG_CREATE);
-       lock_ObtainMutex(&uidp->mx);
-       uidp->userp = userp;
-       uidp->name = strdup(usern);
-       lock_ReleaseMutex(&uidp->mx);
-       smb_ReleaseUID(uidp);
-        
-       if (dead_vcp) {
-               dead_uidp = dead_vcp->usersp;
-               while (dead_uidp) {
-                       if (dead_uidp->userp
-                           && strcmp(dead_uidp->name, usern) == 0)
-                               break;
-                       dead_uidp = dead_uidp->nextp;
-               }
-       }
-
-       /* transfer tokens from dead vcp */
-       if (dead_vcp && dead_uidp) {
-               cm_user_t *dead_userp;
-               s1 = ", tokens from terminated session";
-               dead_userp = dead_uidp->userp;
-               cm_ResetACLCache(dead_userp);
-               userp->cellInfop = dead_userp->cellInfop;
-               dead_userp->cellInfop = NULL;
-               dead_vcp = NULL;
-       }
-
-       /* transfer tokens from integrated logon */
-       if (vcp->logonDLLUser) {
-               s1 = ", tokens from integrated logon";
-               cm_ResetACLCache(vcp->logonDLLUser);
-               userp->cellInfop = vcp->logonDLLUser->cellInfop;
-               vcp->logonDLLUser->cellInfop = NULL;
-               vcp->logonDLLUser = NULL;
-       }
-
-       /* transfer tokens for logoff profile upload */
-       if (vcp->justLoggedOut) {
-               cm_user_t *logout_userp;
-               if (GetTickCount() - vcp->logoffTime <
-                       1000 * smb_LogoffTransferTimeout
-                   && strcmp(vcp->justLoggedOut->name, usern) == 0) {
-                       s1 = ", tokens from logoff";
-                       logout_userp = vcp->justLoggedOut->userp;
-                       cm_ResetACLCache(logout_userp);
-                       userp->cellInfop = logout_userp->cellInfop;
-                       logout_userp->cellInfop = NULL;
-               }
-               vcp->justLoggedOut = NULL;
-       }
-       else if (loggedOut) {
-               cm_user_t *logout_userp;
-               if (GetTickCount() - loggedOutTime <
-                       1000 * smb_LogoffTransferTimeout
-                   && strcmp(loggedOutName, usern) == 0) {
-                       s1 = ", tokens from logoff";
-                       logout_userp = loggedOutUserp->userp;
-                       cm_ResetACLCache(logout_userp);
-                       userp->cellInfop = logout_userp->cellInfop;
-                       logout_userp->cellInfop = NULL;
-               }
-               smb_ReleaseUID(loggedOutUserp);
-               loggedOutUserp = NULL;
-               free(loggedOutName);
-               loggedOutName = NULL;
-               loggedOut = 0;
-       }
-
-       /* Return UID to the client */
-       ((smb_t *)outp)->uid = newUid;
-       /* Also to the next chained message */
-       ((smb_t *)inp)->uid = newUid;
-
-       osi_Log3(afsd_logp, "SMB3 session setup name %s creating ID %d%s",
-                       osi_LogSaveString(afsd_logp, usern), newUid, osi_LogSaveString(afsd_logp, s1));
-       smb_SetSMBParm(outp, 2, 0);
-        smb_SetSMBDataLength(outp, 0);
-        return 0;
+    char *tp;
+    char *usern, *pwd, *pwdx;
+    smb_user_t *uidp;
+    unsigned short newUid;
+    unsigned long caps;
+    cm_user_t *userp;
+    smb_username_t *unp;
+    char *s1 = " ";
+
+    /* Check for bad conns */
+    if (vcp->flags & SMB_VCFLAG_REMOTECONN)
+        return CM_ERROR_REMOTECONN;
+
+    /* For NT LM 0.12 and up, get capabilities */
+    if (vcp->flags & SMB_VCFLAG_USENT) {
+        caps = smb_GetSMBParm(inp, 11);
+        if (caps & 0x40)
+            vcp->flags |= SMB_VCFLAG_STATUS32;
+        /* for now, ignore other capability bits */
+    }
+
+    /* Parse the data */
+    tp = smb_GetSMBData(inp, NULL);
+    if (vcp->flags & SMB_VCFLAG_USENT)
+        pwdx = smb_ParseString(tp, &tp);
+    pwd = smb_ParseString(tp, &tp);
+    usern = smb_ParseString(tp, &tp);
+
+    /* On Windows 2000, this function appears to be called more often than
+       it is expected to be called. This resulted in multiple smb_user_t
+       records existing all for the same user session which results in all
+       of the users tokens disappearing.
+
+       To avoid this problem, we look for an existing smb_user_t record
+       based on the users name, and use that one if we find it.
+    */
+
+    uidp = smb_FindUserByNameThisSession(vcp, usern);
+    if (uidp) {   /* already there, so don't create a new one */
+        unp = uidp->unp;
+        userp = unp->userp;
+        newUid = (unsigned short)uidp->userID;  /* For some reason these are different types!*/
+               osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"FindUserByName:Lana[%d],lsn[%d],userid[%d],name[%s]",vcp->lana,vcp->lsn,newUid,usern);
+               osi_Log3(afsd_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid);
+        smb_ReleaseUID(uidp);
+    }
+    else {
+      /* do a global search for the username/machine name pair */
+        unp = smb_FindUserByName(usern, vcp->rname, SMB_FLAG_CREATE);
+
+        /* Create a new UID and cm_user_t structure */
+        userp = unp->userp;
+        if (!userp)
+          userp = cm_NewUser();
+        lock_ObtainMutex(&vcp->mx);
+        if (!vcp->uidCounter)
+            vcp->uidCounter++; /* handle unlikely wraparounds */
+        newUid = (strlen(usern)==0)?0:vcp->uidCounter++;
+        lock_ReleaseMutex(&vcp->mx);
+
+        /* Create a new smb_user_t structure and connect them up */
+        lock_ObtainMutex(&unp->mx);
+        unp->userp = userp;
+        lock_ReleaseMutex(&unp->mx);
+
+        uidp = smb_FindUID(vcp, newUid, SMB_FLAG_CREATE);
+        lock_ObtainMutex(&uidp->mx);
+        uidp->unp = unp;
+               osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d],TicketKTCName[%s]",(int)vcp,vcp->lana,vcp->lsn,newUid,usern);
+               osi_Log4(afsd_logp,"smb_ReceiveV3SessionSetupX MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d]",vcp,vcp->lana,vcp->lsn,newUid);
+        lock_ReleaseMutex(&uidp->mx);
+        smb_ReleaseUID(uidp);
+    }
+
+    /* Return UID to the client */
+    ((smb_t *)outp)->uid = newUid;
+    /* Also to the next chained message */
+    ((smb_t *)inp)->uid = newUid;
+
+    osi_Log3(afsd_logp, "SMB3 session setup name %s creating ID %d%s",
+             osi_LogSaveString(afsd_logp, usern), newUid, osi_LogSaveString(afsd_logp, s1));
+    smb_SetSMBParm(outp, 2, 0);
+    smb_SetSMBDataLength(outp, 0);
+    return 0;
 }
 
 long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
@@ -230,31 +203,18 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
 
        /* find the tree and free it */
-        uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-        if (uidp) {
+    uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+    /* TODO: smb_ReleaseUID() ? */
+    if (uidp) {
                char *s1 = NULL, *s2 = NULL;
 
-               /* Also, this is not logon session any more */
-               if (uidp->userp == vcp->logonDLLUser) {
-                       s1 = ", was logon session";
-                       vcp->logonDLLUser = NULL;
-               }
-
-               /* But its tokens might be needed later */
-               if (uidp->userp && !(uidp->userp->flags & CM_USERFLAG_WASLOGON)
-                   && smb_LogoffTokenTransfer) {
-                       s2 = ", pre-logout effect";
-                       vcp->justLoggedOut = uidp;
-                       vcp->logoffTime = GetTickCount();
-               }
-
                if (s2 == NULL) s2 = " ";
                if (s1 == NULL) {s1 = s2; s2 = " ";}
 
                osi_Log4(afsd_logp, "SMB3 user logoffX uid %d name %s%s%s",
                         uidp->userID,
-                        osi_LogSaveString(afsd_logp, uidp->name),
-                        s1, s2);
+                        osi_LogSaveString(afsd_logp,
+                 (uidp->unp) ? uidp->unp->name: " "), s1, s2);
 
                lock_ObtainMutex(&uidp->mx);
                uidp->flags |= SMB_USERFLAG_DELETE;
@@ -352,29 +312,29 @@ smb_tran2Packet_t *smb_NewTran2Packet(smb_vc_t *vcp, smb_packet_t *inp,
        int totalParms, int totalData)
 {
        smb_tran2Packet_t *tp;
-        smb_t *smbp;
+    smb_t *smbp;
         
-        smbp = (smb_t *) inp->data;
+    smbp = (smb_t *) inp->data;
        tp = malloc(sizeof(*tp));
-        memset(tp, 0, sizeof(*tp));
-        tp->vcp = vcp;
-        smb_HoldVC(vcp);
-        tp->curData = tp->curParms = 0;
-        tp->totalData = totalData;
-        tp->totalParms = totalParms;
-        tp->tid = smbp->tid;
-        tp->mid = smbp->mid;
-        tp->uid = smbp->uid;
-        tp->pid = smbp->pid;
+    memset(tp, 0, sizeof(*tp));
+    tp->vcp = vcp;
+    smb_HoldVC(vcp);
+    tp->curData = tp->curParms = 0;
+    tp->totalData = totalData;
+    tp->totalParms = totalParms;
+    tp->tid = smbp->tid;
+    tp->mid = smbp->mid;
+    tp->uid = smbp->uid;
+    tp->pid = smbp->pid;
        tp->res[0] = smbp->res[0];
        osi_QAdd((osi_queue_t **)&smb_tran2AssemblyQueuep, &tp->q);
-        tp->opcode = smb_GetSMBParm(inp, 14);
+    tp->opcode = smb_GetSMBParm(inp, 14);
        if (totalParms != 0)
-               tp->parmsp = malloc(totalParms);
+        tp->parmsp = malloc(totalParms);
        if (totalData != 0)
-               tp->datap = malloc(totalData);
+        tp->datap = malloc(totalData);
        tp->flags |= SMB_TRAN2PFLAG_ALLOC;
-        return tp;
+    return tp;
 }
 
 smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
@@ -421,14 +381,14 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
 /* free a tran2 packet; must be called with smb_globalLock held */
 void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
 {
-        if (t2p->vcp) smb_ReleaseVC(t2p->vcp);
+    if (t2p->vcp) smb_ReleaseVC(t2p->vcp);
        if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
                if (t2p->parmsp)
                        free(t2p->parmsp);
                if (t2p->datap)
                        free(t2p->datap);
        }
-        free(t2p);
+    free(t2p);
 }
 
 /* called with a VC, an input packet to respond to, and an error code.
@@ -549,6 +509,7 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        /* We sometimes see 0 word count.  What to do? */
        if (*inp->wctp == 0) {
+#ifndef DJGPP
                HANDLE h;
                char *ptbuf[1];
 
@@ -559,6 +520,9 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
                            1, inp->ncb_length, ptbuf, inp);
                DeregisterEventSource(h);
+#else /* DJGPP */
+               osi_Log0(afsd_logp, "TRANSACTION2 word count = 0"); 
+#endif /* !DJGPP */
 
                 smb_SetSMBDataLength(outp, 0);
                 smb_SendPacket(vcp, outp);
@@ -603,10 +567,15 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        parmCount, dataCount);
        }
 
-        /* now copy the parms and data */
+    /* now copy the parms and data */
+    if ( parmCount != 0 )
+    {
         memcpy(((char *)asp->parmsp) + parmDisp, inp->data + parmOffset, parmCount);
+    }
+    if ( dataCount != 0 ) {
         memcpy(asp->datap + dataDisp, inp->data + dataOffset, dataCount);
-        
+    }
+
         /* account for new bytes */
         asp->curData += dataCount;
         asp->curParms += parmCount;
@@ -618,8 +587,17 @@ 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);
                 
-                /* now dispatch it */
+            /* now dispatch it */
+            if ( asp->opcode >= 0 && asp->opcode < 20 && smb_tran2DispatchTable[asp->opcode].procp) {
+                osi_LogEvent("AFS-Dispatch-2[%s]",myCrt_2Dispatch(asp->opcode),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
+                osi_Log4(afsd_logp,"AFS Server - Dispatch-2 %s vcp[%x] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
                 code = (*smb_tran2DispatchTable[asp->opcode].procp)(vcp, asp, outp);
+            }
+            else {
+                osi_LogEvent("AFS-Dispatch-2 [invalid]", NULL, "op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+                osi_Log4(afsd_logp,"AFS Server - Dispatch-2 [INVALID] op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+                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.
@@ -649,218 +627,235 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
        char *pathp;
-        smb_tran2Packet_t *outp;
-        long code;
+    smb_tran2Packet_t *outp;
+    long code;
        cm_space_t *spacep;
-        int excl;
-        cm_user_t *userp;
-        cm_scache_t *dscp;             /* dir we're dealing with */
-        cm_scache_t *scp;              /* file we're creating */
-        cm_attr_t setAttr;
-        int initialModeBits;
-        smb_fid_t *fidp;
-        int attributes;
-        char *lastNamep;
-        long dosTime;
-        int openFun;
-        int trunc;
-        int openMode;
-        int extraInfo;
-        int openAction;
-        int parmSlot;                  /* which parm we're dealing with */
-        long returnEALength;
+    int excl;
+    cm_user_t *userp;
+    cm_scache_t *dscp;         /* dir we're dealing with */
+    cm_scache_t *scp;          /* file we're creating */
+    cm_attr_t setAttr;
+    int initialModeBits;
+    smb_fid_t *fidp;
+    int attributes;
+    char *lastNamep;
+    long dosTime;
+    int openFun;
+    int trunc;
+    int openMode;
+    int extraInfo;
+    int openAction;
+    int parmSlot;                      /* which parm we're dealing with */
+    long returnEALength;
        char *tidPathp;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        scp = NULL;
+    scp = NULL;
         
        extraInfo = (p->parmsp[0] & 1); /* return extra info */
-        returnEALength = (p->parmsp[0] & 8);   /* return extended attr length */
+    returnEALength = (p->parmsp[0] & 8);       /* return extended attr length */
 
        openFun = p->parmsp[6];         /* open function */
-        excl = ((openFun & 3) == 0);
-        trunc = ((openFun & 3) == 2);  /* truncate it */
+    excl = ((openFun & 3) == 0);
+    trunc = ((openFun & 3) == 2);      /* truncate it */
        openMode = (p->parmsp[1] & 0x7);
-        openAction = 0;                        /* tracks what we did */
+    openAction = 0;                    /* tracks what we did */
 
-        attributes = p->parmsp[3];
-        dosTime = p->parmsp[4] | (p->parmsp[5] << 16);
+    attributes = p->parmsp[3];
+    dosTime = p->parmsp[4] | (p->parmsp[5] << 16);
         
        /* compute initial mode bits based on read-only flag in attributes */
-        initialModeBits = 0666;
-        if (attributes & 1) initialModeBits &= ~0222;
+    initialModeBits = 0666;
+    if (attributes & 1) initialModeBits &= ~0222;
         
-        pathp = (char *) (&p->parmsp[14]);
+    pathp = (char *) (&p->parmsp[14]);
         
-        outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
+    outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0);
 
        spacep = cm_GetSpace();
-        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
        if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
                /* special case magic file name for receiving IOCTL requests
-                 * (since IOCTL calls themselves aren't getting through).
-                 */
-               fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-                smb_SetupIoctlFid(fidp, spacep);
+         * (since IOCTL calls themselves aren't getting through).
+         */
+        fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
+        smb_SetupIoctlFid(fidp, spacep);
 
-               /* copy out remainder of the parms */
+        /* copy out remainder of the parms */
                parmSlot = 0;
                outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
                if (extraInfo) {
-                       outp->parmsp[parmSlot] = /* attrs */ 0; parmSlot++;
-                       outp->parmsp[parmSlot] = 0; parmSlot++; /* mod time */
-                       outp->parmsp[parmSlot] = 0; parmSlot++;
-                       outp->parmsp[parmSlot] = 0; parmSlot++; /* len */
-                       outp->parmsp[parmSlot] = 0x7fff; parmSlot++;
-                       outp->parmsp[parmSlot] = openMode; parmSlot++;
-                       outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
-                       outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
-               }
+            outp->parmsp[parmSlot] = /* attrs */ 0; parmSlot++;
+            outp->parmsp[parmSlot] = 0; parmSlot++;    /* mod time */
+            outp->parmsp[parmSlot] = 0; parmSlot++;
+            outp->parmsp[parmSlot] = 0; parmSlot++;    /* len */
+            outp->parmsp[parmSlot] = 0x7fff; parmSlot++;
+            outp->parmsp[parmSlot] = openMode; parmSlot++;
+            outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
+            outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
+               }   
                /* and the final "always present" stuff */
-               outp->parmsp[parmSlot] = /* openAction found existing file */ 1; parmSlot++;
+        outp->parmsp[parmSlot] = /* openAction found existing file */ 1; parmSlot++;
                /* next write out the "unique" ID */
                outp->parmsp[parmSlot] = 0x1234; parmSlot++;
                outp->parmsp[parmSlot] = 0x5678; parmSlot++;
-               outp->parmsp[parmSlot] = 0; parmSlot++;
+        outp->parmsp[parmSlot] = 0; parmSlot++;
                if (returnEALength) {
                        outp->parmsp[parmSlot] = 0; parmSlot++;
                        outp->parmsp[parmSlot] = 0; parmSlot++;
-                }
+        }
                 
-                outp->totalData = 0;
-                outp->totalParms = parmSlot * 2;
+        outp->totalData = 0;
+        outp->totalParms = parmSlot * 2;
                 
-                smb_SendTran2Packet(vcp, outp, op);
+        smb_SendTran2Packet(vcp, outp, op);
                 
-                smb_FreeTran2Packet(outp);
+        smb_FreeTran2Packet(outp);
 
                /* and clean up fid reference */
-                smb_ReleaseFID(fidp);
-                return 0;
-        }
+        smb_ReleaseFID(fidp);
+        return 0;
+    }
+
+#ifdef DEBUG_VERBOSE
+       {
+               char *hexp, *asciip;
+               asciip = (lastNamep ? lastNamep : pathp);
+               hexp = osi_HexifyString( asciip );
+               DEBUG_EVENT2("AFS","T2Open H[%s] A[%s]", hexp, asciip);
+               free(hexp);
+       }
+#endif
 
        userp = smb_GetTran2User(vcp, p);
+    /* In the off chance that userp is NULL, we log and abandon */
+    if(!userp) {
+        osi_Log1(afsd_logp, "ReceiveTran2Open user [%d] not resolvable", p->uid);
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADSMB;
+    }
+
        tidPathp = smb_GetTIDPath(vcp, p->tid);
 
        dscp = NULL;
        code = cm_NameI(cm_rootSCachep, pathp,
-                       CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                       userp, tidPathp, &req, &scp);
+                    CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                    userp, tidPathp, &req, &scp);
        if (code != 0) {
                code = cm_NameI(cm_rootSCachep, spacep->data,
-                               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                       userp, tidPathp, &req, &dscp);
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &dscp);
                cm_FreeSpace(spacep);
 
-               if (code) {
-                       cm_ReleaseUser(userp);
+        if (code) {
+            cm_ReleaseUser(userp);
                        smb_FreeTran2Packet(outp);
-                       return code;
-               }
+            return code;
+        }
         
-               /* otherwise, scp points to the parent directory.  Do a lookup,
+        /* otherwise, scp points to the parent directory.  Do a lookup,
                 * and truncate the file if we find it, otherwise we create the
                 * file.
-                */
-               if (!lastNamep) lastNamep = pathp;
-               else lastNamep++;
-               code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
-                                &req, &scp);
-               if (code && code != CM_ERROR_NOSUCHFILE) {
+         */
+        if (!lastNamep) lastNamep = pathp;
+        else lastNamep++;
+        code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
+                         &req, &scp);
+        if (code && code != CM_ERROR_NOSUCHFILE) {
                        cm_ReleaseSCache(dscp);
-                       cm_ReleaseUser(userp);
+            cm_ReleaseUser(userp);
                        smb_FreeTran2Packet(outp);
-                       return code;
-               }
+            return code;
+        }
        }
-        else {
-               cm_FreeSpace(spacep);
+    else {
+        cm_FreeSpace(spacep);
        }
         
-        /* if we get here, if code is 0, the file exists and is represented by
-         * scp.  Otherwise, we have to create it.
-         */
+    /* if we get here, if code is 0, the file exists and is represented by
+     * scp.  Otherwise, we have to create it.
+     */
        if (code == 0) {
-               code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
-                if (code) {
-                        if (dscp) cm_ReleaseSCache(dscp);
-                        cm_ReleaseSCache(scp);
-                        cm_ReleaseUser(userp);
+        code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
+        if (code) {
+            if (dscp) cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
                        smb_FreeTran2Packet(outp);
-                        return code;
-                }
+            return code;
+        }
 
                if (excl) {
                        /* oops, file shouldn't be there */
-                        if (dscp) cm_ReleaseSCache(dscp);
-                        cm_ReleaseSCache(scp);
-                        cm_ReleaseUser(userp);
+            if (dscp) cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
                        smb_FreeTran2Packet(outp);
-                        return CM_ERROR_EXISTS;
-                }
+            return CM_ERROR_EXISTS;
+        }
 
                if (trunc) {
                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                       setAttr.length.LowPart = 0;
-                       setAttr.length.HighPart = 0;
+            setAttr.length.LowPart = 0;
+            setAttr.length.HighPart = 0;
                        code = cm_SetAttr(scp, &setAttr, userp, &req);
-                        openAction = 3;        /* truncated existing file */
-               }
-                else openAction = 1;   /* found existing file */
-        }
-       else if (!(openFun & 0x10)) {
+            openAction = 3;    /* truncated existing file */
+               }   
+        else openAction = 1;   /* found existing file */
+    }
+       else if (!(openFun & SMB_ATTR_DIRECTORY)) {
                /* don't create if not found */
-                if (dscp) cm_ReleaseSCache(dscp);
-                osi_assert(scp == NULL);
-                cm_ReleaseUser(userp);
+        if (dscp) cm_ReleaseSCache(dscp);
+        osi_assert(scp == NULL);
+        cm_ReleaseUser(userp);
                smb_FreeTran2Packet(outp);
-                return CM_ERROR_NOSUCHFILE;
-        }
-        else {
+        return CM_ERROR_NOSUCHFILE;
+    }
+    else {
                osi_assert(dscp != NULL && scp == NULL);
                openAction = 2; /* created file */
                setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
                smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
-                code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
-                                &req);
+        code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
+                         &req);
                if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                        smb_NotifyChange(FILE_ACTION_ADDED,
-                                        FILE_NOTIFY_CHANGE_FILE_NAME,
-                                        dscp, lastNamep, NULL, TRUE);
-                if (!excl && code == CM_ERROR_EXISTS) {
+                             FILE_NOTIFY_CHANGE_FILE_NAME,  
+                             dscp, lastNamep, NULL, TRUE);
+        if (!excl && code == CM_ERROR_EXISTS) {
                        /* not an exclusive create, and someone else tried
                         * creating it already, then we open it anyway.  We
                         * don't bother retrying after this, since if this next
                         * fails, that means that the file was deleted after we
                         * started this call.
-                         */
-                        code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
-                                        userp, &req, &scp);
-                        if (code == 0) {
-                               if (trunc) {
+             */
+            code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
+                             userp, &req, &scp);
+            if (code == 0) {
+                if (trunc) {
                                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                                       setAttr.length.LowPart = 0;
-                                       setAttr.length.HighPart = 0;
-                                       code = cm_SetAttr(scp, &setAttr, userp,
-                                                         &req);
-                               }
+                    setAttr.length.LowPart = 0;
+                    setAttr.length.HighPart = 0;
+                    code = cm_SetAttr(scp, &setAttr, userp,
+                                      &req);
+                }   
                        }       /* lookup succeeded */
-                }
         }
+    }
         
        /* we don't need this any longer */
        if (dscp) cm_ReleaseSCache(dscp);
 
-        if (code) {
+    if (code) {
                /* something went wrong creating or truncating the file */
-                if (scp) cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
+        if (scp) cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
                smb_FreeTran2Packet(outp);
-                return code;
-        }
+        return code;
+    }
         
        /* make sure we're about to open a file */
        if (scp->fileType != CM_SCACHETYPE_FILE) {
@@ -870,61 +865,61 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
                return CM_ERROR_ISDIR;
        }
 
-        /* now all we have to do is open the file itself */
-        fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-        osi_assert(fidp);
+    /* now all we have to do is open the file itself */
+    fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
+    osi_assert(fidp);
        
        /* save a pointer to the vnode */
-        fidp->scp = scp;
+    fidp->scp = scp;
         
        /* compute open mode */
-        if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
-        if (openMode == 1 || openMode == 2)
-               fidp->flags |= SMB_FID_OPENWRITE;
+    if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
+    if (openMode == 1 || openMode == 2)
+        fidp->flags |= SMB_FID_OPENWRITE;
 
        smb_ReleaseFID(fidp);
         
        cm_Open(scp, 0, userp);
 
-        /* copy out remainder of the parms */
+    /* copy out remainder of the parms */
        parmSlot = 0;
        outp->parmsp[parmSlot] = fidp->fid; parmSlot++;
        lock_ObtainMutex(&scp->mx);
        if (extraInfo) {
-               outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
+        outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
                smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
-                outp->parmsp[parmSlot] =  dosTime & 0xffff; parmSlot++;
-                outp->parmsp[parmSlot] = (dosTime>>16) & 0xffff; parmSlot++;
-                outp->parmsp[parmSlot] = (unsigned short) (scp->length.LowPart & 0xffff);
-                       parmSlot++;
-                outp->parmsp[parmSlot] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
-                       parmSlot++;
-                outp->parmsp[parmSlot] = openMode; parmSlot++;
-                outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
-                outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
-       }
+        outp->parmsp[parmSlot] = (unsigned short)(dosTime & 0xffff); parmSlot++;
+        outp->parmsp[parmSlot] = (unsigned short)((dosTime>>16) & 0xffff); parmSlot++;
+        outp->parmsp[parmSlot] = (unsigned short) (scp->length.LowPart & 0xffff);
+        parmSlot++;
+        outp->parmsp[parmSlot] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
+        parmSlot++;
+        outp->parmsp[parmSlot] = openMode; parmSlot++;
+        outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */
+        outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */
+       }   
        /* and the final "always present" stuff */
-        outp->parmsp[parmSlot] = openAction; parmSlot++;
+    outp->parmsp[parmSlot] = openAction; parmSlot++;
        /* next write out the "unique" ID */
        outp->parmsp[parmSlot] = (unsigned short) (scp->fid.vnode & 0xffff); parmSlot++;
        outp->parmsp[parmSlot] = (unsigned short) (scp->fid.volume & 0xffff); parmSlot++;
-        outp->parmsp[parmSlot] = 0; parmSlot++;
-        if (returnEALength) {
+    outp->parmsp[parmSlot] = 0; parmSlot++;
+    if (returnEALength) {
                outp->parmsp[parmSlot] = 0; parmSlot++;
                outp->parmsp[parmSlot] = 0; parmSlot++;
-        }
+    }
        lock_ReleaseMutex(&scp->mx);
        outp->totalData = 0;            /* total # of data bytes */
-        outp->totalParms = parmSlot * 2;       /* shorts are two bytes */
+    outp->totalParms = parmSlot * 2;   /* shorts are two bytes */
 
        smb_SendTran2Packet(vcp, outp, op);
         
-        smb_FreeTran2Packet(outp);
+    smb_FreeTran2Packet(outp);
 
-        cm_ReleaseUser(userp);
-        /* leave scp held since we put it in fidp->scp */
-        return 0;
-}
+    cm_ReleaseUser(userp);
+    /* leave scp held since we put it in fidp->scp */
+    return 0;
+}   
 
 long smb_ReceiveTran2FindFirst(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
 {
@@ -969,19 +964,19 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
 
         case 2:
                /* volume info */
-                qi.u.volumeInfo.vsn = 1234;
-                qi.u.volumeInfo.vnCount = 4;
+        qi.u.volumeInfo.vsn = 1234;
+        qi.u.volumeInfo.vnCount = 4;
                /* we're supposed to pad it out with zeroes to the end */
                memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
-                strcpy(qi.u.volumeInfo.label, "AFS");
+        memcpy(qi.u.volumeInfo.label, "AFS", 4);
                break;
 
        case 0x102:
                /* FS volume info */
                memset((char *)&qi.u.FSvolumeInfo.vct, 0, sizeof(FILETIME));
                qi.u.FSvolumeInfo.vsn = 1234;
-               qi.u.FSvolumeInfo.vnCount = 4;
-               strcpy(qi.u.FSvolumeInfo.label, "AFS");
+               qi.u.FSvolumeInfo.vnCount = 8;
+               memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0", 8);
                break;
 
        case 0x103:
@@ -1042,7 +1037,7 @@ struct smb_ShortNameRock {
        size_t shortNameLen;
 };
 
-long cm_GetShortNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *vrockp,
+int cm_GetShortNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *vrockp,
        osi_hyper_t *offp)
 {
        struct smb_ShortNameRock *rockp;
@@ -1160,6 +1155,11 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         }
         
         userp = smb_GetTran2User(vcp, p);
+        if(!userp) {
+               osi_Log1(afsd_logp, "ReceiveTran2QPathInfo unable to resolve user [%d]", p->uid);
+               smb_FreeTran2Packet(outp);
+               return CM_ERROR_BADSMB;
+        }
 
        tidPathp = smb_GetTIDPath(vcp, p->tid);
 
@@ -1181,33 +1181,36 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                spacep = cm_GetSpace();
                smb_StripLastComponent(spacep->data, &lastComp,
                                        (char *)(&p->parmsp[3]));
-               if (strcmp(lastComp, "\\desktop.ini") == 0) {
-                       code = cm_NameI(cm_rootSCachep, spacep->data,
-                                       CM_FLAG_CASEFOLD
-                                         | CM_FLAG_DIRSEARCH
-                                         | CM_FLAG_FOLLOW,
-                                       userp, tidPathp, &req, &dscp);
-                       if (code == 0) {
-                               if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
-                                   && !dscp->mountRootFidp)
-                                       code = CM_ERROR_NOSUCHFILE;
-                               else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
-                                       cm_buf_t *bp = buf_Find(dscp, &hzero);
-                                       if (bp)
-                                               buf_Release(bp);
-                                       else
-                                               code = CM_ERROR_NOSUCHFILE;
-                               }
-                               cm_ReleaseSCache(dscp);
-                               if (code) {
-                                       cm_FreeSpace(spacep);
-                                       cm_ReleaseUser(userp);
-                                       smb_SendTran2Error(vcp, p, opx, code);
-                                       smb_FreeTran2Packet(outp);
-                                       return 0;
-                               }
-                       }
-               }
+               /* Make sure that lastComp is not NULL */
+               if (lastComp) {
+                   if (strcmp(lastComp, "\\desktop.ini") == 0) {
+                code = cm_NameI(cm_rootSCachep, spacep->data,
+                                CM_FLAG_CASEFOLD
+                                | CM_FLAG_DIRSEARCH
+                                | CM_FLAG_FOLLOW,
+                                userp, tidPathp, &req, &dscp);
+                if (code == 0) {
+                    if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
+                         && !dscp->mountRootFidp)
+                        code = CM_ERROR_NOSUCHFILE;
+                    else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
+                        cm_buf_t *bp = buf_Find(dscp, &hzero);
+                        if (bp)
+                            buf_Release(bp);
+                        else
+                            code = CM_ERROR_NOSUCHFILE;
+                    }
+                    cm_ReleaseSCache(dscp);
+                    if (code) {
+                        cm_FreeSpace(spacep);
+                        cm_ReleaseUser(userp);
+                        smb_SendTran2Error(vcp, p, opx, code);
+                        smb_FreeTran2Packet(outp);
+                        return 0;
+                    }
+                }
+            }
+        }
                cm_FreeSpace(spacep);
        }
 
@@ -1221,7 +1224,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 smb_FreeTran2Packet(outp);
                 return 0;
         }
-        
+
         lock_ObtainMutex(&scp->mx);
         code = cm_SyncOp(scp, NULL, userp, &req, 0,
                CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -1235,7 +1238,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        if (infoLevel == 0x108) {
                code = cm_GetShortName((char *)(&p->parmsp[3]), userp, &req,
                                        tidPathp, scp->fid.vnode, shortName,
-                                       &len);
+                                       (size_t *) &len);
                if (code) {
                        goto done;
                }
@@ -1312,7 +1315,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        int nbytesRequired;
        unsigned short fid;
        cm_user_t *userp;
-        smb_fid_t *fidp;
+    smb_fid_t *fidp;
        cm_scache_t *scp;
        char *op;
        long code;
@@ -1320,8 +1323,8 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
        cm_InitReq(&req);
 
-        fid = p->parmsp[0];
-        fidp = smb_FindFID(vcp, fid, 0);
+    fid = p->parmsp[0];
+    fidp = smb_FindFID(vcp, fid, 0);
 
        if (fidp == NULL) {
                smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
@@ -1335,8 +1338,9 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        else if (infoLevel == 0x104) nbytesRequired = 6;
        else {
                osi_Log2(afsd_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
-                        p->opcode, infoLevel);
+                 p->opcode, infoLevel);
                smb_SendTran2Error(vcp, p, opx, CM_ERROR_INVAL);
+        smb_ReleaseFID(fidp);
                return 0;
        }
        osi_Log2(afsd_logp, "T2 QFileInfo type 0x%x fid %d", infoLevel, fid);
@@ -1350,11 +1354,16 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        outp->totalData = nbytesRequired;
 
        userp = smb_GetTran2User(vcp, p);
+    if(!userp) {
+       osi_Log1(afsd_logp, "ReceiveTran2QFileInfo unable to resolve user [%d]", p->uid);
+       code = CM_ERROR_BADSMB;
+       goto done;
+    }
 
        scp = fidp->scp;
        lock_ObtainMutex(&scp->mx);
        code = cm_SyncOp(scp, NULL, userp, &req, 0,
-                        CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
        if (code) goto done;
 
        /* now we have the status in the cache entry, and everything is locked.
@@ -1376,9 +1385,9 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                *((LARGE_INTEGER *)op) = scp->length; op += 8;  /* EOF */
                *((u_long *)op) = scp->linkCount; op += 4;
                *op++ = ((fidp->flags & SMB_FID_DELONCLOSE) ? 1 : 0);
-               *op++ = 0;
                *op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0);
                *op++ = 0;
+               *op++ = 0;
        }
        else if (infoLevel == 0x103) {
                *((u_long *)op) = 0; op += 4;
@@ -1422,7 +1431,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
 
        cm_InitReq(&req);
 
-        fid = p->parmsp[0];
+    fid = p->parmsp[0];
        fidp = smb_FindFID(vcp, fid, 0);
 
        if (fidp == NULL) {
@@ -1435,16 +1444,19 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                osi_Log2(afsd_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                         p->opcode, infoLevel);
                smb_SendTran2Error(vcp, p, op, CM_ERROR_INVAL);
+        smb_ReleaseFID(fidp);
                return 0;
        }
 
        if (infoLevel == 0x102 && !(fidp->flags & SMB_FID_OPENDELETE)) {
                smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
+        smb_ReleaseFID(fidp);
                return 0;
        }
        if ((infoLevel == 0x103 || infoLevel == 0x104)
            && !(fidp->flags & SMB_FID_OPENWRITE)) {
                smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
+        smb_ReleaseFID(fidp);
                return 0;
        }
 
@@ -1456,6 +1468,11 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
        outp->totalData = 0;
 
        userp = smb_GetTran2User(vcp, p);
+    if(!userp) {
+       osi_Log1(afsd_logp,"ReceiveTran2SetFileInfo unable to resolve user [%d]", p->uid);
+       code = CM_ERROR_BADSMB;
+       goto done;
+    }
 
        scp = fidp->scp;
 
@@ -1469,8 +1486,8 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
                 */
                lock_ObtainMutex(&scp->mx);
                code = cm_SyncOp(scp, NULL, userp, &req, 0,
-                                CM_SCACHESYNC_GETSTATUS
-                                | CM_SCACHESYNC_NEEDCALLBACK);
+                         CM_SCACHESYNC_GETSTATUS
+                         | CM_SCACHESYNC_NEEDCALLBACK);
                if (code) {
                        lock_ReleaseMutex(&scp->mx);
                        goto done;
@@ -1478,13 +1495,20 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
 
                /* prepare for setattr call */
                attr.mask = 0;
+               
                lastMod = *((FILETIME *)(p->datap + 16));
-               if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod))) {
+               /* when called as result of move a b, lastMod is (-1, -1). 
+         * If the check for -1 is not present, timestamp
+                * of the resulting file will be 1969 (-1)
+                */
+               if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) && 
+            lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
                        attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
                        smb_UnixTimeFromLargeSearchTime(&attr.clientModTime,
                                                        &lastMod);
                        fidp->flags |= SMB_FID_MTIMESETDONE;
                }
+               
                attribute = *((u_long *)(p->datap + 32));
                if (attribute != 0) {
                        if ((scp->unixModeBits & 0222)
@@ -1641,6 +1665,9 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
                        /* Copy attributes */
                        lattr = smb_ExtAttributes(scp);
+            /* merge in hidden (dot file) attribute */
+                       if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+                               lattr |= SMB_ATTR_HIDDEN;
                        *((u_long *)dptr) = lattr;
                        dptr += 4;
                }
@@ -1688,6 +1715,9 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
                        /* finally copy out attributes as short */
                        attr = smb_Attributes(scp);
+            /* merge in hidden (dot file) attribute */
+            if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+                attr |= SMB_ATTR_HIDDEN;
                        *dptr++ = attr & 0xff;
                        *dptr++ = (attr >> 8) & 0xff;
                }
@@ -1715,12 +1745,14 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
 {
        unsigned char tcp1, tcp2;       /* Pattern characters */
         unsigned char tcn1;            /* Name characters */
-       int sawDot = 0, sawStar = 0;
+       int sawDot = 0, sawStar = 0, req8dot3 = 0;
        char *starNamep, *starMaskp;
        static char nullCharp[] = {0};
 
        /* make sure we only match 8.3 names, if requested */
-       if ((flags & CM_FLAG_8DOT3) && !cm_Is8Dot3(namep)) return 0;
+    req8dot3 = (flags & CM_FLAG_8DOT3);
+       if (req8dot3 && !cm_Is8Dot3(namep)) 
+        return 0;
 
        /* loop */
        while (1) {
@@ -1777,8 +1809,8 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
                        tcp2 = *maskp++;
                        if (tcp2 == 0)
                                return 1;
-                       else if (tcp2 == '.' || tcp2 == '"') {
-                               while (tcn1 != '.' && tcn1 != 0)
+                       else if ((req8dot3 && tcp2 == '.') || tcp2 == '"') {
+                               while (req8dot3 && tcn1 != '.' && tcn1 != 0)
                                        tcn1 = *++namep;
                                if (tcn1 == 0) {
                                        if (sawDot)
@@ -1804,12 +1836,12 @@ int smb_V3MatchMask(char *namep, char *maskp, int flags)
                                        tcp2 = *maskp++;
 
                                /* skip over characters that don't match tcp2 */
-                               while (tcn1 != '.' && tcn1 != 0
+                               while (req8dot3 && tcn1 != '.' && tcn1 != 0
                                        && cm_foldUpper[tcn1] != cm_foldUpper[tcp2])
                                        tcn1 = *++namep;
 
                                /* No match */
-                               if (tcn1 == '.' || tcn1 == 0)
+                               if ((req8dot3 && tcn1 == '.') || tcn1 == 0)
                                        return 0;
 
                                /* Remember where we are */
@@ -1888,6 +1920,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        char shortName[13];             /* 8.3 name if needed */
        int NeedShortName;
        char *shortNameEnd;
+        int fileType;
+        cm_fid_t fid;
         
         cm_req_t req;
 
@@ -1955,14 +1989,22 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                        osi_LogSaveString(afsd_logp, pathp));
         
         /* bail out if request looks bad */
-        if (p->opcode == 1 && !pathp) {
-                return CM_ERROR_BADSMB;
-        }
+    if (p->opcode == 1 && !pathp) {
+        smb_ReleaseDirSearch(dsp);
+        smb_FreeTran2Packet(outp);
+        return CM_ERROR_BADSMB;
+    }
         
        osi_Log2(afsd_logp, "T2 dir search cookie 0x%x, connection %d",
                nextCookie, dsp->cookie);
 
-       userp = smb_GetTran2User(vcp, p);
+       userp = smb_GetTran2User(vcp, p);
+    if (!userp) {
+       osi_Log1(afsd_logp, "T2 dir search unable to resolve user [%d]", p->uid);
+       smb_ReleaseDirSearch(dsp);
+       smb_FreeTran2Packet(outp);
+       return CM_ERROR_BADSMB;
+    }
 
        /* try to get the vnode for the path name next */
        lock_ObtainMutex(&dsp->mx);
@@ -2064,31 +2106,33 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 curOffset.LowPart &= ~(2048-1);
                 curOffset.LowPart |= temp;
 
-               /* check if we've returned all the names that will fit in the
-                 * response packet; we check return count as well as the number
-                * of bytes requested.  We check the # of bytes after we find
-                * the dir entry, since we'll need to check its size.
-                 */
-               if (returnedNames >= maxCount) break;
+            /* check if we've passed the dir's EOF */
+            if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
+                eos = 1;
+                break;
+            }
+
+            /* check if we've returned all the names that will fit in the
+             * response packet; we check return count as well as the number
+             * of bytes requested.  We check the # of bytes after we find
+             * the dir entry, since we'll need to check its size.
+             */
+            if (returnedNames >= maxCount) {
+                break;
+            }
                 
-                /* check if we've passed the dir's EOF */
-                if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
-                       eos = 1;
-                       break;
-               }
-                
-                /* see if we can use the bufferp we have now; compute in which
-                * page the current offset would be, and check whether that's
-                * the offset of the buffer we have.  If not, get the buffer.
-                */
-                thyper.HighPart = curOffset.HighPart;
-                thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
-                if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+            /* see if we can use the bufferp we have now; compute in which
+             * page the current offset would be, and check whether that's
+             * the offset of the buffer we have.  If not, get the buffer.
+             */
+            thyper.HighPart = curOffset.HighPart;
+            thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+            if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
                        /* wrong buffer */
-                        if (bufferp) {
-                               buf_Release(bufferp);
-                                bufferp = NULL;
-                       }
+                if (bufferp) {
+                    buf_Release(bufferp);
+                    bufferp = NULL;
+                       }   
                        lock_ReleaseMutex(&scp->mx);
                        lock_ObtainRead(&scp->bufCreateLock);
                         code = buf_Get(scp, &thyper, &bufferp);
@@ -2199,6 +2243,28 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                        || (NeedShortName
                            && smb_V3MatchMask(shortName, maskp,
                                                CM_FLAG_CASEFOLD)))) {
+
+                        /* Eliminate entries that don't match requested
+                           attributes */
+                    if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) && 
+                        smb_IsDotFile(dep->name))
+                        goto nextEntry; /* no hidden files */
+                    
+                    if (!(dsp->attribute & SMB_ATTR_DIRECTORY))  /* no directories */
+                    {
+                            /* We have already done the cm_TryBulkStat above */
+                            fid.cell = scp->fid.cell;
+                            fid.volume = scp->fid.volume;
+                            fid.vnode = ntohl(dep->fid.vnode);
+                            fid.unique = ntohl(dep->fid.unique);
+                            fileType = cm_FindFileType(&fid);
+                            /*osi_Log2(afsd_logp, "smb_ReceiveTran2SearchDir: file %s "
+                              "has filetype %d", dep->name,
+                              fileType);*/
+                            if (fileType == CM_SCACHETYPE_DIRECTORY)
+                              goto nextEntry;
+                        }
+
                        /* finally check if this name will fit */
 
                        /* standard dir entry stuff */
@@ -2290,10 +2356,20 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                                curPatchp->dptr = op;
                                if (infoLevel >= 0x101)
                                        curPatchp->dptr += 8;
+
+                if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
+                    curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
+                }
+                else
+                    curPatchp->flags = 0;
+
                                curPatchp->fid.cell = scp->fid.cell;
                                curPatchp->fid.volume = scp->fid.volume;
                                curPatchp->fid.vnode = ntohl(dep->fid.vnode);
                                curPatchp->fid.unique = ntohl(dep->fid.unique);
+
+                                /* temp */
+                                curPatchp->dep = dep;
                        }
 
                        if (searchFlags & 4)
@@ -2367,245 +2443,259 @@ nextEntry:
          * we're supposed to close the search if we're done, and we're done,
          * or if something went wrong, close the search.
          */
-        if ((searchFlags & 1) || ((searchFlags & 2) && eos)
-               || code != 0) smb_DeleteDirSearch(dsp);
+        /* ((searchFlags & 1) || ((searchFlags & 2) && eos) */
+       if ((searchFlags & 1) || (returnedNames == 0) || ((searchFlags & 2) &&
+                                                         eos) || code != 0)
+           smb_DeleteDirSearch(dsp);
        if (code)
                smb_SendTran2Error(vcp, p, opx, code);
        else {
                smb_SendTran2Packet(vcp, outp, opx);
        }
        smb_FreeTran2Packet(outp);
-        smb_ReleaseDirSearch(dsp);
-        cm_ReleaseSCache(scp);
-        cm_ReleaseUser(userp);
-        return 0;
+    smb_ReleaseDirSearch(dsp);
+    cm_ReleaseSCache(scp);
+    cm_ReleaseUser(userp);
+    return 0;
 }
 
 long smb_ReceiveV3FindClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-        int dirHandle;
-        smb_dirSearch_t *dsp;
+    int dirHandle;
+    smb_dirSearch_t *dsp;
 
-        dirHandle = smb_GetSMBParm(inp, 0);
+    dirHandle = smb_GetSMBParm(inp, 0);
        
-        osi_Log1(afsd_logp, "SMB3 find close handle %d", dirHandle);
+    osi_Log1(afsd_logp, "SMB3 find close handle %d", dirHandle);
 
-        dsp = smb_FindDirSearch(dirHandle);
+    dsp = smb_FindDirSearch(dirHandle);
         
-        if (!dsp)
+    if (!dsp)
                return CM_ERROR_BADFD;
        
-        /* otherwise, we have an FD to destroy */
-        smb_DeleteDirSearch(dsp);
-        smb_ReleaseDirSearch(dsp);
+    /* otherwise, we have an FD to destroy */
+    smb_DeleteDirSearch(dsp);
+    smb_ReleaseDirSearch(dsp);
         
        /* and return results */
        smb_SetSMBDataLength(outp, 0);
 
-        return 0;
+    return 0;
 }
 
 long smb_ReceiveV3FindNotifyClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        smb_SetSMBDataLength(outp, 0);
-        return 0;
+    return 0;
 }
 
 long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *pathp;
-        long code;
+    long code;
        cm_space_t *spacep;
-        int excl;
-        cm_user_t *userp;
-        cm_scache_t *dscp;             /* dir we're dealing with */
-        cm_scache_t *scp;              /* file we're creating */
-        cm_attr_t setAttr;
-        int initialModeBits;
-        smb_fid_t *fidp;
-        int attributes;
-        char *lastNamep;
-        long dosTime;
-        int openFun;
-        int trunc;
-        int openMode;
-        int extraInfo;
-        int openAction;
-        int parmSlot;                  /* which parm we're dealing with */
+    int excl;
+    cm_user_t *userp;
+    cm_scache_t *dscp;         /* dir we're dealing with */
+    cm_scache_t *scp;          /* file we're creating */
+    cm_attr_t setAttr;
+    int initialModeBits;
+    smb_fid_t *fidp;
+    int attributes;
+    char *lastNamep;
+    long dosTime;
+    int openFun;
+    int trunc;
+    int openMode;
+    int extraInfo;
+    int openAction;
+    int parmSlot;                      /* which parm we're dealing with */
        char *tidPathp;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        scp = NULL;
+    scp = NULL;
         
        extraInfo = (smb_GetSMBParm(inp, 2) & 1);       /* return extra info */
        openFun = smb_GetSMBParm(inp, 8);       /* open function */
-        excl = ((openFun & 3) == 0);
-        trunc = ((openFun & 3) == 2);          /* truncate it */
+    excl = ((openFun & 3) == 0);
+    trunc = ((openFun & 3) == 2);              /* truncate it */
        openMode = (smb_GetSMBParm(inp, 3) & 0x7);
-        openAction = 0;                        /* tracks what we did */
+    openAction = 0;                    /* tracks what we did */
+
+    attributes = smb_GetSMBParm(inp, 5);
+    dosTime = smb_GetSMBParm(inp, 6) | (smb_GetSMBParm(inp, 7) << 16);
 
-        attributes = smb_GetSMBParm(inp, 5);
-        dosTime = smb_GetSMBParm(inp, 6) | (smb_GetSMBParm(inp, 7) << 16);
-        
        /* compute initial mode bits based on read-only flag in attributes */
-        initialModeBits = 0666;
-        if (attributes & 1) initialModeBits &= ~0222;
+    initialModeBits = 0666;
+    if (attributes & 1) initialModeBits &= ~0222;
         
-        pathp = smb_GetSMBData(inp, NULL);
+    pathp = smb_GetSMBData(inp, NULL);
 
        spacep = inp->spacep;
-        smb_StripLastComponent(spacep->data, &lastNamep, pathp);
+    smb_StripLastComponent(spacep->data, &lastNamep, pathp);
 
        if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
                /* special case magic file name for receiving IOCTL requests
-                 * (since IOCTL calls themselves aren't getting through).
-                 */
-               fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-                smb_SetupIoctlFid(fidp, spacep);
+         * (since IOCTL calls themselves aren't getting through).
+         */
+#ifdef NOTSERVICE
+        osi_Log0(afsd_logp, "IOCTL Open");
+#endif
+
+        fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
+        smb_SetupIoctlFid(fidp, spacep);
 
                /* set inp->fid so that later read calls in same msg can find fid */
-               inp->fid = fidp->fid;
+        inp->fid = fidp->fid;
         
-               /* copy out remainder of the parms */
+        /* copy out remainder of the parms */
                parmSlot = 2;
                smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
                if (extraInfo) {
-                       smb_SetSMBParm(outp, parmSlot, /* attrs */ 0); parmSlot++;
-                       smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;  /* mod time */
-                       smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
-                       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, /* attrs */ 0); parmSlot++;
+            smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* mod time */
+            smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
+            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 */
+               }   
                /* and the final "always present" stuff */
-               smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, /* openAction found existing file */ 1); parmSlot++;
                /* next write out the "unique" ID */
                smb_SetSMBParm(outp, parmSlot, 0x1234); parmSlot++;
                smb_SetSMBParm(outp, parmSlot, 0x5678); parmSlot++;
-               smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
-               smb_SetSMBDataLength(outp, 0);
+        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
+        smb_SetSMBDataLength(outp, 0);
 
                /* and clean up fid reference */
-                smb_ReleaseFID(fidp);
-                return 0;
-        }
-
-       userp = smb_GetUser(vcp, inp);
+        smb_ReleaseFID(fidp);
+        return 0;
+    }
+
+#ifdef DEBUG_VERBOSE
+    {
+       char *hexp, *asciip;
+       asciip = (lastNamep ? lastNamep : pathp );
+       hexp = osi_HexifyString(asciip);
+       DEBUG_EVENT2("AFS", "V3Open H[%s] A[%s]", hexp, asciip );
+       free(hexp);
+    }
+#endif
+    userp = smb_GetUser(vcp, inp);
 
        dscp = NULL;
        tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        code = cm_NameI(cm_rootSCachep, pathp,
-               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-               userp, tidPathp, &req, &scp);
+                    CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                    userp, tidPathp, &req, &scp);
        if (code != 0) {
                code = cm_NameI(cm_rootSCachep, spacep->data,
-                               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                               userp, tidPathp, &req, &dscp);
+                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                        userp, tidPathp, &req, &dscp);
 
-               if (code) {
-                       cm_ReleaseUser(userp);
-                       return code;
-               }
+        if (code) {
+            cm_ReleaseUser(userp);
+            return code;
+        }
         
-               /* otherwise, scp points to the parent directory.  Do a lookup,
-                * and truncate the file if we find it, otherwise we create the
-                * file.
-                */
-               if (!lastNamep) lastNamep = pathp;
-               else lastNamep++;
-               code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
-                                &req, &scp);
-               if (code && code != CM_ERROR_NOSUCHFILE) {
+        /* otherwise, scp points to the parent directory.  Do a lookup,
+         * and truncate the file if we find it, otherwise we create the
+         * file.
+         */
+        if (!lastNamep) lastNamep = pathp;
+        else lastNamep++;
+        code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp,
+                          &req, &scp);
+        if (code && code != CM_ERROR_NOSUCHFILE) {
                        cm_ReleaseSCache(dscp);
-                       cm_ReleaseUser(userp);
-                       return code;
-               }
+            cm_ReleaseUser(userp);
+            return code;
+        }
        }
         
-        /* if we get here, if code is 0, the file exists and is represented by
-         * scp.  Otherwise, we have to create it.  The dir may be represented
-         * by dscp, or we may have found the file directly.  If code is non-zero,
-         * scp is NULL.
-         */
+    /* if we get here, if code is 0, the file exists and is represented by
+     * scp.  Otherwise, we have to create it.  The dir may be represented
+     * by dscp, or we may have found the file directly.  If code is non-zero,
+     * scp is NULL.
+     */
        if (code == 0) {
-               code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
-                if (code) {
-                        if (dscp) cm_ReleaseSCache(dscp);
-                        cm_ReleaseSCache(scp);
-                        cm_ReleaseUser(userp);
-                        return code;
-                }
+        code = cm_CheckOpen(scp, openMode, trunc, userp, &req);
+        if (code) {
+            if (dscp) cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            return code;
+        }
 
                if (excl) {
                        /* oops, file shouldn't be there */
-                        if (dscp) cm_ReleaseSCache(dscp);
-                        cm_ReleaseSCache(scp);
-                        cm_ReleaseUser(userp);
-                        return CM_ERROR_EXISTS;
-                }
+            if (dscp) cm_ReleaseSCache(dscp);
+            cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            return CM_ERROR_EXISTS;
+        }
 
                if (trunc) {
                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                       setAttr.length.LowPart = 0;
-                       setAttr.length.HighPart = 0;
+            setAttr.length.LowPart = 0;
+            setAttr.length.HighPart = 0;
                        code = cm_SetAttr(scp, &setAttr, userp, &req);
-                        openAction = 3;        /* truncated existing file */
+            openAction = 3;    /* truncated existing file */
                }
-                else openAction = 1;   /* found existing file */
-        }
+        else openAction = 1;   /* found existing file */
+    }
        else if (!(openFun & 0x10)) {
                /* don't create if not found */
-                if (dscp) cm_ReleaseSCache(dscp);
-                cm_ReleaseUser(userp);
-                return CM_ERROR_NOSUCHFILE;
-        }
-        else {
+        if (dscp) cm_ReleaseSCache(dscp);
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHFILE;
+    }
+    else {
                osi_assert(dscp != NULL);
                osi_Log1(afsd_logp, "smb_ReceiveV3OpenX creating file %s",
-                               osi_LogSaveString(afsd_logp, lastNamep));
+                 osi_LogSaveString(afsd_logp, lastNamep));
                openAction = 2; /* created file */
                setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
                smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
-                code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
-                                &req);
+        code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp,
+                         &req);
                if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                        smb_NotifyChange(FILE_ACTION_ADDED,
-                                        FILE_NOTIFY_CHANGE_FILE_NAME,
-                                        dscp, lastNamep, NULL, TRUE);
-                if (!excl && code == CM_ERROR_EXISTS) {
+                             FILE_NOTIFY_CHANGE_FILE_NAME,
+                             dscp, lastNamep, NULL, TRUE);
+        if (!excl && code == CM_ERROR_EXISTS) {
                        /* not an exclusive create, and someone else tried
                         * creating it already, then we open it anyway.  We
                         * don't bother retrying after this, since if this next
                         * fails, that means that the file was deleted after we
                         * started this call.
-                         */
-                        code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
-                                        userp, &req, &scp);
-                        if (code == 0) {
-                               if (trunc) {
+             */
+            code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
+                             userp, &req, &scp);
+            if (code == 0) {
+                if (trunc) {
                                        setAttr.mask = CM_ATTRMASK_LENGTH;
-                                       setAttr.length.LowPart = 0;
-                                       setAttr.length.HighPart = 0;
-                                       code = cm_SetAttr(scp, &setAttr, userp,
-                                                         &req);
-                               }
+                    setAttr.length.LowPart = 0;
+                    setAttr.length.HighPart = 0;
+                    code = cm_SetAttr(scp, &setAttr, userp, &req);
+                }   
                        }       /* lookup succeeded */
-                }
         }
+    }
         
        /* we don't need this any longer */
        if (dscp) cm_ReleaseSCache(dscp);
 
-        if (code) {
+    if (code) {
                /* something went wrong creating or truncating the file */
-                if (scp) cm_ReleaseSCache(scp);
-                cm_ReleaseUser(userp);
-                return code;
-        }
+        if (scp) cm_ReleaseSCache(scp);
+        cm_ReleaseUser(userp);
+        return code;
+    }
         
        /* make sure we're about to open a file */
        if (scp->fileType != CM_SCACHETYPE_FILE) {
@@ -2614,55 +2704,55 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                return CM_ERROR_ISDIR;
        }
 
-        /* now all we have to do is open the file itself */
-        fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
-        osi_assert(fidp);
+    /* now all we have to do is open the file itself */
+    fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
+    osi_assert(fidp);
        
        /* save a pointer to the vnode */
-        fidp->scp = scp;
+    fidp->scp = scp;
         
        /* compute open mode */
-        if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
-        if (openMode == 1 || openMode == 2)
-               fidp->flags |= SMB_FID_OPENWRITE;
+    if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
+    if (openMode == 1 || openMode == 2)
+        fidp->flags |= SMB_FID_OPENWRITE;
 
        smb_ReleaseFID(fidp);
         
        cm_Open(scp, 0, userp);
 
        /* set inp->fid so that later read calls in same msg can find fid */
-        inp->fid = fidp->fid;
+    inp->fid = fidp->fid;
         
-        /* copy out remainder of the parms */
+    /* copy out remainder of the parms */
        parmSlot = 2;
        smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++;
        lock_ObtainMutex(&scp->mx);
        if (extraInfo) {
-               smb_SetSMBParm(outp, parmSlot, smb_Attributes(scp)); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, smb_Attributes(scp)); parmSlot++;
                smb_DosUTimeFromUnixTime(&dosTime, scp->clientModTime);
-                smb_SetSMBParm(outp, parmSlot, dosTime & 0xffff); parmSlot++;
-                smb_SetSMBParm(outp, parmSlot, (dosTime>>16) & 0xffff); parmSlot++;
-                smb_SetSMBParm(outp, parmSlot, scp->length.LowPart & 0xffff); parmSlot++;
-                smb_SetSMBParm(outp, parmSlot, (scp->length.LowPart >> 16) & 0xffff); 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, dosTime & 0xffff); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, (dosTime>>16) & 0xffff); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, scp->length.LowPart & 0xffff); parmSlot++;
+        smb_SetSMBParm(outp, parmSlot, (scp->length.LowPart >> 16) & 0xffff); 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 */
        }
        /* and the final "always present" stuff */
-        smb_SetSMBParm(outp, parmSlot, openAction); parmSlot++;
+    smb_SetSMBParm(outp, parmSlot, openAction); parmSlot++;
        /* next write out the "unique" ID */
        smb_SetSMBParm(outp, parmSlot, scp->fid.vnode & 0xffff); parmSlot++;
        smb_SetSMBParm(outp, parmSlot, scp->fid.volume & 0xffff); parmSlot++;
-        smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
+    smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;
        lock_ReleaseMutex(&scp->mx);
-        smb_SetSMBDataLength(outp, 0);
+    smb_SetSMBDataLength(outp, 0);
 
        osi_Log1(afsd_logp, "SMB OpenX opening fid %d", fidp->fid);
 
-        cm_ReleaseUser(userp);
-        /* leave scp held since we put it in fidp->scp */
-        return 0;
-}
+    cm_ReleaseUser(userp);
+    /* leave scp held since we put it in fidp->scp */
+    return 0;
+}   
 
 long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
@@ -2691,7 +2781,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                return CM_ERROR_BADFD;
        }
        /* set inp->fid so that later read calls in same msg can find fid */
-        inp->fid = fid;
+    inp->fid = fid;
 
        userp = smb_GetUser(vcp, inp);
 
@@ -2797,57 +2887,57 @@ doneSync:
 long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        unsigned short fid;
-        smb_fid_t *fidp;
-        cm_scache_t *scp;
-        long code;
-        long searchTime;
-        cm_user_t *userp;
+    smb_fid_t *fidp;
+    cm_scache_t *scp;
+    long code;
+    long searchTime;
+    cm_user_t *userp;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        fid = smb_GetSMBParm(inp, 0);
-        fid = smb_ChainFID(fid, inp);
+    fid = smb_GetSMBParm(inp, 0);
+    fid = smb_ChainFID(fid, inp);
         
-        fidp = smb_FindFID(vcp, fid, 0);
-        if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
                return CM_ERROR_BADFD;
-        }
+    }
         
-        userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUser(vcp, inp);
         
-        scp = fidp->scp;
+    scp = fidp->scp;
         
-        /* otherwise, stat the file */
+    /* otherwise, stat the file */
        lock_ObtainMutex(&scp->mx);
-        code = cm_SyncOp(scp, NULL, userp, &req, 0,
-               CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    code = cm_SyncOp(scp, NULL, userp, &req, 0,
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
        if (code) goto done;
 
        /* decode times.  We need a search time, but the response to this
-         * call provides the date first, not the time, as returned in the
-         * searchTime variable.  So we take the high-order bits first.
-         */
+     * 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);
-        smb_SetSMBParm(outp, 0, (searchTime >> 16) & 0xffff);  /* ctime */
-        smb_SetSMBParm(outp, 1, searchTime & 0xffff);
-        smb_SetSMBParm(outp, 2, (searchTime >> 16) & 0xffff);  /* atime */
-        smb_SetSMBParm(outp, 3, searchTime & 0xffff);
-        smb_SetSMBParm(outp, 4, (searchTime >> 16) & 0xffff);  /* mtime */
-        smb_SetSMBParm(outp, 5, searchTime & 0xffff);
-        
-        /* now handle file size and allocation size */
-        smb_SetSMBParm(outp, 6, scp->length.LowPart & 0xffff);         /* file size */
-        smb_SetSMBParm(outp, 7, (scp->length.LowPart >> 16) & 0xffff);
-        smb_SetSMBParm(outp, 8, scp->length.LowPart & 0xffff);         /* alloc size */
-        smb_SetSMBParm(outp, 9, (scp->length.LowPart >> 16) & 0xffff);
-        
+    smb_SetSMBParm(outp, 0, (searchTime >> 16) & 0xffff);      /* ctime */
+    smb_SetSMBParm(outp, 1, searchTime & 0xffff);
+    smb_SetSMBParm(outp, 2, (searchTime >> 16) & 0xffff);      /* atime */
+    smb_SetSMBParm(outp, 3, searchTime & 0xffff);
+    smb_SetSMBParm(outp, 4, (searchTime >> 16) & 0xffff);      /* mtime */
+    smb_SetSMBParm(outp, 5, searchTime & 0xffff);
+
+    /* now handle file size and allocation size */
+    smb_SetSMBParm(outp, 6, scp->length.LowPart & 0xffff);             /* file size */
+    smb_SetSMBParm(outp, 7, (scp->length.LowPart >> 16) & 0xffff);
+    smb_SetSMBParm(outp, 8, scp->length.LowPart & 0xffff);             /* alloc size */
+    smb_SetSMBParm(outp, 9, (scp->length.LowPart >> 16) & 0xffff);
+
        /* file attribute */
-        smb_SetSMBParm(outp, 10, smb_Attributes(scp));
+    smb_SetSMBParm(outp, 10, smb_Attributes(scp));
         
-        /* and finalize stuff */
-        smb_SetSMBDataLength(outp, 0);
-        code = 0;
+    /* and finalize stuff */
+    smb_SetSMBDataLength(outp, 0);
+    code = 0;
 
 done:
        lock_ReleaseMutex(&scp->mx);
@@ -2859,42 +2949,49 @@ done:
 long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        unsigned short fid;
-        smb_fid_t *fidp;
-        cm_scache_t *scp;
-        long code;
+    smb_fid_t *fidp;
+    cm_scache_t *scp;
+    long code;
        long searchTime;
-        long unixTime;
-        cm_user_t *userp;
-        cm_attr_t attrs;
+    long unixTime;
+    cm_user_t *userp;
+    cm_attr_t attrs;
        cm_req_t req;
 
        cm_InitReq(&req);
 
-        fid = smb_GetSMBParm(inp, 0);
-        fid = smb_ChainFID(fid, inp);
+    fid = smb_GetSMBParm(inp, 0);
+    fid = smb_ChainFID(fid, inp);
         
-        fidp = smb_FindFID(vcp, fid, 0);
-        if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
                return CM_ERROR_BADFD;
-        }
+    }
         
-        userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUser(vcp, inp);
         
-        scp = fidp->scp;
+    scp = fidp->scp;
         
        /* 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.
-         */
+     * and AFS only implements mtime, and we'll set the mtime if that's
+     * requested.  The others we'll ignore.
+     */
        searchTime = smb_GetSMBParm(inp, 5) | (smb_GetSMBParm(inp, 6) << 16);
         
-        if (searchTime != 0) {
+    if (searchTime != 0) {
                smb_UnixTimeFromSearchTime(&unixTime, searchTime);
-                attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
-                attrs.clientModTime = unixTime;
-                code = cm_SetAttr(scp, &attrs, userp, &req);
+
+        if ( unixTime != -1 ) {
+            attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
+            attrs.clientModTime = unixTime;
+            code = cm_SetAttr(scp, &attrs, userp, &req);
+
+            osi_Log1(afsd_logp, "SMB receive V3SetAttributes [fid=%ld]", fid);
+        } else {
+            osi_Log1(afsd_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
         }
-        else code = 0;
+    }
+    else code = 0;
 
        cm_ReleaseUser(userp);
        smb_ReleaseFID(fidp);
@@ -2905,71 +3002,75 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
 long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        osi_hyper_t offset;
-        long count, finalCount;
-        unsigned short fd;
-        smb_fid_t *fidp;
-        long code;
-        cm_user_t *userp;
-        char *op;
-        
-        fd = smb_GetSMBParm(inp, 2);
-        count = smb_GetSMBParm(inp, 5);
-        offset.HighPart = 0;   /* too bad */
-        offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+    long count, finalCount;
+    unsigned short fd;
+    smb_fid_t *fidp;
+    long code;
+    cm_user_t *userp;
+    char *op;
         
-        osi_Log3(afsd_logp, "smb_ReceiveV3Read fd %d, off 0x%x, size 0x%x",
-               fd, offset.LowPart, count);
+    fd = smb_GetSMBParm(inp, 2);
+    count = smb_GetSMBParm(inp, 5);
+    offset.HighPart = 0;       /* too bad */
+    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+
+    osi_Log3(afsd_logp, "smb_ReceiveV3Read fd %d, off 0x%x, size 0x%x",
+             fd, offset.LowPart, count);
         
        fd = smb_ChainFID(fd, inp);
-        fidp = smb_FindFID(vcp, fd, 0);
-        if (!fidp) {
+    fidp = smb_FindFID(vcp, fd, 0);
+    if (!fidp) {
                return CM_ERROR_BADFD;
-        }
+    }
        /* set inp->fid so that later read calls in same msg can find fid */
-        inp->fid = fd;
+    inp->fid = fd;
 
-        if (fidp->flags & SMB_FID_IOCTL) {
+    if (fidp->flags & SMB_FID_IOCTL) {
                return smb_IoctlV3Read(fidp, vcp, inp, outp);
-        }
+    }
         
        userp = smb_GetUser(vcp, inp);
 
        /* 0 and 1 are reserved for request chaining, were setup by our caller,
-         * and will be further filled in after we return.
-         */
-        smb_SetSMBParm(outp, 2, 0);    /* remaining bytes, for pipes */
-        smb_SetSMBParm(outp, 3, 0);    /* resvd */
-        smb_SetSMBParm(outp, 4, 0);    /* resvd */
+     * and will be further filled in after we return.
+     */
+    smb_SetSMBParm(outp, 2, 0);        /* remaining bytes, for pipes */
+    smb_SetSMBParm(outp, 3, 0);        /* resvd */
+    smb_SetSMBParm(outp, 4, 0);        /* resvd */
        smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */
-        /* fill in #6 when we have all the parameters' space reserved */
-        smb_SetSMBParm(outp, 7, 0);    /* resv'd */
-        smb_SetSMBParm(outp, 8, 0);    /* resv'd */
-        smb_SetSMBParm(outp, 9, 0);    /* resv'd */
-        smb_SetSMBParm(outp, 10, 0);   /* resv'd */
+    /* fill in #6 when we have all the parameters' space reserved */
+    smb_SetSMBParm(outp, 7, 0);        /* resv'd */
+    smb_SetSMBParm(outp, 8, 0);        /* resv'd */
+    smb_SetSMBParm(outp, 9, 0);        /* resv'd */
+    smb_SetSMBParm(outp, 10, 0);       /* resv'd */
        smb_SetSMBParm(outp, 11, 0);    /* reserved */
 
        /* get op ptr after putting in the parms, since otherwise we don't
-         * know where the data really is.
-         */
-        op = smb_GetSMBData(outp, NULL);
+     * know where the data really is.
+     */
+    op = smb_GetSMBData(outp, NULL);
         
-        /* now fill in offset from start of SMB header to first data byte (to op) */
-        smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
+    /* now fill in offset from start of SMB header to first data byte (to op) */
+    smb_SetSMBParm(outp, 6, ((int) (op - outp->data)));
 
        /* set the packet data length the count of the # of bytes */
-        smb_SetSMBDataLength(outp, count);
+    smb_SetSMBDataLength(outp, count);
 
+#ifndef DJGPP
        code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
+#else /* DJGPP */
+       code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
+#endif /* !DJGPP */
 
        /* fix some things up */
        smb_SetSMBParm(outp, 5, finalCount);
        smb_SetSMBDataLength(outp, finalCount);
 
-        smb_ReleaseFID(fidp);
+    smb_ReleaseFID(fidp);
 
-        cm_ReleaseUser(userp);
-        return code;
-}
+    cm_ReleaseUser(userp);
+    return code;
+}   
         
 /*
  * Values for createDisp, copied from NTDDK.H
@@ -2992,11 +3093,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        cm_scache_t *scp;               /* file to create or open */
        cm_attr_t setAttr;
        char *lastNamep;
+    char *treeStartp;
        unsigned short nameLength;
        unsigned int flags;
        unsigned int requestOpLock;
        unsigned int requestBatchOpLock;
        unsigned int mustBeDir;
+    unsigned int treeCreate;
        int realDirFlag;
        unsigned int desiredAccess;
        unsigned int extAttributes;
@@ -3018,6 +3121,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        cm_InitReq(&req);
 
+    treeCreate = FALSE;
        foundscp = FALSE;
        scp = NULL;
 
@@ -3070,6 +3174,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        spacep = inp->spacep;
        smb_StripLastComponent(spacep->data, &lastNamep, realPathp);
 
+    osi_Log1(afsd_logp,"NTCreateX for [%s]",osi_LogSaveString(afsd_logp,realPathp));
+    osi_Log4(afsd_logp,"NTCreateX da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
+
        if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
                /* special case magic file name for receiving IOCTL requests
                 * (since IOCTL calls themselves aren't getting through).
@@ -3106,19 +3213,41 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                return 0;
        }
 
-       userp = smb_GetUser(vcp, inp);
+#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);
+    }
+#endif
+    userp = smb_GetUser(vcp, inp);
+    if (!userp) {
+       osi_Log1(afsd_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
+       free(realPathp);
+       return CM_ERROR_INVAL;
+    }
 
        if (baseFid == 0) {
                baseDirp = cm_rootSCachep;
                tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        }
        else {
-               baseFidp = smb_FindFID(vcp, baseFid, 0);
+        baseFidp = smb_FindFID(vcp, baseFid, 0);
+        if (!baseFidp) {
+               osi_Log1(afsd_logp, "NTCreateX Invalid base fid [%d]", baseFid);
+               free(realPathp);
+               cm_ReleaseUser(userp);
+               return CM_ERROR_INVAL;
+        }
                baseDirp = baseFidp->scp;
                tidPathp = NULL;
        }
 
-       /* compute open mode */
+    osi_Log1(afsd_logp, "NTCreateX tidPathp=[%s]", (tidPathp==NULL)?"null": osi_LogSaveString(afsd_logp,tidPathp));
+       
+    /* compute open mode */
        fidflags = 0;
        if (desiredAccess & DELETE)
                fidflags |= SMB_FID_OPENDELETE;
@@ -3135,25 +3264,65 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        if (code != 0
            || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
                /* look up parent directory */
-               code = cm_NameI(baseDirp, spacep->data,
-                               CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                               userp, tidPathp, &req, &dscp);
+        /* If we are trying to create a path (i.e. multiple nested directories), then we don't *need*
+        the immediate parent.  We have to work our way up realPathp until we hit something that we
+        recognize.
+        */
+
+        while(1) {
+            char *tp;
+
+            code = cm_NameI(baseDirp, spacep->data,
+                             CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                             userp, tidPathp, &req, &dscp);
+
+            if (code && 
+                (tp = strrchr(spacep->data,'\\')) &&
+                (createDisp == 2) &&
+                (realDirFlag == 1)) {
+                *tp++ = 0;
+                treeCreate = TRUE;
+                treeStartp = realPathp + (tp - spacep->data);
+
+                if (*tp && !smb_IsLegalFilename(tp)) {
+                    if(baseFid != 0) smb_ReleaseFID(baseFidp);
+                    cm_ReleaseUser(userp);
+                    free(realPathp);
+                    return CM_ERROR_BADNTFILENAME;
+                }
+            }
+            else
+                break;
+        }
 
-               if (baseFid != 0) smb_ReleaseFID(baseFidp);
+        if (baseFid != 0) smb_ReleaseFID(baseFidp);
 
-               if (code) {
-                       cm_ReleaseUser(userp);
-                       free(realPathp);
-                       return code;
-               }
+        if (code) {
+            osi_Log0(afsd_logp,"NTCreateX parent not found");
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return code;
+        }
 
-               if (!lastNamep) lastNamep = realPathp;
-               else lastNamep++;
+        if(treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
+            /* A file exists where we want a directory. */
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return CM_ERROR_EXISTS;
+        }
 
-                if (!smb_IsLegalFilename(lastNamep))
-                        return CM_ERROR_BADNTFILENAME;
+        if (!lastNamep) lastNamep = realPathp;
+        else lastNamep++;
 
-               if (!foundscp) {
+        if (!smb_IsLegalFilename(lastNamep)) {
+            cm_ReleaseSCache(dscp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return CM_ERROR_BADNTFILENAME;
+        }
+
+        if (!foundscp && !treeCreate) {
                        code = cm_Lookup(dscp, lastNamep,
                                         CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
                                         userp, &req, &scp);
@@ -3174,7 +3343,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         * by dscp, or we may have found the file directly.  If code is non-zero,
         * scp is NULL.
         */
-       if (code == 0) {
+       if (code == 0 && !treeCreate) {
                code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
                                      &req);
                if (code) {
@@ -3245,48 +3414,96 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                }
        }
        else {
-               /* create directory */
-               osi_assert(dscp != NULL);
-               osi_Log1(afsd_logp, "smb_ReceiveNTCreateX creating directory %s",
-                               osi_LogSaveString(afsd_logp, lastNamep));
+        char *tp, *pp;
+        char *cp; /* This component */
+        int clen = 0; /* length of component */
+        cm_scache_t *tscp;
+        int isLast = 0;
+               
+        /* create directory */
+               if ( !treeCreate ) treeStartp = lastNamep;
+        osi_assert(dscp != NULL);
+        osi_Log1(afsd_logp, "smb_ReceiveNTCreateX creating directory [%s]",
+                               osi_LogSaveString(afsd_logp, treeStartp));
                openAction = 2;         /* created directory */
+
                setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
                setAttr.clientModTime = time(NULL);
-               code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req);
-               if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-                       smb_NotifyChange(FILE_ACTION_ADDED,
-                                        FILE_NOTIFY_CHANGE_DIR_NAME,
-                                        dscp, lastNamep, NULL, TRUE);
-               if (code == 0
-                   || (code == CM_ERROR_EXISTS && createDisp != 2)) {
-                       /* Not an exclusive create, and someone else tried
-                        * creating it already, then we open it anyway.  We
-                        * don't bother retrying after this, since if this next
-                        * fails, that means that the file was deleted after we
-                        * started this call.
-                        */
-                       code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
-                                        userp, &req, &scp);
+               
+               pp = treeStartp;
+               cp = spacep->data;
+               tscp = dscp;
+
+               while(pp && *pp) {
+                       tp = strchr(pp, '\\');
+                       if(!tp) {
+                               strcpy(cp,pp);
+                clen = strlen(cp);
+                               isLast = 1; /* indicate last component.  the supplied path never ends in a slash */
+                       }
+                       else {
+                               clen = tp - pp;
+                               strncpy(cp,pp,clen);
+                               *(cp + clen) = 0;
+                               tp++;
+                       }
+                       pp = tp;
+
+                       if(clen == 0) continue; /* the supplied path can't have consecutive slashes either , but */
+
+                       /* cp is the next component to be created. */
+                       code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req);
+                       if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH))
+                               smb_NotifyChange(FILE_ACTION_ADDED,
+                               FILE_NOTIFY_CHANGE_DIR_NAME,
+                               tscp, cp, NULL, TRUE);
+                       if (code == 0 || 
+                               (code == CM_ERROR_EXISTS && createDisp != 2)) {
+                                       /* Not an exclusive create, and someone else tried
+                                       * creating it already, then we open it anyway.  We
+                                       * don't bother retrying after this, since if this next
+                                       * fails, that means that the file was deleted after we
+                                       * started this call.
+                                       */
+                                       code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD,
+                                               userp, &req, &scp);
+                               }
+                       if(code) break;
+
+                       if(!isLast) { /* for anything other than dscp, release it unless it's the last one */
+                               cm_ReleaseSCache(tscp);
+                               tscp = scp; /* Newly created directory will be next parent */
+                       }
                }
+
+               /* 
+               if we get here and code == 0, then scp is the last directory created, and tscp is the
+               parent of scp.  dscp got released if dscp != tscp. both tscp and scp are held.
+               */
+               dscp = tscp;
        }
 
        if (code) {
                /* something went wrong creating or truncating the file */
                if (scp) cm_ReleaseSCache(scp);
+        if (dscp) cm_ReleaseSCache(dscp);
                cm_ReleaseUser(userp);
                free(realPathp);
                return code;
        }
 
-       /* make sure we have file vs. dir right */
+       /* make sure we have file vs. dir right (only applies for single component case) */
        if (realDirFlag == 0 && scp->fileType != CM_SCACHETYPE_FILE) {
                cm_ReleaseSCache(scp);
+        if (dscp) cm_ReleaseSCache(dscp);
                cm_ReleaseUser(userp);
                free(realPathp);
                return CM_ERROR_ISDIR;
        }
+    /* (only applies to single component case) */
        if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
                cm_ReleaseSCache(scp);
+        if (dscp) cm_ReleaseSCache(dscp);
                cm_ReleaseUser(userp);
                free(realPathp);
                return CM_ERROR_NOTDIR;
@@ -3345,6 +3562,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        cm_ReleaseUser(userp);
 
+    /* Can't free realPathp if we get here since fidp->NTopen_wholepathp is pointing there */
+
        /* leave scp held since we put it in fidp->scp */
        return 0;
 }
@@ -3368,10 +3587,18 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        unsigned int requestOpLock;
        unsigned int requestBatchOpLock;
        unsigned int mustBeDir;
+    unsigned int extendedRespRequired;
        int realDirFlag;
        unsigned int desiredAccess;
+#ifdef DEBUG_VERBOSE    
+    unsigned int allocSize;
+    unsigned int shareAccess;
+#endif
        unsigned int extAttributes;
        unsigned int createDisp;
+#ifdef DEBUG_VERBOSE
+    unsigned int sdLen;
+#endif
        unsigned int createOptions;
        int initialModeBits;
        unsigned short baseFid;
@@ -3404,6 +3631,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        requestOpLock = flags & 0x02;
        requestBatchOpLock = flags & 0x04;
        mustBeDir = flags & 0x08;
+    extendedRespRequired = flags & 0x10;
+
        /*
         * Why all of a sudden 32-bit FID?
         * We will reject all bits higher than 16.
@@ -3412,11 +3641,26 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                return CM_ERROR_INVAL;
        baseFid = (unsigned short)lparmp[1];
        desiredAccess = lparmp[2];
+#ifdef DEBUG_VERBOSE
+    allocSize = lparmp[3];
+#endif /* DEBUG_VERSOSE */
        extAttributes = lparmp[5];
+#ifdef DEBUG_VEROSE
+    shareAccess = lparmp[6];
+#endif
        createDisp = lparmp[7];
        createOptions = lparmp[8];
+#ifdef DEBUG_VERBOSE
+    sdLen = lparmp[9];
+#endif
        nameLength = lparmp[11];
 
+#ifdef DEBUG_VERBOSE
+       osi_Log4(afsd_logp,"NTTransCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
+       osi_Log2(afsd_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize);
+       osi_Log1(afsd_logp,"... flags[%x]",flags);
+#endif
+
        /* mustBeDir is never set; createOptions directory bit seems to be
          * more important
         */
@@ -3448,26 +3692,47 @@ 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);
+               free(hexp);
+       }
+#endif
+
        userp = smb_GetUser(vcp, inp);
+    if(!userp) {
+       osi_Log1(afsd_logp, "NTTranCreate invalid user [%d]", ((smb_t *) inp)->uid);
+       free(realPathp);
+       return CM_ERROR_INVAL;
+    }
 
        if (baseFid == 0) {
                baseDirp = cm_rootSCachep;
                tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
        }
        else {
-               baseFidp = smb_FindFID(vcp, baseFid, 0);
+        baseFidp = smb_FindFID(vcp, baseFid, 0);
+        if(!baseFidp) {
+               osi_Log1(afsd_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+               free(realPathp);
+               cm_ReleaseUser(userp);
+               return CM_ERROR_INVAL;
+        }
                baseDirp = baseFidp->scp;
                tidPathp = NULL;
        }
 
-        /* compute open mode */
-        fidflags = 0;
-        if (desiredAccess & DELETE)
-                fidflags |= SMB_FID_OPENDELETE;
-        if (desiredAccess & AFS_ACCESS_READ)
-                fidflags |= SMB_FID_OPENREAD;
-        if (desiredAccess & AFS_ACCESS_WRITE)
-                fidflags |= SMB_FID_OPENWRITE;
+    /* compute open mode */
+    fidflags = 0;
+    if (desiredAccess & DELETE)
+        fidflags |= SMB_FID_OPENDELETE;
+    if (desiredAccess & AFS_ACCESS_READ)
+        fidflags |= SMB_FID_OPENREAD;
+    if (desiredAccess & AFS_ACCESS_WRITE)
+        fidflags |= SMB_FID_OPENWRITE;
 
        dscp = NULL;
        code = 0;
@@ -3482,7 +3747,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                                userp, tidPathp, &req, &dscp);
                cm_FreeSpace(spacep);
 
-               if (baseFid != 0) smb_ReleaseFID(baseFidp);
+               if (baseFid != 0) {
+           smb_ReleaseFID(baseFidp);
+           baseFidp = 0;
+        }
 
                if (code) {
                        cm_ReleaseUser(userp);
@@ -3493,13 +3761,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                if (!lastNamep) lastNamep = realPathp;
                else lastNamep++;
 
-                if (!smb_IsLegalFilename(lastNamep))
-                        return CM_ERROR_BADNTFILENAME;
+        if (!smb_IsLegalFilename(lastNamep))
+            return CM_ERROR_BADNTFILENAME;
 
                if (!foundscp) {
                        code = cm_Lookup(dscp, lastNamep,
-                                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
-                                        userp, &req, &scp);
+                             CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+                             userp, &req, &scp);
                        if (code && code != CM_ERROR_NOSUCHFILE) {
                                cm_ReleaseSCache(dscp);
                                cm_ReleaseUser(userp);
@@ -3509,7 +3777,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                }
        }
        else {
-               if (baseFid != 0) smb_ReleaseFID(baseFidp);
+               if (baseFid != 0) {
+            smb_ReleaseFID(baseFidp);
+            baseFidp = 0;
+        }
                cm_FreeSpace(spacep);
        }
 
@@ -3558,7 +3829,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        else if (realDirFlag == 0 || realDirFlag == -1) {
                osi_assert(dscp != NULL);
                osi_Log1(afsd_logp, "smb_ReceiveNTTranCreate creating file %s",
-                               osi_LogSaveString(afsd_logp, lastNamep));
+                 osi_LogSaveString(afsd_logp, lastNamep));
                openAction = 2;         /* created file */
                setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
                setAttr.clientModTime = time(NULL);
@@ -3646,13 +3917,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
        fidp->flags = fidflags;
 
-        /* save parent dir and pathname for deletion or change notification */
-        if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
-                fidp->flags |= SMB_FID_NTOPEN;
-                fidp->NTopen_dscp = dscp;
-                cm_HoldSCache(dscp);
-                fidp->NTopen_pathp = strdup(lastNamep);
-        }
+    /* save parent dir and pathname for deletion or change notification */
+    if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
+        fidp->flags |= SMB_FID_NTOPEN;
+        fidp->NTopen_dscp = dscp;
+        cm_HoldSCache(dscp);
+        fidp->NTopen_pathp = strdup(lastNamep);
+    }
        fidp->NTopen_wholepathp = realPathp;
 
        /* we don't need this any longer */
@@ -3663,53 +3934,107 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        /* set inp->fid so that later read calls in same msg can find fid */
        inp->fid = fidp->fid;
 
-       /* out parms */
-       parmOffset = 8*4 + 39;
-       parmOffset += 1;        /* pad to 4 */
-       dataOffset = parmOffset + 70;
+    /* check whether we are required to send an extended response */
+    if (!extendedRespRequired) {
+        /* out parms */
+        parmOffset = 8*4 + 39;
+        parmOffset += 1;       /* pad to 4 */
+        dataOffset = parmOffset + 70;
+
+        parmSlot = 1;
+        outp->oddByte = 1;
+        /* Total Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
+        /* Total Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
+        /* Parameter Offset */
+        smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+        /* Parameter Displacement */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Data Offset */
+        smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+        /* Data Displacement */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
+        smb_SetSMBDataLength(outp, 70);
 
-       parmSlot = 1;
-       outp->oddByte = 1;
-       /* Total Parameter Count */
-       smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
-       /* Total Data Count */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       /* Parameter Count */
-       smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
-       /* Parameter Offset */
-       smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
-       /* Parameter Displacement */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       /* Data Count */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       /* Data Offset */
-       smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
-       /* Data Displacement */
-       smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
-       smb_SetSMBParmByte(outp, parmSlot, 0);  /* Setup Count */
-       smb_SetSMBDataLength(outp, 70);
-
-       lock_ObtainMutex(&scp->mx);
-       outData = smb_GetSMBData(outp, NULL);
-       outData++;                      /* round to get to parmOffset */
-       *outData = 0; outData++;        /* oplock */
-       *outData = 0; outData++;        /* reserved */
-       *((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);
-       *((FILETIME *)outData) = ft; outData += 8;      /* creation time */
-       *((FILETIME *)outData) = ft; outData += 8;      /* last access time */
-       *((FILETIME *)outData) = ft; outData += 8;      /* last write time */
-       *((FILETIME *)outData) = ft; outData += 8;      /* change time */
-       *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
-       *((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) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
-                                outData += 2;  /* is a dir? */
-       lock_ReleaseMutex(&scp->mx);
+        lock_ObtainMutex(&scp->mx);
+        outData = smb_GetSMBData(outp, NULL);
+        outData++;                     /* round to get to parmOffset */
+        *outData = 0; outData++;       /* oplock */
+        *outData = 0; outData++;       /* reserved */
+        *((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);
+        *((FILETIME *)outData) = ft; outData += 8;     /* creation time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last access time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last write time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* change time */
+        *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
+        *((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) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
+        outData += 2;  /* is a dir? */
+        lock_ReleaseMutex(&scp->mx);
+    } else {
+        /* out parms */
+        parmOffset = 8*4 + 39;
+        parmOffset += 1;       /* pad to 4 */
+        dataOffset = parmOffset + 104;
+        
+        parmSlot = 1;
+        outp->oddByte = 1;
+        /* Total Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 101); parmSlot += 2;
+        /* Total Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Parameter Count */
+        smb_SetSMBParmLong(outp, parmSlot, 101); parmSlot += 2;
+        /* Parameter Offset */
+        smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+        /* Parameter Displacement */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Data Count */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        /* Data Offset */
+        smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+        /* Data Displacement */
+        smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
+        smb_SetSMBDataLength(outp, 105);
+        
+        lock_ObtainMutex(&scp->mx);
+        outData = smb_GetSMBData(outp, NULL);
+        outData++;                     /* round to get to parmOffset */
+        *outData = 0; outData++;       /* oplock */
+        *outData = 1; outData++;       /* response type */
+        *((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);
+        *((FILETIME *)outData) = ft; outData += 8;     /* creation time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last access time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* last write time */
+        *((FILETIME *)outData) = ft; outData += 8;     /* change time */
+        *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
+        *((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) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
+        outData += 1;  /* is a dir? */
+        memset(outData,0,24); outData += 24; /* Volume ID and file ID */
+        *((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
+        *((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
+        lock_ReleaseMutex(&scp->mx);
+    }
 
        osi_Log1(afsd_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
 
@@ -3717,6 +4042,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
 
        cm_ReleaseUser(userp);
 
+       /* free(realPathp); Can't free realPathp here because fidp->NTopen_wholepathp points there */
        /* leave scp held since we put it in fidp->scp */
        return 0;
 }
@@ -3732,31 +4058,34 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
        filter = smb_GetSMBParm(inp, 19)
                        | (smb_GetSMBParm(inp, 20) << 16);
        fid = smb_GetSMBParm(inp, 21);
-       watchtree = smb_GetSMBParm(inp, 22) && 0xffff;
+       watchtree = smb_GetSMBParm(inp, 22) && 0xffff;  /* TODO: should this be 0xff ? */
+
+    fidp = smb_FindFID(vcp, fid, 0);
+    if (!fidp) {
+        osi_Log1(afsd_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
+        return CM_ERROR_BADFD;
+    }
 
        savedPacketp = smb_CopyPacket(inp);
-       savedPacketp->vcp = vcp;
+       savedPacketp->vcp = vcp; /* TODO: refcount vcp? */
        lock_ObtainMutex(&smb_Dir_Watch_Lock);
        savedPacketp->nextp = smb_Directory_Watches;
        smb_Directory_Watches = savedPacketp;
        lock_ReleaseMutex(&smb_Dir_Watch_Lock);
 
-       fidp = smb_FindFID(vcp, fid, 0);
-                
-       osi_Log4(afsd_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d file %s",
-                filter, fid, watchtree, osi_LogSaveString(afsd_logp, fidp->NTopen_wholepathp));
+    osi_Log4(afsd_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d file %s",
+             filter, fid, watchtree, osi_LogSaveString(afsd_logp, fidp->NTopen_wholepathp));
 
-       scp = fidp->scp;
-       lock_ObtainMutex(&scp->mx);
-       if (watchtree)
-               scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
-       else
-               scp->flags |= CM_SCACHEFLAG_WATCHED;
-       lock_ReleaseMutex(&scp->mx);
-       smb_ReleaseFID(fidp);
+    scp = fidp->scp;
+    lock_ObtainMutex(&scp->mx);
+    if (watchtree)
+        scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
+    else
+        scp->flags |= CM_SCACHEFLAG_WATCHED;
+    lock_ReleaseMutex(&scp->mx);
+    smb_ReleaseFID(fidp);
 
        outp->flags |= SMB_PACKETFLAG_NOSEND;
-
        return 0;
 }
 
@@ -3902,7 +4231,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
                filter = smb_GetSMBParm(watch, 19)
                                | (smb_GetSMBParm(watch, 20) << 16);
                fid = smb_GetSMBParm(watch, 21);
-               wtree = smb_GetSMBParm(watch, 22) & 0xffff;
+               wtree = smb_GetSMBParm(watch, 22) & 0xffff;  /* TODO: should this be 0xff ? */
                maxLen = smb_GetSMBOffsetParm(watch, 5, 1)
                                | (smb_GetSMBOffsetParm(watch, 6, 1) << 16);
                vcp = watch->vcp;
@@ -3915,6 +4244,11 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
                        filter = 0x17;
 
                fidp = smb_FindFID(vcp, fid, 0);
+        if (!fidp) {
+               lastWatch = watch;
+               watch = watch->nextp;
+               continue;
+        }
                if (fidp->scp != dscp
                    || (filter & notifyFilter) == 0
                    || (!isDirectParent && !wtree)) {
@@ -4064,19 +4398,22 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        watchtree = smb_GetSMBParm(watch, 22) & 0xffff;
 
                        fidp = smb_FindFID(vcp, fid, 0);
-                        
-                        osi_Log3(afsd_logp, "Cancelling change notification for fid %d wtree %d file %s", 
-                                fid, watchtree,
-                                osi_LogSaveString(afsd_logp, fidp->NTopen_wholepathp));
-
-                       scp = fidp->scp;
-                       lock_ObtainMutex(&scp->mx);
-                       if (watchtree)
-                               scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
-                       else
-                               scp->flags &= ~CM_SCACHEFLAG_WATCHED;
-                       lock_ReleaseMutex(&scp->mx);
-                       smb_ReleaseFID(fidp);
+            if (fidp) {
+                osi_Log3(afsd_logp, "Cancelling change notification for fid %d wtree %d file %s", 
+                         fid, watchtree,
+                         osi_LogSaveString(afsd_logp, (fidp)?fidp->NTopen_wholepathp:""));
+
+                scp = fidp->scp;
+                lock_ObtainMutex(&scp->mx);
+                if (watchtree)
+                    scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
+                else
+                    scp->flags &= ~CM_SCACHEFLAG_WATCHED;
+                lock_ReleaseMutex(&scp->mx);
+                smb_ReleaseFID(fidp);
+            } else {
+                osi_Log2(afsd_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
+            }
 
                        /* assume STATUS32; return 0xC0000120 (CANCELED) */
                        replyWctp = watch->wctp;
@@ -4104,3 +4441,21 @@ void smb3_Init()
 {
        lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock");
 }
+
+cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine)
+{
+    /*int newUid;*/
+    smb_username_t *unp;
+
+    unp = smb_FindUserByName(usern, machine, SMB_FLAG_CREATE);
+    if (!unp->userp) {
+        lock_ObtainMutex(&unp->mx);
+        unp->userp = cm_NewUser();
+        lock_ReleaseMutex(&unp->mx);
+               osi_LogEvent("AFS smb_FindCMUserByName : New User",NULL,"name[%s] machine[%s]",usern,machine);
+    }  else    {
+               osi_LogEvent("AFS smb_FindCMUserByName : Found",NULL,"name[%s] machine[%s]",usern,machine);
+       }
+    return unp->userp;
+}
+