DEVEL15-windows-largefile-support-20060623
[openafs.git] / src / WINNT / afsd / smb3.c
index 149c740..fc2b955 100644 (file)
@@ -49,14 +49,10 @@ cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp)
     cm_user_t *up = NULL;
         
     uidp = smb_FindUID(vcp, inp->uid, 0);
-    if (!uidp) return NULL;
+    if (!uidp) 
+       return NULL;
         
-    lock_ObtainMutex(&uidp->mx);
-    if (uidp->unp) {
-        up = uidp->unp->userp;
-        cm_HoldUser(up);
-    }
-    lock_ReleaseMutex(&uidp->mx);
+    up = smb_GetUserFromUID(uidp);
 
     smb_ReleaseUID(uidp);
 
@@ -138,7 +134,7 @@ void OutputDebugF(char * format, ...) {
 }
 
 void OutputDebugHexDump(unsigned char * buffer, int len) {
-    int i,j,k;
+    int i,j,k,pcts=0;
     char buf[256];
     static char tr[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
 
@@ -163,9 +159,13 @@ void OutputDebugHexDump(unsigned char * buffer, int len) {
         buf[j] = tr[k / 16]; buf[j+1] = tr[k % 16];
 
         j = (i%16);
-        j = j + 56 + ((j>7)?1:0);
+        j = j + 56 + ((j>7)?1:0) + pcts;
 
         buf[j] = (k>32 && k<127)?k:'.';
+               if (k == '%') {
+                       buf[++j] = k;
+                       pcts++;
+               }
     }    
     if(i) {
         osi_Log0(smb_logp, osi_LogSaveString(smb_logp, buf));
@@ -531,19 +531,19 @@ long smb_AuthenticateUserLM(smb_vc_t *vcp, char * accountName, char * primaryDom
        
     lmAuth.lmlogon.LogonDomainName.Buffer = lmAuth.primaryDomainW;
     mbstowcs(lmAuth.primaryDomainW, primaryDomain, P_LEN);
-    lmAuth.lmlogon.LogonDomainName.Length = wcslen(lmAuth.primaryDomainW) * sizeof(WCHAR);
+    lmAuth.lmlogon.LogonDomainName.Length = (USHORT)(wcslen(lmAuth.primaryDomainW) * sizeof(WCHAR));
     lmAuth.lmlogon.LogonDomainName.MaximumLength = P_LEN * sizeof(WCHAR);
 
     lmAuth.lmlogon.UserName.Buffer = lmAuth.accountNameW;
     mbstowcs(lmAuth.accountNameW, accountName, P_LEN);
-    lmAuth.lmlogon.UserName.Length = wcslen(lmAuth.accountNameW) * sizeof(WCHAR);
+    lmAuth.lmlogon.UserName.Length = (USHORT)(wcslen(lmAuth.accountNameW) * sizeof(WCHAR));
     lmAuth.lmlogon.UserName.MaximumLength = P_LEN * sizeof(WCHAR);
 
     lmAuth.lmlogon.Workstation.Buffer = lmAuth.workstationW;
     lmAuth.lmlogon.Workstation.MaximumLength = (MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR);
     size = MAX_COMPUTERNAME_LENGTH + 1;
     GetComputerNameW(lmAuth.workstationW, &size);
-    lmAuth.lmlogon.Workstation.Length = wcslen(lmAuth.workstationW) * sizeof(WCHAR);
+    lmAuth.lmlogon.Workstation.Length = (USHORT)(wcslen(lmAuth.workstationW) * sizeof(WCHAR));
 
     memcpy(lmAuth.lmlogon.ChallengeToClient, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
 
@@ -563,8 +563,8 @@ long smb_AuthenticateUserLM(smb_vc_t *vcp, char * accountName, char * primaryDom
     lmAuth.tgroups.Groups[0].Sid = NULL;
     lmAuth.tgroups.Groups[0].Attributes = 0;
 
-    lmAuth.tsource.SourceIdentifier.HighPart = 0;
-    lmAuth.tsource.SourceIdentifier.LowPart = (DWORD) vcp;
+    lmAuth.tsource.SourceIdentifier.HighPart = (DWORD)((LONG_PTR)vcp << 32);
+    lmAuth.tsource.SourceIdentifier.LowPart = (DWORD)((LONG_PTR)vcp & _UI32_MAX);
     strcpy(lmAuth.tsource.SourceName,"OpenAFS"); /* 8 char limit */
 
     nts = LsaLogonUser( smb_lsaHandle,
@@ -661,7 +661,6 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     smb_user_t *uidp;
     unsigned short newUid;
     unsigned long caps = 0;
-    cm_user_t *userp;
     smb_username_t *unp;
     char *s1 = " ";
     long code = 0; 
@@ -841,21 +840,31 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     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,osi_LogSaveString(smb_logp, usern));
-        osi_Log3(smb_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid);
+        newUid = uidp->userID;
+        osi_Log3(smb_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 */
+       cm_user_t *userp;
+
+       /* do a global search for the username/machine name pair */
         unp = smb_FindUserByName(usern, vcp->rname, SMB_FLAG_CREATE);
+       lock_ObtainMutex(&unp->mx);
+       if (unp->flags & SMB_USERNAMEFLAG_AFSLOGON) {
+           /* clear the afslogon flag so that the tickets can now 
+            * be freed when the refCount returns to zero.
+            */
+           unp->flags &= ~SMB_USERNAMEFLAG_AFSLOGON;
+       }
+       lock_ReleaseMutex(&unp->mx);
 
         /* Create a new UID and cm_user_t structure */
         userp = unp->userp;
         if (!userp)
             userp = cm_NewUser();
-        lock_ObtainMutex(&vcp->mx);
+       cm_HoldUserVCRef(userp);
+       lock_ObtainMutex(&vcp->mx);
         if (!vcp->uidCounter)
             vcp->uidCounter++; /* handle unlikely wraparounds */
         newUid = (strlen(usern)==0)?0:vcp->uidCounter++;
@@ -869,8 +878,7 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
         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,osi_LogSaveString(smb_logp, usern));
-        osi_Log4(smb_logp,"smb_ReceiveV3SessionSetupX MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d]",vcp,vcp->lana,vcp->lsn,newUid);
+        osi_Log4(smb_logp,"smb_ReceiveV3SessionSetupX MakeNewUser:VCP[%p],Lana[%d],lsn[%d],userid[%d]",vcp,vcp->lana,vcp->lsn,newUid);
         lock_ReleaseMutex(&uidp->mx);
         smb_ReleaseUID(uidp);
     }
@@ -926,31 +934,38 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 {
     smb_user_t *uidp;
 
-    /* don't get tokens from this VC */
-    vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
-
-    inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
-
     /* find the tree and free it */
     uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
-    /* TODO: smb_ReleaseUID() ? */
     if (uidp) {
-        char *s1 = NULL, *s2 = NULL;
+       smb_username_t * unp;
 
-        if (s2 == NULL) s2 = " ";
-        if (s1 == NULL) {s1 = s2; s2 = " ";}
-
-        osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID,
-                  osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), 
-                  osi_LogSaveString(smb_logp,s1), osi_LogSaveString(smb_logp,s2));
+        osi_Log2(smb_logp, "SMB3 user logoffX uid %d name %s", uidp->userID,
+                  osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "));
 
         lock_ObtainMutex(&uidp->mx);
         uidp->flags |= SMB_USERFLAG_DELETE;
-        /*
+       /*
          * it doesn't get deleted right away
          * because the vcp points to it
          */
+       unp = uidp->unp;
         lock_ReleaseMutex(&uidp->mx);
+
+#ifdef COMMENT
+       /* we can't do this.  we get logoff messages prior to a session
+        * disconnect even though it doesn't mean the user is logging out.
+        * we need to create a new pioctl and EventLogoff handler to set
+        * SMB_USERNAMEFLAG_LOGOFF.
+        */
+       if (unp && smb_LogoffTokenTransfer) {
+           lock_ObtainMutex(&unp->mx);
+           unp->flags |= SMB_USERNAMEFLAG_LOGOFF;
+           unp->last_logoff_t = osi_Time() + smb_LogoffTransferTimeout;
+           lock_ReleaseMutex(&unp->mx);
+       }
+#endif
+
+       smb_ReleaseUID(uidp);
     }
     else    
         osi_Log0(smb_logp, "SMB3 user logoffX");
@@ -1006,7 +1021,8 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
 #endif
     }
 
-    userp = smb_GetUser(vcp, inp);
+    uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+    userp = smb_GetUserFromUID(uidp);
 
     lock_ObtainMutex(&vcp->mx);
     newTid = vcp->tidCounter++;
@@ -1015,11 +1031,11 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
     tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
 
     if (!ipc) {
-        uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+       if (!strcmp(shareName, "*."))
+           strcpy(shareName, "all");
        shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
-        if (uidp)
-            smb_ReleaseUID(uidp);
        if (!shareFound) {
+           smb_ReleaseUID(uidp);
             smb_ReleaseTID(tidp);
             return CM_ERROR_BADSHARENAME;
        }
@@ -1037,6 +1053,7 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
         smb_SetSMBParm(outp, 2, 0);
         sharePath = NULL;
     }
+    smb_ReleaseUID(uidp);
 
     lock_ObtainMutex(&tidp->mx);
     tidp->userp = userp;
@@ -1128,7 +1145,8 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
         
     tp = malloc(sizeof(*tp));
     memset(tp, 0, sizeof(*tp));
-    tp->vcp = NULL;
+    smb_HoldVC(vcp);
+    tp->vcp = vcp;
     tp->curData = tp->curParms = 0;
     tp->totalData = totalData;
     tp->totalParms = totalParms;
@@ -1159,11 +1177,13 @@ smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
     return tp;
 }       
 
-/* free a tran2 packet; must be called with smb_globalLock held */
+/* free a tran2 packet */
 void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
 {
-    if (t2p->vcp) 
+    if (t2p->vcp) {
         smb_ReleaseVC(t2p->vcp);
+       t2p->vcp = NULL;
+    }
     if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
         if (t2p->parmsp)
             free(t2p->parmsp);
@@ -1292,19 +1312,9 @@ long smb_ReceiveV3Trans(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) {
+        osi_Log0(smb_logp, "Transaction2 word count = 0"); 
 #ifndef DJGPP
-        HANDLE h;
-        char *ptbuf[1];
-
-        osi_Log0(smb_logp, "TRANSACTION word count = 0"); 
-
-        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-        ptbuf[0] = "Transaction2 word count = 0";
-        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
-                    1, inp->ncb_length, ptbuf, inp);
-        DeregisterEventSource(h);
-#else /* DJGPP */
-        osi_Log0(smb_logp, "TRANSACTION word count = 0"); 
+       LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_ZERO_TRANSACTION_COUNT);
 #endif /* !DJGPP */
 
         smb_SetSMBDataLength(outp, 0);
@@ -1377,13 +1387,12 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         rapOp = asp->parmsp[0];
 
         if ( rapOp >= 0 && rapOp < SMB_RAP_NOPCODES && smb_rapDispatchTable[rapOp].procp) {
-            osi_LogEvent("AFS-Dispatch-RAP[%s]",myCrt_RapDispatch(rapOp),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
-            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%x] lana[%d] lsn[%d]",myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP %s vcp[%p] lana[%d] lsn[%d]",myCrt_RapDispatch(rapOp),vcp,vcp->lana,vcp->lsn);
             code = (*smb_rapDispatchTable[rapOp].procp)(vcp, asp, outp);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP return  code 0x%x vcp[%x] lana[%d] lsn[%d]",code,vcp,vcp->lana,vcp->lsn);
         }
         else {
-            osi_LogEvent("AFS-Dispatch-RAP [invalid]", NULL, "op[%x] vcp[%x] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
-            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%x] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-RAP [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]", rapOp, vcp, vcp->lana, vcp->lsn);
             code = CM_ERROR_BADOP;
         }
 
@@ -1397,9 +1406,7 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         }
 
         /* free the input tran 2 packet */
-        lock_ObtainWrite(&smb_globalLock);
         smb_FreeTran2Packet(asp);
-        lock_ReleaseWrite(&smb_globalLock);
     }
     else if (firstPacket) {
         /* the first packet in a multi-packet request, we need to send an
@@ -1480,10 +1487,10 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
     int outDataTotal;  /* total data bytes */
     int code = 0;
     DWORD rv;
-    DWORD allSubmount;
-    USHORT nShares;
-    DWORD nRegShares;
-    DWORD nSharesRet;
+    DWORD allSubmount = 0;
+    USHORT nShares = 0;
+    DWORD nRegShares = 0;
+    DWORD nSharesRet = 0;
     HKEY hkParam;
     HKEY hkSubmount = NULL;
     smb_rap_share_info_1_t * shares;
@@ -1549,7 +1556,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
 
     cm_ReleaseUser(userp);
 
-    nShares = rootShares.cShare + nRegShares + allSubmount;
+    nShares = (USHORT)(rootShares.cShare + nRegShares + allSubmount);
 
 #define REMARK_LEN 1
     outParmsTotal = 8; /* 4 dwords */
@@ -1572,7 +1579,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
 
     if (allSubmount) {
         strcpy( shares[cshare].shi1_netname, "all" );
-        shares[cshare].shi1_remark = cstrp - outp->datap;
+        shares[cshare].shi1_remark = (DWORD)(cstrp - outp->datap);
         /* type and pad are zero already */
         cshare++;
         cstrp+=REMARK_LEN;
@@ -1585,7 +1592,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
             if (rv == ERROR_SUCCESS && strlen(thisShare) && (!allSubmount || stricmp(thisShare,"all"))) {
                 strncpy(shares[cshare].shi1_netname, thisShare, sizeof(shares->shi1_netname)-1);
                 shares[cshare].shi1_netname[sizeof(shares->shi1_netname)-1] = 0; /* unfortunate truncation */
-                shares[cshare].shi1_remark = cstrp - outp->datap;
+                shares[cshare].shi1_remark = (DWORD)(cstrp - outp->datap);
                 cshare++;
                 cstrp+=REMARK_LEN;
             }
@@ -1610,7 +1617,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
         }
 
         strcpy(shares[cshare].shi1_netname, rootShares.shares[i].shi0_netname);
-        shares[cshare].shi1_remark = cstrp - outp->datap;
+        shares[cshare].shi1_remark = (DWORD)(cstrp - outp->datap);
         cshare++;
         cstrp+=REMARK_LEN;
     }
@@ -1620,7 +1627,7 @@ long smb_ReceiveRAPNetShareEnum(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_
     outp->parmsp[2] = cshare;
     outp->parmsp[3] = nShares;
 
-    outp->totalData = cstrp - outp->datap;
+    outp->totalData = (int)(cstrp - outp->datap);
     outp->totalParms = outParmsTotal;
 
     smb_SendTran2Packet(vcp, outp, op);
@@ -1668,7 +1675,7 @@ long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack
 
     outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParam, totalData);
 
-    if(!stricmp(shareName,"all")) {
+    if(!stricmp(shareName,"all") || !strcmp(shareName,"*.")) {
         rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
                           KEY_QUERY_VALUE, &hkParam);
         if (rv == ERROR_SUCCESS) {
@@ -1715,16 +1722,16 @@ long smb_ReceiveRAPNetShareGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack
         smb_rap_share_info_1_t * info = (smb_rap_share_info_1_t *) outp->datap;
         strncpy(info->shi1_netname, shareName, sizeof(info->shi1_netname)-1);
         info->shi1_netname[sizeof(info->shi1_netname)-1] = 0;
-        info->shi1_remark = ((unsigned char *) (info + 1)) - outp->datap;
+        info->shi1_remark = (DWORD)(((unsigned char *) (info + 1)) - outp->datap);
         /* type and pad are already zero */
     } else { /* infoLevel==2 */
         smb_rap_share_info_2_t * info = (smb_rap_share_info_2_t *) outp->datap;
         strncpy(info->shi2_netname, shareName, sizeof(info->shi2_netname)-1);
         info->shi2_netname[sizeof(info->shi2_netname)-1] = 0;
-        info->shi2_remark = ((unsigned char *) (info + 1)) - outp->datap;
+        info->shi2_remark = (DWORD)(((unsigned char *) (info + 1)) - outp->datap);
         info->shi2_permissions = ACCESS_ALL;
         info->shi2_max_uses = (unsigned short) -1;
-        info->shi2_path = 1 + (((unsigned char *) (info + 1)) - outp->datap);
+        info->shi2_path = (DWORD)(1 + (((unsigned char *) (info + 1)) - outp->datap));
     }
 
     outp->totalData = totalData;
@@ -1904,7 +1911,7 @@ long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pac
         cstrp += smb_ServerCommentLen;
     }
 
-    totalData = cstrp - outp->datap;
+    totalData = (DWORD)(cstrp - outp->datap);
     outp->totalData = min(bufsize,totalData); /* actual data size */
     outp->parmsp[0] = (outp->totalData == totalData)? 0 : ERROR_MORE_DATA;
     outp->parmsp[2] = totalData;
@@ -1932,19 +1939,9 @@ 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) {
+        osi_Log0(smb_logp, "Transaction2 word count = 0"); 
 #ifndef DJGPP
-        HANDLE h;
-        char *ptbuf[1];
-
-        osi_Log0(smb_logp, "TRANSACTION2 word count = 0"); 
-
-        h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME);
-        ptbuf[0] = "Transaction2 word count = 0";
-        ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
-                    1, inp->ncb_length, ptbuf, inp);
-        DeregisterEventSource(h);
-#else /* DJGPP */
-        osi_Log0(smb_logp, "TRANSACTION2 word count = 0"); 
+       LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_ZERO_TRANSACTION_COUNT);
 #endif /* !DJGPP */
 
         smb_SetSMBDataLength(outp, 0);
@@ -2015,13 +2012,11 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         /* 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(smb_logp,"AFS Server - Dispatch-2 %s vcp[%x] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-2 %s vcp[%p] 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(smb_logp,"AFS Server - Dispatch-2 [INVALID] op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+            osi_Log4(smb_logp,"AFS Server - Dispatch-2 [INVALID] op[%x] vcp[%p] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
             code = CM_ERROR_BADOP;
         }
 
@@ -2035,9 +2030,7 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         }
 
         /* free the input tran 2 packet */
-        lock_ObtainWrite(&smb_globalLock);
         smb_FreeTran2Packet(asp);
-        lock_ReleaseWrite(&smb_globalLock);
     }
     else if (firstPacket) {
         /* the first packet in a multi-packet request, we need to send an
@@ -2075,6 +2068,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     long returnEALength;
     char *tidPathp;
     cm_req_t req;
+    int created = 0;
 
     cm_InitReq(&req);
 
@@ -2293,11 +2287,13 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime);
         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) {
+        if (code == 0) {
+           created = 1;
+           if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+               smb_NotifyChange(FILE_ACTION_ADDED,
+                                FILE_NOTIFY_CHANGE_FILE_NAME,  
+                                 dscp, lastNamep, NULL, TRUE);
+       } else 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
@@ -2360,14 +2356,25 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
        
+    cm_HoldUser(userp);
+    lock_ObtainMutex(&fidp->mx);
     /* save a pointer to the vnode */
     fidp->scp = scp;
+    /* and the user */
+    fidp->userp = userp;
         
     /* compute open mode */
-    if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD;
+    if (openMode != 1) 
+       fidp->flags |= SMB_FID_OPENREAD;
     if (openMode == 1 || openMode == 2)
         fidp->flags |= SMB_FID_OPENWRITE;
 
+    /* remember that the file was newly created */
+    if (created)
+       fidp->flags |= SMB_FID_CREATED;
+
+    lock_ReleaseMutex(&fidp->mx);
+
     smb_ReleaseFID(fidp);
         
     cm_Open(scp, 0, userp);
@@ -2435,13 +2442,15 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
     switch (p->parmsp[0]) {
     case 1: responseSize = sizeof(qi.u.allocInfo); break;
     case 2: responseSize = sizeof(qi.u.volumeInfo); break;
+       break;
     case 0x102: responseSize = sizeof(qi.u.FSvolumeInfo); break;
     case 0x103: responseSize = sizeof(qi.u.FSsizeInfo); break;
     case 0x104: responseSize = sizeof(qi.u.FSdeviceInfo); break;
     case 0x105: responseSize = sizeof(qi.u.FSattributeInfo); break;
     case 0x200: /* CIFS Unix Info */
     case 0x301: /* Mac FS Info */
-    default: return CM_ERROR_INVAL;
+    default: 
+       return CM_ERROR_INVAL;
     }
 
     outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, responseSize);
@@ -2615,6 +2624,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     cm_scache_t *scp, *dscp;
     long code = 0;
     char *op;
+    char *pathp;
     char *tidPathp;
     char *lastComp;
     cm_req_t req;
@@ -2642,8 +2652,12 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_INVAL);
         return 0;
     }
+
+    pathp = (char *)(&p->parmsp[3]);
+    if (smb_StoreAnsiFilenames)
+       OemToChar(pathp,pathp);
     osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path %s", infoLevel,
-              osi_LogSaveString(smb_logp, (char *)(&p->parmsp[3])));
+              osi_LogSaveString(smb_logp, pathp));
 
     outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, nbytesRequired);
 
@@ -2694,8 +2708,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
      */
     if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         spacep = cm_GetSpace();
-        smb_StripLastComponent(spacep->data, &lastComp,
-                                (char *)(&p->parmsp[3]));
+        smb_StripLastComponent(spacep->data, &lastComp, pathp);
 #ifndef SPECIAL_FOLDERS
         /* Make sure that lastComp is not NULL */
         if (lastComp) {
@@ -2740,7 +2753,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     }
 
     /* now do namei and stat, and copy out the info */
-    code = cm_NameI(cm_data.rootSCachep, (char *)(&p->parmsp[3]),
+    code = cm_NameI(cm_data.rootSCachep, pathp,
                      CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
 
     if (code) {
@@ -2775,7 +2788,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     op = outp->datap;
     /* for info level 108, figure out short name */
     if (infoLevel == 0x108) {
-        code = cm_GetShortName((char *)(&p->parmsp[3]), userp, &req,
+        code = cm_GetShortName(pathp, userp, &req,
                                 tidPathp, scp->fid.vnode, shortName,
                                 (size_t *) &len);
         if (code) {
@@ -2812,10 +2825,12 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
         *((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */
         *((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
-        *((u_long *)op) = scp->linkCount; op += 4;
-        *op++ = 0;
+        *((u_long *)op) = scp->linkCount; op += 4;     /* Link count */
+        *op++ = 0;                                     /* Delete Pending */
+        *op++ = ((scp->fileType == CM_SCACHETYPE_DIRECTORY || 
+                 scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+                 scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
         *op++ = 0;
-        *op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0);
         *op++ = 0;
     }
     else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
@@ -2856,6 +2871,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     unsigned short infoLevel;
     int nbytesRequired;
     unsigned short fid;
+    int delonclose = 0;
     cm_user_t *userp;
     smb_fid_t *fidp;
     cm_scache_t *scp;
@@ -2906,7 +2922,11 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        goto done;
     }   
 
+    lock_ObtainMutex(&fidp->mx);
+    delonclose = fidp->flags & SMB_FID_DELONCLOSE;
     scp = fidp->scp;
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
     lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -2930,9 +2950,11 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
         *((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */
         *((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
-        *((u_long *)op) = scp->linkCount; op += 4;
-        *op++ = ((fidp->flags & SMB_FID_DELONCLOSE) ? 1 : 0);
-        *op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0);
+        *((u_long *)op) = scp->linkCount; op += 4;     /* Link count */
+        *op++ = (delonclose ? 1 : 0);                  /* Delete Pending */
+        *op++ = ((scp->fileType == CM_SCACHETYPE_DIRECTORY || 
+                 scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+                 scp->fileType == CM_SCACHETYPE_INVALID)? 1 : 0);
         *op++ = 0;
         *op++ = 0;
     }
@@ -2943,11 +2965,15 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         unsigned long len;
         char *name;
 
+       lock_ReleaseMutex(&scp->mx);
+       lock_ObtainMutex(&fidp->mx);
+       lock_ObtainMutex(&scp->mx);
         if (fidp->NTopen_wholepathp)
             name = fidp->NTopen_wholepathp;
         else
             name = "\\";       /* probably can't happen */
-        len = strlen(name);
+       lock_ReleaseMutex(&fidp->mx);
+        len = (unsigned long)strlen(name);
         outp->totalData = (len*2) + 4; /* this is actually what we want to return */
         *((u_long *)op) = len * 2; op += 4;
         mbstowcs((unsigned short *)op, name, len); op += (len * 2);
@@ -2956,6 +2982,7 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     /* send and free the packets */
   done:
     lock_ReleaseMutex(&scp->mx);
+    cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
     if (code == 0) 
@@ -2989,7 +3016,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     }
 
     infoLevel = p->parmsp[1];
-    osi_Log2(smb_logp,"ReceiveTran2SetFileInfo type=[%x] fid=[%x]", infoLevel, fid);
+    osi_Log2(smb_logp,"ReceiveTran2SetFileInfo type 0x%x fid %d", infoLevel, fid);
     if (infoLevel > 0x104 || infoLevel < 0x101) {
         osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
@@ -2998,18 +3025,25 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         return 0;
     }
 
+    lock_ObtainMutex(&fidp->mx);
     if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO && !(fidp->flags & SMB_FID_OPENDELETE)) {
-        smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
+       lock_ReleaseMutex(&fidp->mx);
         smb_ReleaseFID(fidp);
+        smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
         return 0;
     }
     if ((infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO)
          && !(fidp->flags & SMB_FID_OPENWRITE)) {
-        smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
+       lock_ReleaseMutex(&fidp->mx);
         smb_ReleaseFID(fidp);
+        smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
         return 0;
     }
 
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
+
     osi_Log1(smb_logp, "T2 SFileInfo type 0x%x", infoLevel);
 
     outp = smb_GetTran2ResponsePacket(vcp, p, op, 2, 0);
@@ -3024,8 +3058,6 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
        goto done;
     }   
 
-    scp = fidp->scp;
-
     if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         FILETIME lastMod;
         unsigned int attribute;
@@ -3038,11 +3070,14 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         code = cm_SyncOp(scp, NULL, userp, &req, 0,
                           CM_SCACHESYNC_GETSTATUS
                          | CM_SCACHESYNC_NEEDCALLBACK);
+       lock_ReleaseMutex(&scp->mx);
         if (code) {
-            lock_ReleaseMutex(&scp->mx);
             goto done;
         }
 
+       lock_ObtainMutex(&fidp->mx);
+       lock_ObtainMutex(&scp->mx);
+
         /* prepare for setattr call */
         attr.mask = 0;
 
@@ -3074,6 +3109,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
             }
         }
         lock_ReleaseMutex(&scp->mx);
+       lock_ReleaseMutex(&fidp->mx);
 
         /* call setattr */
         if (attr.mask)
@@ -3094,16 +3130,22 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
         if (*((char *)(p->datap))) {
             code = cm_CheckNTDelete(fidp->NTopen_dscp, scp, userp,
                                      &req);
-            if (code == 0)          
+            if (code == 0) {
+               lock_ObtainMutex(&fidp->mx);
                 fidp->flags |= SMB_FID_DELONCLOSE;
-        }               
+               lock_ReleaseMutex(&fidp->mx);
+           }
+       }               
         else {  
             code = 0;
+           lock_ObtainMutex(&fidp->mx);
             fidp->flags &= ~SMB_FID_DELONCLOSE;
+           lock_ReleaseMutex(&fidp->mx);
         }
     }       
 
   done:
+    cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
     if (code == 0) 
@@ -3208,7 +3250,8 @@ smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         requestFileName[0] == '\\' &&
         !_strnicmp(cm_NetbiosName,&requestFileName[1],nbnLen) &&
         requestFileName[nbnLen+1] == '\\' &&
-        !_strnicmp("all",&requestFileName[nbnLen+2],3)) 
+        (!_strnicmp("all",&requestFileName[nbnLen+2],3) || 
+         !_strnicmp("*.",&requestFileName[nbnLen+2],2)))
     {
         USHORT * sp;
         struct smb_v2_referral * v2ref;
@@ -3557,9 +3600,10 @@ szWildCardMatchFileName(PSZ pattern, PSZ name, int casefold)
     while (*name) {
         switch (*pattern) {
         case '?':
-            if (*name == '.') 
-                return FALSE;
-            ++pattern, ++name;
+           ++pattern;
+            if (*name == '.')
+               continue;
+            ++name;
             break;
          case '*':
             ++pattern;
@@ -3581,10 +3625,12 @@ szWildCardMatchFileName(PSZ pattern, PSZ name, int casefold)
         } /* endswitch */
     } /* endwhile */ 
 
-    if (*pattern == '\0' || *pattern == '*' && *(pattern+1) == '\0')
-        return TRUE;
-    else 
-        return FALSE;
+    /* if all we have left are wildcards, then we match */
+    for (;*pattern; pattern++) {
+       if (*pattern != '*' && *pattern != '?')
+           return FALSE;
+    }
+    return TRUE;
 }
 
 /* do a case-folding search of the star name mask with the name in namep.
@@ -4094,7 +4140,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
                     LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
                     /* Don't bulk stat if risking timeout */
-                    int now = GetCurrentTime();
+                    int now = GetTickCount();
                     if (now - req.startTime > 5000) {
                         scp->bulkStatProgress = thyper;
                         scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
@@ -4296,7 +4342,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                     strcpy(op + 70, shortName);
                     if (smb_StoreAnsiFilenames)
                         CharToOem(op + 70, op + 70);
-                    *(op + 68) = shortNameEnd - shortName;
+                    *(op + 68) = (char)(shortNameEnd - shortName);
                 }
             }
 
@@ -4506,6 +4552,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     int parmSlot;                      /* which parm we're dealing with */
     char *tidPathp;
     cm_req_t req;
+    int created = 0;
 
     cm_InitReq(&req);
 
@@ -4581,7 +4628,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        free(hexp);
     }
 #endif
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     dscp = NULL;
     code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
@@ -4623,7 +4670,6 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 return CM_ERROR_BADSHARENAME;
         }
 #endif /* DFS_SUPPORT */
-
         /* otherwise, scp points to the parent directory.  Do a lookup,
          * and truncate the file if we find it, otherwise we create the
          * file.
@@ -4688,11 +4734,13 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         smb_UnixTimeFromDosUTime(&setAttr.clientModTime, dosTime);
         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) {
+        if (code == 0) {
+           created = 1;
+           if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+               smb_NotifyChange(FILE_ACTION_ADDED,
+                                FILE_NOTIFY_CHANGE_FILE_NAME,
+                                dscp, lastNamep, NULL, TRUE);
+       } else 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
@@ -4735,8 +4783,12 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
        
+    cm_HoldUser(userp);
+    lock_ObtainMutex(&fidp->mx);
     /* save a pointer to the vnode */
     fidp->scp = scp;
+    /* also the user */
+    fidp->userp = userp;
         
     /* compute open mode */
     if (openMode != 1) 
@@ -4744,6 +4796,11 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (openMode == 1 || openMode == 2)
         fidp->flags |= SMB_FID_OPENWRITE;
 
+    /* remember if the file was newly created */
+    if (created)
+       fidp->flags |= SMB_FID_CREATED;
+
+    lock_ReleaseMutex(&fidp->mx);
     smb_ReleaseFID(fidp);
         
     cm_Open(scp, 0, userp);
@@ -4834,16 +4891,25 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fid = smb_ChainFID(fid, inp);
 
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+    if (!fidp)
+       return CM_ERROR_BADFD;
+    
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_IOCTL) {
         osi_Log0(smb_logp, "smb_ReceiveV3Locking BadFD");
+       lock_ReleaseMutex(&fidp->mx);
+       smb_ReleaseFID(fidp);
         return CM_ERROR_BADFD;
     }
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
+
     /* set inp->fid so that later read calls in same msg can find fid */
     inp->fid = fid;
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
-    scp = fidp->scp;
 
     lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
@@ -4966,8 +5032,8 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             osi_QAdd((osi_queue_t **) &wlRequest->locks,
                      &wLock->q);
 
-            osi_Log1(smb_logp, "smb_ReceiveV3Locking WaitingLock created 0x%x",
-                     (long) wLock);
+            osi_Log1(smb_logp, "smb_ReceiveV3Locking WaitingLock created 0x%p",
+                     wLock);
 
             code = 0;
             continue;
@@ -5027,7 +5093,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             lock_ObtainWrite(&smb_globalLock);
             osi_QAdd((osi_queue_t **)&smb_allWaitingLocks,
                      &wlRequest->q);
-            osi_Wakeup((long) &smb_allWaitingLocks);
+            osi_Wakeup((LONG_PTR)&smb_allWaitingLocks);
             lock_ReleaseWrite(&smb_globalLock);
 
             /* don't send reply immediately */
@@ -5042,6 +5108,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
   doneSync:
     lock_ReleaseMutex(&scp->mx);
+    cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
 
@@ -5064,19 +5131,28 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     fid = smb_ChainFID(fid, inp);
         
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+    if (!fidp)
+       return CM_ERROR_BADFD;
+    
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_IOCTL) {
+       lock_ReleaseMutex(&fidp->mx);
+       smb_ReleaseFID(fidp);
         return CM_ERROR_BADFD;
     }
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
         
-    scp = fidp->scp;
         
     /* otherwise, stat the file */
     lock_ObtainMutex(&scp->mx);
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-    if (code) goto done;
+    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
@@ -5105,6 +5181,7 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
 
   done:
     lock_ReleaseMutex(&scp->mx);
+    cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
     return code;
@@ -5128,13 +5205,21 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     fid = smb_ChainFID(fid, inp);
         
     fidp = smb_FindFID(vcp, fid, 0);
-    if (!fidp || (fidp->flags & SMB_FID_IOCTL)) {
+    if (!fidp)
+       return CM_ERROR_BADFD;
+    
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_IOCTL) {
+       lock_ReleaseMutex(&fidp->mx);
+       smb_ReleaseFID(fidp);
         return CM_ERROR_BADFD;
     }
+    scp = fidp->scp;
+    cm_HoldSCache(scp);
+    lock_ReleaseMutex(&fidp->mx);
         
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
         
-    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
@@ -5155,13 +5240,146 @@ long smb_ReceiveV3SetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
             osi_Log1(smb_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
         }
     }
-    else code = 0;
+    else 
+       code = 0;
 
+    cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
     return code;
 }
 
+long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
+{
+    osi_hyper_t offset;
+    long count, written = 0, total_written = 0;
+    unsigned short fd;
+    unsigned pid;
+    smb_fid_t *fidp;
+    long code = 0;
+    cm_user_t *userp;
+    cm_attr_t truncAttr;       /* attribute struct used for truncating file */
+    char *op;
+    int inDataBlockCount;
+
+    fd = smb_GetSMBParm(inp, 2);
+    count = smb_GetSMBParm(inp, 10);
+
+    offset.HighPart = 0;
+    offset.LowPart = smb_GetSMBParm(inp, 3) | (smb_GetSMBParm(inp, 4) << 16);
+
+    if (*inp->wctp == 14) {
+        /* we have a request with 64-bit file offsets */
+#ifdef AFS_LARGEFILES
+        offset.HighPart = smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16);
+#else
+        if ((smb_GetSMBParm(inp, 12) | (smb_GetSMBParm(inp, 13) << 16)) != 0) {
+            /* uh oh */
+            osi_Log0(smb_logp, "smb_ReceiveV3WriteX offset requires largefile support");
+            /* we shouldn't have received this op if we didn't specify
+               largefile support */
+            return CM_ERROR_BADOP;
+        }
+#endif
+    }
+
+    op = inp->data + smb_GetSMBParm(inp, 11);
+    inDataBlockCount = count;
+
+    osi_Log4(smb_logp, "smb_ReceiveV3WriteX fid %d, off 0x%x:%08x, size 0x%x",
+             fd, offset.HighPart, offset.LowPart, count);
+        
+    fd = smb_ChainFID(fd, inp);
+    fidp = smb_FindFID(vcp, fd, 0);
+    if (!fidp)
+        return CM_ERROR_BADFD;
+        
+    lock_ObtainMutex(&fidp->mx);
+    if (fidp->flags & SMB_FID_IOCTL) {
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_IoctlV3Write(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+    userp = smb_GetUserFromVCP(vcp, inp);
+
+    /* special case: 0 bytes transferred means there is no data
+       transferred.  A slight departure from SMB_COM_WRITE where this
+       means that we are supposed to truncate the file at this
+       position. */
+
+    {
+        cm_key_t key;
+        LARGE_INTEGER LOffset;
+        LARGE_INTEGER LLength;
+
+        pid = ((smb_t *) inp)->pid;
+        key = cm_GenerateKey(vcp->vcID, pid, fd);
+
+        LOffset.HighPart = offset.HighPart;
+        LOffset.LowPart = offset.LowPart;
+        LLength.HighPart = 0;
+        LLength.LowPart = count;
+
+        lock_ObtainMutex(&fidp->scp->mx);
+        code = cm_LockCheckWrite(fidp->scp, LOffset, LLength, key);
+        lock_ReleaseMutex(&fidp->scp->mx);
+
+        if (code)
+            goto done;
+    }
+
+    /*
+     * Work around bug in NT client
+     *
+     * When copying a file, the NT client should first copy the data,
+     * then copy the last write time.  But sometimes the NT client does
+     * these in the wrong order, so the data copies would inadvertently
+     * cause the last write time to be overwritten.  We try to detect this,
+     * and don't set client mod time if we think that would go against the
+     * intention.
+     */
+    lock_ObtainMutex(&fidp->mx);
+    if ((fidp->flags & SMB_FID_MTIMESETDONE) != SMB_FID_MTIMESETDONE) {
+        fidp->scp->mask |= CM_SCACHEMASK_CLIENTMODTIME;
+        fidp->scp->clientModTime = time(NULL);
+    }
+    lock_ReleaseMutex(&fidp->mx);
+
+    code = 0;
+    while ( code == 0 && count > 0 ) {
+#ifndef DJGPP
+       code = smb_WriteData(fidp, &offset, count, op, userp, &written);
+#else /* DJGPP */
+       code = smb_WriteData(fidp, &offset, count, op, userp, &written, FALSE);
+#endif /* !DJGPP */
+       if (code == 0 && written == 0)
+            code = CM_ERROR_PARTIALWRITE;
+
+        offset = LargeIntegerAdd(offset,
+                                 ConvertLongToLargeInteger(written));
+        count -= written;
+        total_written += written;
+        written = 0;
+    }
+
+ done_writing:
+    
+    /* slots 0 and 1 are reserved for request chaining and will be
+       filled in when we return. */
+    smb_SetSMBParm(outp, 2, total_written);
+    smb_SetSMBParm(outp, 3, 0); /* reserved */
+    smb_SetSMBParm(outp, 4, 0); /* reserved */
+    smb_SetSMBParm(outp, 5, 0); /* reserved */
+    smb_SetSMBDataLength(outp, 0);
+
+ done:
+    smb_ReleaseFID(fidp);
+    cm_ReleaseUser(userp);
+
+    return code;
+}
 
 long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
@@ -5178,12 +5396,33 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         
     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(smb_logp, "smb_ReceiveV3Read fd %d, off 0x%x, size 0x%x",
-             fd, offset.LowPart, count);
-        
+    if (*inp->wctp == 12) {
+        /* a request with 64-bit offsets */
+#ifdef AFS_LARGEFILES
+        offset.HighPart = smb_GetSMBParm(inp, 10) | (smb_GetSMBParm(inp, 11) << 16);
+
+        if (LargeIntegerLessThanZero(offset)) {
+            osi_Log2(smb_logp, "smb_ReceiveV3Read offset too large (0x%x:%08x)",
+                     offset.HighPart, offset.LowPart);
+            return CM_ERROR_BADSMB;
+        }
+#else
+        if ((smb_GetSMBParm(inp, 10) | (smb_GetSMBParm(inp, 11) << 16)) != 0) {
+            osi_Log0(smb_logp, "smb_ReceiveV3Read offset is 64-bit.  Dropping");
+            return CM_ERROR_BADSMB;
+        } else {
+            offset.HighPart = 0;
+        }
+#endif
+    } else {
+        offset.HighPart = 0;
+    }
+
+    osi_Log4(smb_logp, "smb_ReceiveV3Read fd %d, off 0x%x:%08x, size 0x%x",
+             fd, offset.HighPart, offset.LowPart, count);
+
     fd = smb_ChainFID(fd, inp);
     fidp = smb_FindFID(vcp, fd, 0);
     if (!fidp) {
@@ -5213,11 +5452,16 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* set inp->fid so that later read calls in same msg can find fid */
     inp->fid = fd;
 
+    lock_ObtainMutex(&fidp->mx);
     if (fidp->flags & SMB_FID_IOCTL) {
-        return smb_IoctlV3Read(fidp, vcp, inp, outp);
+       lock_ReleaseMutex(&fidp->mx);
+        code = smb_IoctlV3Read(fidp, vcp, inp, outp);
+       smb_ReleaseFID(fidp);
+       return code;
     }
+    lock_ReleaseMutex(&fidp->mx);
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
 
     /* 0 and 1 are reserved for request chaining, were setup by our caller,
      * and will be further filled in after we return.
@@ -5325,6 +5569,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     char *tidPathp;
     BOOL foundscp;
     cm_req_t req;
+    int created = 0;
 
     cm_InitReq(&req);
 
@@ -5443,7 +5688,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     }
 #endif
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
     if (!userp) {
        osi_Log1(smb_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
        free(realPathp);
@@ -5451,6 +5696,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     }
 
     if (baseFid == 0) {
+       baseFidp = NULL;
         baseDirp = cm_data.rootSCachep;
         code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
         if (code == CM_ERROR_TIDIPC) {
@@ -5497,6 +5743,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (shareAccess & FILE_SHARE_WRITE)
         fidflags |= SMB_FID_SHARE_WRITE;
 
+    osi_Log1(smb_logp, "NTCreateX fidflags 0x%x", fidflags);
     code = 0;
 
     /* For an exclusive create, we want to do a case sensitive match for the last component. */
@@ -5511,6 +5758,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 cm_ReleaseSCache(dscp);
                 cm_ReleaseUser(userp);
                 free(realPathp);
+               if (baseFidp) 
+                   smb_ReleaseFID(baseFidp);
                 if ( WANTS_DFS_PATHNAMES(inp) )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
@@ -5527,6 +5776,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     cm_ReleaseSCache(dscp);
                     cm_ReleaseUser(userp);
                     free(realPathp);
+                   if (baseFidp) 
+                       smb_ReleaseFID(baseFidp);
                     return CM_ERROR_EXISTS;
                 }
             }
@@ -5540,6 +5791,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
+           if (baseFidp) 
+               smb_ReleaseFID(baseFidp);
             if ( WANTS_DFS_PATHNAMES(inp) )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
@@ -5576,6 +5829,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     cm_ReleaseSCache(dscp);
                     cm_ReleaseUser(userp);
                     free(realPathp);
+                   if (baseFidp) 
+                       smb_ReleaseFID(baseFidp);
                     if ( WANTS_DFS_PATHNAMES(inp) )
                         return CM_ERROR_PATH_NOT_COVERED;
                     else
@@ -5592,7 +5847,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                     treeStartp = realPathp + (tp - spacep->data);
 
                     if (*tp && !smb_IsLegalFilename(tp)) {
-                        if (baseFid != 0) 
+                        if (baseFidp) 
                             smb_ReleaseFID(baseFidp);
                         cm_ReleaseUser(userp);
                         free(realPathp);
@@ -5608,7 +5863,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
         /* we might have scp and we might have dscp */
 
-        if (baseFid != 0) 
+        if (baseFidp)
             smb_ReleaseFID(baseFidp);
 
         if (code) {
@@ -5670,7 +5925,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         /* we have scp and dscp */
     } else {
         /* we have scp but not dscp */
-        if (baseFid != 0) 
+        if (baseFidp)
             smb_ReleaseFID(baseFidp);
     }
 
@@ -5680,7 +5935,18 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
      * scp is NULL.
      */
     if (code == 0 && !treeCreate) {
-        if (createDisp == FILE_CREATE) {
+        code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req);
+        if (code) {
+            if (dscp)
+                cm_ReleaseSCache(dscp);
+            if (scp)
+                cm_ReleaseSCache(scp);
+            cm_ReleaseUser(userp);
+            free(realPathp);
+            return code;
+        }
+
+       if (createDisp == FILE_CREATE) {
             /* oops, file shouldn't be there */
             if (dscp)
                 cm_ReleaseSCache(dscp);
@@ -5720,16 +5986,6 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         else 
             openAction = 1;    /* found existing file */
 
-        code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, &req);
-        if (code) {
-            if (dscp)
-                cm_ReleaseSCache(dscp);
-            if (scp)
-                cm_ReleaseSCache(scp);
-            cm_ReleaseUser(userp);
-            free(realPathp);
-            return code;
-        }
     } else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
         /* don't create if not found */
         if (dscp)
@@ -5747,11 +6003,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         setAttr.clientModTime = time(NULL);
         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 (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+        if (code == 0) {
+           created = 1;
+           if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+               smb_NotifyChange(FILE_ACTION_ADDED,
+                                FILE_NOTIFY_CHANGE_FILE_NAME,
+                                dscp, lastNamep, NULL, TRUE);
+       } else if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
             /* 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
@@ -5801,6 +6059,13 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                   osi_LogSaveString(smb_logp, treeStartp));
         openAction = 2;                /* created directory */
 
+       /* if the request is to create the root directory 
+        * it will appear as a directory name of the nul-string
+        * and a code of CM_ERROR_NOSUCHFILE
+        */
+       if ( !*treeStartp && code == CM_ERROR_NOSUCHFILE)
+           code = CM_ERROR_EXISTS;
+
         setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
         setAttr.clientModTime = time(NULL);
 
@@ -5814,10 +6079,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             tp = strchr(pp, '\\');
             if (!tp) {
                 strcpy(cp,pp);
-                clen = strlen(cp);
+                clen = (int)strlen(cp);
                 isLast = 1; /* indicate last component.  the supplied path never ends in a slash */
             } else {
-                clen = tp - pp;
+                clen = (int)(tp - pp);
                 strncpy(cp,pp,clen);
                 *(cp + clen) = 0;
                 tp++;
@@ -5919,6 +6184,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
 
+    /* save a reference to the user */
+    cm_HoldUser(userp);
+    fidp->userp = userp;
+
     /* If we are restricting sharing, we should do so with a suitable
        share lock. */
     if (scp->fileType == CM_SCACHETYPE_FILE &&
@@ -5945,7 +6214,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         lock_ReleaseMutex(&scp->mx);
 
         if (code) {
-            fidp->flags = SMB_FID_DELETE;
+            /* shouldn't this be smb_CloseFID() fidp->flags = SMB_FID_DELETE; */
+           smb_CloseFID(vcp, fidp, NULL, 0);
             smb_ReleaseFID(fidp);
 
             cm_ReleaseSCache(scp);
@@ -5954,15 +6224,20 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
             cm_ReleaseUser(userp);
             free(realPathp);
             
-            return CM_ERROR_SHARING_VIOLATION;
+            return code;
         }
     }
 
+    lock_ObtainMutex(&fidp->mx);
     /* save a pointer to the vnode */
     fidp->scp = scp;    /* Hold transfered to fidp->scp and no longer needed */
 
     fidp->flags = fidflags;
 
+    /* remember if the file was newly created */
+    if (created)
+       fidp->flags |= SMB_FID_CREATED;
+
     /* save parent dir and pathname for delete or change notification */
     if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
         fidp->flags |= SMB_FID_NTOPEN;
@@ -5971,6 +6246,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         fidp->NTopen_pathp = strdup(lastNamep);
     }
     fidp->NTopen_wholepathp = realPathp;
+    lock_ReleaseMutex(&fidp->mx);
 
     /* we don't need this any longer */
     if (dscp) {
@@ -6001,7 +6277,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* filetype */
     smb_SetSMBParm(outp, parmSlot, 0); parmSlot++;     /* dev state */
     smb_SetSMBParmByte(outp, parmSlot,
-                        scp->fileType == CM_SCACHETYPE_DIRECTORY); /* is a dir? */
+                        (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+                        scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+                        scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0); /* is a dir? */
     lock_ReleaseMutex(&scp->mx);
     smb_SetSMBDataLength(outp, 0);
 
@@ -6068,6 +6346,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     ULONG *lparmp;
     char *outData;
     cm_req_t req;
+    int created = 0;
 
     cm_InitReq(&req);
 
@@ -6155,7 +6434,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     }
 #endif
 
-    userp = smb_GetUser(vcp, inp);
+    userp = smb_GetUserFromVCP(vcp, inp);
     if (!userp) {
        osi_Log1(smb_logp, "NTTranCreate invalid user [%d]", ((smb_t *) inp)->uid);
        free(realPathp);
@@ -6163,6 +6442,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     }
 
     if (baseFid == 0) {
+       baseFidp = NULL;
         baseDirp = cm_data.rootSCachep;
         code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
         if (code == CM_ERROR_TIDIPC) {
@@ -6181,7 +6461,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     } else {
         baseFidp = smb_FindFID(vcp, baseFid, 0);
         if (!baseFidp) {
-               osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+           osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid);
             free(realPathp);
             cm_ReleaseUser(userp);
             return CM_ERROR_INVAL;
@@ -6220,6 +6500,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                 cm_ReleaseSCache(dscp);
                 cm_ReleaseUser(userp);
                 free(realPathp);
+               if (baseFidp)
+                   smb_ReleaseFID(baseFidp);
                 if ( WANTS_DFS_PATHNAMES(inp) )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
@@ -6236,6 +6518,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                     cm_ReleaseSCache(dscp);
                     cm_ReleaseUser(userp);
                     free(realPathp);
+                   if (baseFidp)
+                       smb_ReleaseFID(baseFidp);
                     return CM_ERROR_EXISTS;
                 }
             }
@@ -6249,6 +6533,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
             cm_ReleaseSCache(scp);
             cm_ReleaseUser(userp);
             free(realPathp);
+           if (baseFidp)
+               smb_ReleaseFID(baseFidp);
             if ( WANTS_DFS_PATHNAMES(inp) )
                 return CM_ERROR_PATH_NOT_COVERED;
             else
@@ -6271,6 +6557,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
                 cm_ReleaseSCache(dscp);
                 cm_ReleaseUser(userp);
                 free(realPathp);
+               if (baseFidp)
+                   smb_ReleaseFID(baseFidp);
                 if ( WANTS_DFS_PATHNAMES(inp) )
                     return CM_ERROR_PATH_NOT_COVERED;
                 else
@@ -6282,10 +6570,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         
         cm_FreeSpace(spacep);
 
-        if (baseFid != 0) {
+        if (baseFidp)
             smb_ReleaseFID(baseFidp);
-            baseFidp = 0;
-        }
 
         if (code) {
             cm_ReleaseUser(userp);
@@ -6293,8 +6579,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
             return code;
         }
 
-        if (!lastNamep) lastNamep = realPathp;
-        else lastNamep++;
+        if (!lastNamep)
+           lastNamep = realPathp;
+        else 
+           lastNamep++;
 
         if (!smb_IsLegalFilename(lastNamep))
             return CM_ERROR_BADNTFILENAME;
@@ -6316,10 +6604,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
             }
         }
     } else {
-        if (baseFid != 0) {
+        if (baseFidp)
             smb_ReleaseFID(baseFidp);
-            baseFidp = 0;
-        }
         cm_FreeSpace(spacep);
     }
 
@@ -6394,11 +6680,13 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         setAttr.clientModTime = time(NULL);
         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 (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
+        if (code == 0) {
+           created = 1;
+           if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+               smb_NotifyChange(FILE_ACTION_ADDED,
+                                FILE_NOTIFY_CHANGE_FILE_NAME,
+                                dscp, lastNamep, NULL, TRUE);
+       } else if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
             /* 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
@@ -6507,6 +6795,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
     fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
     osi_assert(fidp);
 
+    /* save a reference to the user */
+    cm_HoldUser(userp);
+    fidp->userp = userp;
+
     /* If we are restricting sharing, we should do so with a suitable
        share lock. */
     if (scp->fileType == CM_SCACHETYPE_FILE &&
@@ -6533,7 +6825,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         lock_ReleaseMutex(&scp->mx);
 
         if (code) {
-            fidp->flags = SMB_FID_DELETE;
+            /* Shouldn't this be smb_CloseFID()?  fidp->flags = SMB_FID_DELETE; */
+           smb_CloseFID(vcp, fidp, NULL, 0);
             smb_ReleaseFID(fidp);
 
             cm_ReleaseSCache(scp);
@@ -6544,11 +6837,16 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         }
     }
 
+    lock_ObtainMutex(&fidp->mx);
     /* save a pointer to the vnode */
     fidp->scp = scp;
 
     fidp->flags = fidflags;
 
+    /* remember if the file was newly created */
+    if (created)
+       fidp->flags |= SMB_FID_CREATED;
+
     /* save parent dir and pathname for deletion or change notification */
     if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) {
         fidp->flags |= SMB_FID_NTOPEN;
@@ -6557,6 +6855,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         fidp->NTopen_pathp = strdup(lastNamep);
     }
     fidp->NTopen_wholepathp = realPathp;
+    lock_ReleaseMutex(&fidp->mx);
 
     /* we don't need this any longer */
     if (dscp) 
@@ -6613,7 +6912,9 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         *((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);
+        *((USHORT *)outData) = ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+                               scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+                               scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
         outData += 2;  /* is a dir? */
         lock_ReleaseMutex(&scp->mx);
     } else {
@@ -6661,7 +6962,9 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         *((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);
+        *((USHORT *)outData) = ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+                               scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+                               scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
         outData += 1;  /* is a dir? */
         memset(outData,0,24); outData += 24; /* Volume ID and file ID */
         *((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
@@ -6701,6 +7004,8 @@ long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp,
 
     savedPacketp = smb_CopyPacket(inp);
     smb_HoldVC(vcp);
+    if (savedPacketp->vcp)
+       smb_ReleaseVC(savedPacketp->vcp);
     savedPacketp->vcp = vcp;
     lock_ObtainMutex(&smb_Dir_Watch_Lock);
     savedPacketp->nextp = smb_Directory_Watches;
@@ -6819,15 +7124,23 @@ long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         ((smb_t *)outp)->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
         
     switch (function) {
-    case 6: 
-        return smb_ReceiveNTTranQuerySecurityDesc(vcp, inp, outp);
-    case 4: 
-        return smb_ReceiveNTTranNotifyChange(vcp, inp, outp);
     case 1: 
         return smb_ReceiveNTTranCreate(vcp, inp, outp);
-    default: 
-        return CM_ERROR_INVAL;
+    case 2:
+       osi_Log0(smb_logp, "SMB NT Transact Ioctl - not implemented");
+       break;
+    case 3:
+       osi_Log0(smb_logp, "SMB NT Transact SetSecurityDesc - not implemented");
+       break;
+    case 4:
+        return smb_ReceiveNTTranNotifyChange(vcp, inp, outp);
+    case 5:
+       osi_Log0(smb_logp, "SMB NT Transact Rename - not implemented");
+       break;
+    case 6:
+        return smb_ReceiveNTTranQuerySecurityDesc(vcp, inp, outp);
     }
+    return CM_ERROR_INVAL;
 }
 
 /*
@@ -6850,7 +7163,6 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
     BOOL twoEntries = FALSE;
     ULONG otherNameLen, oldParmCount = 0;
     DWORD otherAction;
-    smb_vc_t *vcp;
     smb_fid_t *fidp;
 
     /* Get ready for rename within directory */
@@ -6871,7 +7183,6 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
         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;
 
         /*
          * Strange hack - bug in NT Client and NT Server that we
@@ -6880,7 +7191,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
         if (filter == 3 && wtree)
             filter = 0x17;
 
-        fidp = smb_FindFID(vcp, fid, 0);
+        fidp = smb_FindFID(watch->vcp, fid, 0);
         if (!fidp) {
             osi_Log1(smb_logp," no fidp for fid[%d]",fid);
             lastWatch = watch;
@@ -6924,11 +7235,11 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
         if (filename == NULL)
             parmCount = 0;
         else {
-            nameLen = strlen(filename);
+            nameLen = (ULONG)strlen(filename);
             parmCount = 3*4 + nameLen*2;
             parmCount = (parmCount + 3) & ~3;  /* pad to 4 */
             if (twoEntries) {
-                otherNameLen = strlen(otherFilename);
+                otherNameLen = (ULONG)strlen(otherFilename);
                 oldParmCount = parmCount;
                 parmCount += 3*4 + otherNameLen*2;
                 parmCount = (parmCount + 3) & ~3; /* pad to 4 */
@@ -7010,7 +7321,7 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
             ((smb_t *) watch)->flg2 |= SMB_FLAGS2_32BIT_STATUS;
         }
 
-        smb_SendPacket(vcp, watch);
+        smb_SendPacket(watch->vcp, watch);
         smb_FreePacket(watch);
         watch = nextWatch;
     }
@@ -7139,22 +7450,23 @@ 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)
+cm_user_t *smb_FindCMUserByName(char *usern, char *machine, afs_uint32 flags)
 {
-    /*int newUid;*/
     smb_username_t *unp;
+    cm_user_t *     userp;
 
-    unp = smb_FindUserByName(usern, machine, SMB_FLAG_CREATE);
+    unp = smb_FindUserByName(usern, machine, flags);
     if (!unp->userp) {
         lock_ObtainMutex(&unp->mx);
         unp->userp = cm_NewUser();
         lock_ReleaseMutex(&unp->mx);
         osi_Log2(smb_logp,"smb_FindCMUserByName New user name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
-        osi_LogEvent("AFS smb_FindCMUserByName : New User",NULL,"name[%s] machine[%s]",usern,machine);
     }  else    {
         osi_Log2(smb_logp,"smb_FindCMUserByName Not found name[%s] machine[%s]",osi_LogSaveString(smb_logp,usern),osi_LogSaveString(smb_logp,machine));
-        osi_LogEvent("AFS smb_FindCMUserByName : Found",NULL,"name[%s] machine[%s]",usern,machine);
-       }
-    return unp->userp;
+    }
+    userp = unp->userp;
+    cm_HoldUser(userp);
+    smb_ReleaseUsername(unp);
+    return userp;
 }