windows-multi-fix-20061003
[openafs.git] / src / WINNT / afsd / smb3.c
index b739b6b..f9d54ec 100644 (file)
 #include <afs/param.h>
 #include <afs/stds.h>
 
-#ifndef DJGPP
 #include <windows.h>
 #include <ntstatus.h>
 #define SECURITY_WIN32
 #include <security.h>
 #include <lmaccess.h>
-#endif /* !DJGPP */
 #include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
@@ -1317,9 +1315,7 @@ 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
        LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_ZERO_TRANSACTION_COUNT);
-#endif /* !DJGPP */
 
         smb_SetSMBDataLength(outp, 0);
         smb_SendPacket(vcp, outp);
@@ -1944,9 +1940,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) {
         osi_Log0(smb_logp, "Transaction2 word count = 0"); 
-#ifndef DJGPP
        LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_ZERO_TRANSACTION_COUNT);
-#endif /* !DJGPP */
 
         smb_SetSMBDataLength(outp, 0);
         smb_SendPacket(vcp, outp);
@@ -2092,7 +2086,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
         
     /* compute initial mode bits based on read-only flag in attributes */
     initialModeBits = 0666;
-    if (attributes & 1) 
+    if (attributes & SMB_ATTR_READONLY) 
         initialModeBits &= ~0222;
         
     pathp = (char *) (&p->parmsp[14]);
@@ -2295,7 +2289,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
            created = 1;
            if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
                smb_NotifyChange(FILE_ACTION_ADDED,
-                                FILE_NOTIFY_CHANGE_FILE_NAME,  
+                                FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,  
                                  dscp, lastNamep, NULL, TRUE);
        } else if (!excl && code == CM_ERROR_EXISTS) {
             /* not an exclusive create, and someone else tried
@@ -2433,33 +2427,55 @@ long smb_ReceiveTran2FindNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     return CM_ERROR_BADOP;
 }
 
+long smb_ReceiveTran2QFSInfoFid(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+{
+    unsigned short fid;
+    unsigned short infolevel;
+
+    infolevel = p->parmsp[0];
+    fid = p->parmsp[1];
+    osi_Log2(smb_logp, "T2 QFSInfoFid InfoLevel 0x%x fid 0x%x - NOT_SUPPORTED", infolevel, fid);
+    
+    return CM_ERROR_BADOP;
+}
+
 long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
 {
     smb_tran2Packet_t *outp;
     smb_tran2QFSInfo_t qi;
     int responseSize;
-    osi_hyper_t temp;
-    static char FSname[6] = {'A', 0, 'F', 0, 'S', 0};
+    static char FSname[8] = {'A', 0, 'F', 0, 'S', 0, 0, 0};
         
     osi_Log1(smb_logp, "T2 QFSInfo type 0x%x", p->parmsp[0]);
 
     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 */
+    case SMB_INFO_ALLOCATION: 
+       responseSize = sizeof(qi.u.allocInfo); 
+       break;
+    case SMB_INFO_VOLUME: 
+       responseSize = sizeof(qi.u.volumeInfo); 
+       break;
+    case SMB_QUERY_FS_VOLUME_INFO: 
+       responseSize = sizeof(qi.u.FSvolumeInfo); 
+       break;
+    case SMB_QUERY_FS_SIZE_INFO: 
+       responseSize = sizeof(qi.u.FSsizeInfo); 
+       break;
+    case SMB_QUERY_FS_DEVICE_INFO: 
+       responseSize = sizeof(qi.u.FSdeviceInfo); 
+       break;
+    case SMB_QUERY_FS_ATTRIBUTE_INFO: 
+       responseSize = sizeof(qi.u.FSattributeInfo); 
+       break;
+    case SMB_INFO_UNIX:        /* CIFS Unix Info */
+    case SMB_INFO_MACOS:       /* Mac FS Info */
     default: 
-       return CM_ERROR_INVAL;
+       return CM_ERROR_BADOP;
     }
 
     outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, responseSize);
     switch (p->parmsp[0]) {
-    case 1:
+    case SMB_INFO_ALLOCATION: 
         /* alloc info */
         qi.u.allocInfo.FSID = 0;
         qi.u.allocInfo.sectorsPerAllocUnit = 1;
@@ -2468,7 +2484,7 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
         qi.u.allocInfo.bytesPerSector = 1024;
         break;
 
-    case 2:
+    case SMB_INFO_VOLUME: 
         /* volume info */
         qi.u.volumeInfo.vsn = 1234;
         qi.u.volumeInfo.vnCount = 4;
@@ -2477,45 +2493,45 @@ long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *
         memcpy(qi.u.volumeInfo.label, "AFS", 4);
         break;
 
-    case 0x102:
+    case SMB_QUERY_FS_VOLUME_INFO: 
         /* FS volume info */
-        memset((char *)&qi.u.FSvolumeInfo.vct, 0, sizeof(FILETIME));
+        memset((char *)&qi.u.FSvolumeInfo.vct, 0, 4);
         qi.u.FSvolumeInfo.vsn = 1234;
         qi.u.FSvolumeInfo.vnCount = 8;
-        memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0", 8);
+        memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0\0", 8);
         break;
 
-    case 0x103:
+    case SMB_QUERY_FS_SIZE_INFO: 
         /* FS size info */
-        temp.HighPart = 0;
-        temp.LowPart = 0x7fffffff;
-        qi.u.FSsizeInfo.totalAllocUnits = temp;
-        temp.LowPart = 0x3fffffff;
-        qi.u.FSsizeInfo.availAllocUnits = temp;
+        qi.u.FSsizeInfo.totalAllocUnits.HighPart = 0;
+       qi.u.FSsizeInfo.totalAllocUnits.LowPart= 0x7fffffff;
+        qi.u.FSsizeInfo.availAllocUnits.HighPart = 0;
+       qi.u.FSsizeInfo.availAllocUnits.LowPart= 0x3fffffff;
         qi.u.FSsizeInfo.sectorsPerAllocUnit = 1;
         qi.u.FSsizeInfo.bytesPerSector = 1024;
         break;
 
-    case 0x104:
+    case SMB_QUERY_FS_DEVICE_INFO: 
         /* FS device info */
-        qi.u.FSdeviceInfo.devType = 0; /* don't have a number */
+        qi.u.FSdeviceInfo.devType = 0x14; /* network file system */
         qi.u.FSdeviceInfo.characteristics = 0x50; /* remote, virtual */
         break;
 
-       case 0x105:
+    case SMB_QUERY_FS_ATTRIBUTE_INFO: 
         /* FS attribute info */
         /* attributes, defined in WINNT.H:
          *     FILE_CASE_SENSITIVE_SEARCH      0x1
          *     FILE_CASE_PRESERVED_NAMES       0x2
+        *      FILE_VOLUME_QUOTAS              0x10
          *     <no name defined>               0x4000
          *        If bit 0x4000 is not set, Windows 95 thinks
          *        we can't handle long (non-8.3) names,
          *        despite our protestations to the contrary.
          */
         qi.u.FSattributeInfo.attributes = 0x4003;
-        qi.u.FSattributeInfo.maxCompLength = 255;
-        qi.u.FSattributeInfo.FSnameLength = 6;
-        memcpy(qi.u.FSattributeInfo.FSname, FSname, 6);
+        qi.u.FSattributeInfo.maxCompLength = MAX_PATH;
+        qi.u.FSattributeInfo.FSnameLength = sizeof(FSname);
+        memcpy(qi.u.FSattributeInfo.FSname, FSname, sizeof(FSname));
         break;
     }   
         
@@ -2618,7 +2634,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     afs_uint32 dosTime;
     FILETIME ft;
     unsigned short infoLevel;
-    int nbytesRequired;
+    smb_tran2QPathInfo_t qpi;
+    int responseSize;
     unsigned short attributes;
     unsigned long extAttributes;
     char shortName[13];
@@ -2626,8 +2643,8 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     cm_user_t *userp;
     cm_space_t *spacep;
     cm_scache_t *scp, *dscp;
+    int delonclose = 0;
     long code = 0;
-    char *op;
     char *pathp;
     char *tidPathp;
     char *lastComp;
@@ -2637,43 +2654,27 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     infoLevel = p->parmsp[0];
     if (infoLevel == SMB_INFO_IS_NAME_VALID) 
-        nbytesRequired = 0;
+        responseSize = 0;
     else if (infoLevel == SMB_INFO_STANDARD) 
-        nbytesRequired = 22;
+        responseSize = sizeof(qpi.u.QPstandardInfo);
     else if (infoLevel == SMB_INFO_QUERY_EA_SIZE) 
-        nbytesRequired = 26;
-    else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
-#ifdef COMMENT
-        nbytesRequired = 40;
-#else
-        nbytesRequired = 34;
-#endif
-    }
-    else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
-#ifdef COMMENT
-       nbytesRequired = 24;
-#else
-       nbytesRequired = 22;
-#endif
-    }
-    else if (infoLevel == SMB_QUERY_FILE_EA_INFO) 
-        nbytesRequired = 4;
-#if 0
+        responseSize = sizeof(qpi.u.QPeaSizeInfo);
+    else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO)
+        responseSize = sizeof(qpi.u.QPfileBasicInfo);
+    else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO)
+       responseSize = sizeof(qpi.u.QPfileStandardInfo);
+    else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+        responseSize = sizeof(qpi.u.QPfileEaInfo);
     else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) 
-        nbytesRequired = ???;
+        responseSize = sizeof(qpi.u.QPfileNameInfo);
     else if (infoLevel == SMB_QUERY_FILE_ALL_INFO) 
-        nbytesRequired = ???;
-#endif
+        responseSize = sizeof(qpi.u.QPfileAllInfo);
     else if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO) 
-        nbytesRequired = 30;
+        responseSize = sizeof(qpi.u.QPfileAltNameInfo);
     else {
         osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
-#ifdef COMMENT
-        smb_SendTran2Error(vcp, p, opx, CM_ERROR_INVAL);
-#else
         smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADOP);
-#endif
         return 0;
     }
 
@@ -2683,13 +2684,13 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     osi_Log2(smb_logp, "T2 QPathInfo type 0x%x path %s", infoLevel,
               osi_LogSaveString(smb_logp, pathp));
 
-    outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, nbytesRequired);
+    outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
 
     if (infoLevel > 0x100)
         outp->totalParms = 2;
     else
         outp->totalParms = 0;
-    outp->totalData = nbytesRequired;
+    outp->totalData = responseSize;
         
     /* now, if we're at infoLevel 6, we're only being asked to check
      * the syntax, so we just OK things now.  In particular, we're *not*
@@ -2805,13 +2806,14 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     code = cm_SyncOp(scp, NULL, userp, &req, 0,
                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
     if (code) goto done;
+
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         
     /* now we have the status in the cache entry, and everything is locked.
      * Marshall the output data.
      */
-    op = outp->datap;
     /* for info level 108, figure out short name */
-    if (infoLevel == 0x108) {
+    if (infoLevel == SMB_QUERY_FILE_ALT_NAME_INFO) {
         code = cm_GetShortName(pathp, userp, &req,
                                 tidPathp, scp->fid.vnode, shortName,
                                 (size_t *) &len);
@@ -2819,80 +2821,329 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             goto done;
         }
 
-        op = outp->datap;
-        *((u_long *)op) = len * 2; op += 4;
-        mbstowcs((unsigned short *)op, shortName, len);
-        op += (len * 2);
+       qpi.u.QPfileAltNameInfo.fileNameLength = (len + 1) * 2;
+        mbstowcs((unsigned short *)qpi.u.QPfileAltNameInfo.fileName, shortName, len + 1);
 
         goto done;
     }
-    if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
+    else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
+       len = strlen(lastComp);
+       qpi.u.QPfileNameInfo.fileNameLength = (len + 1) * 2;
+        mbstowcs((unsigned short *)qpi.u.QPfileNameInfo.fileName, lastComp, len + 1);
+
+        goto done;
+    }
+    else if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
         smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
-        *((u_long *)op) = dosTime; op += 4;    /* creation time */
-        *((u_long *)op) = dosTime; op += 4;    /* access time */
-        *((u_long *)op) = dosTime; op += 4;    /* write time */
-        *((u_long *)op) = scp->length.LowPart; op += 4;        /* length */
-        *((u_long *)op) = scp->length.LowPart; op += 4;        /* alloc size */
+       qpi.u.QPstandardInfo.creationDateTime = dosTime;
+       qpi.u.QPstandardInfo.lastAccessDateTime = dosTime;
+       qpi.u.QPstandardInfo.lastWriteDateTime = dosTime;
+        qpi.u.QPstandardInfo.dataSize = scp->length.LowPart;
+        qpi.u.QPstandardInfo.allocationSize = scp->length.LowPart;
         attributes = smb_Attributes(scp);
-        *((u_short *)op) = attributes; op += 2;        /* attributes */
-
-       /* now, if we are being asked about extended attrs, return a 0 size */
-       if (infoLevel == SMB_INFO_QUERY_EA_SIZE) {
-           *((u_long *)op) = 0; op += 4;
-       }
+        qpi.u.QPstandardInfo.attributes = attributes;
+       qpi.u.QPstandardInfo.eaSize = 0;
     }
     else if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
-        *((FILETIME *)op) = ft; op += 8;       /* creation time */
-        *((FILETIME *)op) = ft; op += 8;       /* last access time */
-        *((FILETIME *)op) = ft; op += 8;       /* last write time */
-        *((FILETIME *)op) = ft; op += 8;       /* last change time */
+        qpi.u.QPfileBasicInfo.creationTime = ft;
+        qpi.u.QPfileBasicInfo.lastAccessTime = ft;
+        qpi.u.QPfileBasicInfo.lastWriteTime = ft;
+        qpi.u.QPfileBasicInfo.changeTime = ft;
         extAttributes = smb_ExtAttributes(scp);
-#ifdef COMMENT
-        *((u_long *)op) = extAttributes; op += 4; /* extended attribs */
-        *((u_long *)op) = 0; op += 4;  /* don't know what this is */
-#else
-       /* The CIFS Specs say */
-        *((u_short *)op) = extAttributes; op += 2; /* extended attributes */
-#endif 
+       qpi.u.QPfileBasicInfo.attributes = extAttributes;
+       qpi.u.QPfileBasicInfo.reserved = 0;
     }
     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;     /* Link count */
-        *op++ = 0;                                     /* Delete Pending */
-        *op++ = ((scp->fileType == CM_SCACHETYPE_DIRECTORY || 
-                 scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
-                 scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
-#ifdef COMMENT
-        *op++ = 0;
-        *op++ = 0;
-#endif
+       smb_fid_t *fidp = smb_FindFIDByScache(vcp, scp);
+       if (fidp) {
+           lock_ObtainMutex(&fidp->mx);
+           delonclose = fidp->flags & SMB_FID_DELONCLOSE;
+           lock_ReleaseMutex(&fidp->mx);
+           smb_ReleaseFID(fidp);
+       }
+
+        qpi.u.QPfileStandardInfo.allocationSize = scp->length;
+        qpi.u.QPfileStandardInfo.endOfFile = scp->length;
+        qpi.u.QPfileStandardInfo.numberOfLinks = scp->linkCount;
+        qpi.u.QPfileStandardInfo.deletePending = (delonclose ? 1 : 0);
+        qpi.u.QPfileStandardInfo.directory = 
+           ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+             scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+             scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
+        qpi.u.QPfileStandardInfo.reserved = 0;
     }
     else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
-        memset(op, 0, 4); op += 4;     /* EA size */
+        qpi.u.QPfileEaInfo.eaSize = 0;
+    }
+    else if (infoLevel == SMB_QUERY_FILE_ALL_INFO) {
+        smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+        qpi.u.QPfileAllInfo.creationTime = ft;
+        qpi.u.QPfileAllInfo.lastAccessTime = ft;
+        qpi.u.QPfileAllInfo.lastWriteTime = ft;
+        qpi.u.QPfileAllInfo.changeTime = ft;
+        extAttributes = smb_ExtAttributes(scp);
+       qpi.u.QPfileAllInfo.attributes = extAttributes;
+        qpi.u.QPfileAllInfo.allocationSize = scp->length;
+        qpi.u.QPfileAllInfo.endOfFile = scp->length;
+        qpi.u.QPfileAllInfo.numberOfLinks = scp->linkCount;
+        qpi.u.QPfileAllInfo.deletePending = 0;
+        qpi.u.QPfileAllInfo.directory = 
+           ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+             scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+             scp->fileType == CM_SCACHETYPE_INVALID) ? 1 : 0);
+       qpi.u.QPfileAllInfo.indexNumber.HighPart = scp->fid.cell;
+       qpi.u.QPfileAllInfo.indexNumber.LowPart  = scp->fid.volume;
+       qpi.u.QPfileAllInfo.eaSize = 0;
+       qpi.u.QPfileAllInfo.accessFlags = 0;
+       qpi.u.QPfileAllInfo.indexNumber2.HighPart = scp->fid.vnode;
+       qpi.u.QPfileAllInfo.indexNumber2.LowPart  = scp->fid.unique;
+       qpi.u.QPfileAllInfo.currentByteOffset.HighPart = 0;
+       qpi.u.QPfileAllInfo.currentByteOffset.LowPart = 0;
+       qpi.u.QPfileAllInfo.mode = 0;
+       qpi.u.QPfileAllInfo.alignmentRequirement = 0;
+       len = strlen(lastComp);
+       qpi.u.QPfileAllInfo.fileNameLength = (len + 1) * 2;
+        mbstowcs((unsigned short *)qpi.u.QPfileAllInfo.fileName, lastComp, len + 1);
     }
-
-
 
     /* send and free the packets */
   done:
     lock_ReleaseMutex(&scp->mx);
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
-    if (code == 0) 
-        smb_SendTran2Packet(vcp, outp, opx);
-    else 
+    if (code == 0) {
+       memcpy(outp->datap, &qpi, responseSize);
+       smb_SendTran2Packet(vcp, outp, opx);
+    } else {
         smb_SendTran2Error(vcp, p, opx, code);
+    }
     smb_FreeTran2Packet(outp);
 
     return 0;
 }
 
-long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp)
+long smb_ReceiveTran2SetPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
 {
+#if 0
     osi_Log0(smb_logp,"ReceiveTran2SetPathInfo - NOT_SUPPORTED");
     return CM_ERROR_BADOP;
+#else
+    long code = 0;
+    smb_fid_t *fidp;
+    unsigned short infoLevel;
+    char * pathp;
+    smb_tran2Packet_t *outp;
+    smb_tran2QPathInfo_t *spi;
+    cm_user_t *userp;
+    cm_scache_t *scp, *dscp;
+    cm_req_t req;
+    cm_space_t *spacep;
+    char *tidPathp;
+    char *lastComp;
+
+    cm_InitReq(&req);
+
+    infoLevel = p->parmsp[0];
+    osi_Log1(smb_logp,"ReceiveTran2SetPathInfo type 0x%x", infoLevel);
+    if (infoLevel != SMB_INFO_STANDARD && 
+       infoLevel != SMB_INFO_QUERY_EA_SIZE &&
+       infoLevel != SMB_INFO_QUERY_ALL_EAS) {
+        osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
+                  p->opcode, infoLevel);
+        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 SetPathInfo infolevel 0x%x path %s", infoLevel,
+              osi_LogSaveString(smb_logp, pathp));
+
+    userp = smb_GetTran2User(vcp, p);
+    if (!userp) {
+       osi_Log1(smb_logp,"ReceiveTran2SetPathInfo unable to resolve user [%d]", p->uid);
+       code = CM_ERROR_BADSMB;
+       goto done;
+    }   
+
+    code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
+    if (code == CM_ERROR_TIDIPC) {
+        /* Attempt to use a TID allocated for IPC.  The client
+         * is probably looking for DCE RPC end points which we
+         * don't support OR it could be looking to make a DFS
+         * referral request. 
+         */
+        osi_Log0(smb_logp, "Tran2Open received IPC TID");
+        cm_ReleaseUser(userp);
+        return CM_ERROR_NOSUCHPATH;
+    }
+
+    /*
+    * XXX Strange hack XXX
+    *
+    * As of Patch 7 (13 January 98), we are having the following problem:
+    * In NT Explorer 4.0, whenever we click on a directory, AFS gets
+    * requests to look up "desktop.ini" in all the subdirectories.
+    * This can cause zillions of timeouts looking up non-existent cells
+    * and volumes, especially in the top-level directory.
+    *
+    * We have not found any way to avoid this or work around it except
+    * to explicitly ignore the requests for mount points that haven't
+    * yet been evaluated and for directories that haven't yet been
+    * fetched.
+    */
+    if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
+        spacep = cm_GetSpace();
+        smb_StripLastComponent(spacep->data, &lastComp, pathp);
+#ifndef SPECIAL_FOLDERS
+        /* Make sure that lastComp is not NULL */
+        if (lastComp) {
+            if (stricmp(lastComp, "\\desktop.ini") == 0) {
+                code = cm_NameI(cm_data.rootSCachep, spacep->data,
+                                 CM_FLAG_CASEFOLD
+                                 | CM_FLAG_DIRSEARCH
+                                 | CM_FLAG_FOLLOW,
+                                 userp, tidPathp, &req, &dscp);
+                if (code == 0) {
+#ifdef DFS_SUPPORT
+                    if (dscp->fileType == CM_SCACHETYPE_DFSLINK) {
+                        if ( WANTS_DFS_PATHNAMES(p) )
+                            code = CM_ERROR_PATH_NOT_COVERED;
+                        else
+                            code = CM_ERROR_BADSHARENAME;
+                    } else
+#endif /* DFS_SUPPORT */
+                    if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFid.volume)
+                        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);
+                        return 0;
+                    }
+                }
+            }
+        }
+#endif /* SPECIAL_FOLDERS */
+
+        cm_FreeSpace(spacep);
+    }
+
+    /* now do namei and stat, and copy out the info */
+    code = cm_NameI(cm_data.rootSCachep, pathp,
+                     CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp);
+    if (code) {
+        cm_ReleaseUser(userp);
+        smb_SendTran2Error(vcp, p, opx, code);
+        return 0;
+    }
+
+    fidp = smb_FindFIDByScache(vcp, scp);
+    if (!fidp) {
+        cm_ReleaseUser(userp);
+        cm_ReleaseSCache(scp);
+       smb_SendTran2Error(vcp, p, opx, code);
+        return 0;
+    }
+
+    lock_ObtainMutex(&fidp->mx);
+    if (!(fidp->flags & SMB_FID_OPENWRITE)) {
+       lock_ReleaseMutex(&fidp->mx);
+        smb_ReleaseFID(fidp);
+        cm_ReleaseUser(userp);
+        cm_ReleaseSCache(scp);
+        smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS);
+        return 0;
+    }
+    lock_ReleaseMutex(&fidp->mx);
+
+    outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, 0);
+
+    outp->totalParms = 2;
+    outp->totalData = 0;
+
+    spi = (smb_tran2QPathInfo_t *)p->datap;
+    if (infoLevel == SMB_INFO_STANDARD || infoLevel == SMB_INFO_QUERY_EA_SIZE) {
+        cm_attr_t attr;
+
+        /* lock the vnode with a callback; we need the current status
+         * to determine what the new status is, in some cases.
+         */
+        lock_ObtainMutex(&scp->mx);
+        code = cm_SyncOp(scp, NULL, userp, &req, 0,
+                          CM_SCACHESYNC_GETSTATUS
+                         | CM_SCACHESYNC_NEEDCALLBACK);
+        if (code) {
+           lock_ReleaseMutex(&scp->mx);
+            goto done;
+        }
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+       lock_ReleaseMutex(&scp->mx);
+       lock_ObtainMutex(&fidp->mx);
+       lock_ObtainMutex(&scp->mx);
+
+        /* prepare for setattr call */
+        attr.mask = CM_ATTRMASK_LENGTH;
+        attr.length.LowPart = spi->u.QPstandardInfo.dataSize;
+        attr.length.HighPart = 0;
+
+       if (spi->u.QPstandardInfo.lastWriteDateTime != 0) {
+           smb_UnixTimeFromSearchTime(&attr.clientModTime, spi->u.QPstandardInfo.lastWriteDateTime);
+            attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
+            fidp->flags |= SMB_FID_MTIMESETDONE;
+        }
+               
+        if (spi->u.QPstandardInfo.attributes != 0) {
+            if ((scp->unixModeBits & 0222)
+                 && (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) != 0) {
+                /* make a writable file read-only */
+                attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
+                attr.unixModeBits = scp->unixModeBits & ~0222;
+            }
+            else if ((scp->unixModeBits & 0222) == 0
+                      && (spi->u.QPstandardInfo.attributes & SMB_ATTR_READONLY) == 0) {
+                /* make a read-only file writable */
+                attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
+                attr.unixModeBits = scp->unixModeBits | 0222;
+            }
+        }
+        lock_ReleaseMutex(&scp->mx);
+       lock_ReleaseMutex(&fidp->mx);
+
+        /* call setattr */
+        if (attr.mask)
+            code = cm_SetAttr(scp, &attr, userp, &req);
+        else
+            code = 0;
+    }               
+    else if (infoLevel == SMB_INFO_QUERY_ALL_EAS) {
+       /* we don't support EAs */
+       code = CM_ERROR_INVAL;
+    }       
+
+  done:
+    cm_ReleaseSCache(scp);
+    cm_ReleaseUser(userp);
+    smb_ReleaseFID(fidp);
+    if (code == 0) 
+        smb_SendTran2Packet(vcp, outp, opx);
+    else 
+        smb_SendTran2Error(vcp, p, opx, code);
+    smb_FreeTran2Packet(outp);
+
+    return 0;
+#endif
 }
 
 long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
@@ -2901,13 +3152,13 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     FILETIME ft;
     unsigned long attributes;
     unsigned short infoLevel;
-    int nbytesRequired;
+    int responseSize;
     unsigned short fid;
     int delonclose = 0;
     cm_user_t *userp;
     smb_fid_t *fidp;
     cm_scache_t *scp;
-    char *op;
+    smb_tran2QFileInfo_t qfi;
     long code = 0;
     cm_req_t req;
 
@@ -2923,29 +3174,29 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     infoLevel = p->parmsp[1];
     if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) 
-        nbytesRequired = 40;
+        responseSize = sizeof(qfi.u.QFbasicInfo);
     else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) 
-        nbytesRequired = 24;
+        responseSize = sizeof(qfi.u.QFstandardInfo);
     else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
-        nbytesRequired = 4;
+        responseSize = sizeof(qfi.u.QFeaInfo);
     else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) 
-        nbytesRequired = 6;
+        responseSize = sizeof(qfi.u.QFfileNameInfo);
     else {
         osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
-        smb_SendTran2Error(vcp, p, opx, CM_ERROR_INVAL);
+        smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADOP);
         smb_ReleaseFID(fidp);
         return 0;
     }
     osi_Log2(smb_logp, "T2 QFileInfo type 0x%x fid %d", infoLevel, fid);
 
-    outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, nbytesRequired);
+    outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, responseSize);
 
     if (infoLevel > 0x100)
         outp->totalParms = 2;
     else
         outp->totalParms = 0;
-    outp->totalData = nbytesRequired;
+    outp->totalData = responseSize;
 
     userp = smb_GetTran2User(vcp, p);
     if (!userp) {
@@ -2965,33 +3216,32 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     if (code) 
         goto done;
 
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     /* now we have the status in the cache entry, and everything is locked.
      * Marshall the output data.
      */
-    op = outp->datap;
     if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
         smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
-        *((FILETIME *)op) = ft; op += 8;       /* creation time */
-        *((FILETIME *)op) = ft; op += 8;       /* last access time */
-        *((FILETIME *)op) = ft; op += 8;       /* last write time */
-        *((FILETIME *)op) = ft; op += 8;       /* last change time */
+        qfi.u.QFbasicInfo.creationTime = ft;
+        qfi.u.QFbasicInfo.lastAccessTime = ft;
+        qfi.u.QFbasicInfo.lastWriteTime = ft;
+        qfi.u.QFbasicInfo.lastChangeTime = ft;
         attributes = smb_ExtAttributes(scp);
-        *((u_long *)op) = attributes; op += 4;
-        *((u_long *)op) = 0; op += 4;
+        qfi.u.QFbasicInfo.attributes = attributes;
     }
     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;     /* 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;
+       qfi.u.QFstandardInfo.allocationSize = scp->length;
+       qfi.u.QFstandardInfo.endOfFile = scp->length;
+        qfi.u.QFstandardInfo.numberOfLinks = scp->linkCount;
+        qfi.u.QFstandardInfo.deletePending = (delonclose ? 1 : 0);
+        qfi.u.QFstandardInfo.directory = 
+           ((scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+             scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+             scp->fileType == CM_SCACHETYPE_INVALID)? 1 : 0);
     }
     else if (infoLevel == SMB_QUERY_FILE_EA_INFO) {
-        *((u_long *)op) = 0; op += 4;
+        qfi.u.QFeaInfo.eaSize = 0;
     }
     else if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
         unsigned long len;
@@ -3006,9 +3256,9 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             name = "\\";       /* probably can't happen */
        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);
+        outp->totalData = ((len+1)*2) + 4;     /* this is actually what we want to return */
+        qfi.u.QFfileNameInfo.fileNameLength = (len + 1) * 2;
+        mbstowcs((unsigned short *)qfi.u.QFfileNameInfo.fileName, name, len + 1);
     }
 
     /* send and free the packets */
@@ -3017,16 +3267,18 @@ long smb_ReceiveTran2QFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
-    if (code == 0) 
+    if (code == 0) {
+       memcpy(outp->datap, &qfi, responseSize);
         smb_SendTran2Packet(vcp, outp, opx);
-    else 
+    } else {
         smb_SendTran2Error(vcp, p, opx, code);
+    }
     smb_FreeTran2Packet(outp);
 
     return 0;
 }       
 
-long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
+long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *opx)
 {
     long code = 0;
     unsigned short fid;
@@ -3043,32 +3295,33 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     fidp = smb_FindFID(vcp, fid, 0);
 
     if (fidp == NULL) {
-        smb_SendTran2Error(vcp, p, op, CM_ERROR_BADFD);
+        smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADFD);
         return 0;
     }
 
     infoLevel = p->parmsp[1];
     osi_Log2(smb_logp,"ReceiveTran2SetFileInfo type 0x%x fid %d", infoLevel, fid);
-    if (infoLevel > 0x104 || infoLevel < 0x101) {
+    if (infoLevel > SMB_SET_FILE_END_OF_FILE_INFO || infoLevel < SMB_SET_FILE_BASIC_INFO) {
         osi_Log2(smb_logp, "Bad Tran2 op 0x%x infolevel 0x%x",
                   p->opcode, infoLevel);
-        smb_SendTran2Error(vcp, p, op, CM_ERROR_INVAL);
+        smb_SendTran2Error(vcp, p, opx, CM_ERROR_BADOP);
         smb_ReleaseFID(fidp);
         return 0;
     }
 
     lock_ObtainMutex(&fidp->mx);
-    if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO && !(fidp->flags & SMB_FID_OPENDELETE)) {
+    if (infoLevel == SMB_SET_FILE_DISPOSITION_INFO && !(fidp->flags & SMB_FID_OPENDELETE)) {
        lock_ReleaseMutex(&fidp->mx);
         smb_ReleaseFID(fidp);
-        smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
+        smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS);
         return 0;
     }
-    if ((infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO)
+    if ((infoLevel == SMB_SET_FILE_ALLOCATION_INFO || 
+        infoLevel == SMB_SET_FILE_END_OF_FILE_INFO)
          && !(fidp->flags & SMB_FID_OPENWRITE)) {
        lock_ReleaseMutex(&fidp->mx);
         smb_ReleaseFID(fidp);
-        smb_SendTran2Error(vcp, p, op, CM_ERROR_NOACCESS);
+        smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOACCESS);
         return 0;
     }
 
@@ -3076,9 +3329,7 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
     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);
+    outp = smb_GetTran2ResponsePacket(vcp, p, opx, 2, 0);
 
     outp->totalParms = 2;
     outp->totalData = 0;
@@ -3090,30 +3341,36 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
        goto done;
     }   
 
-    if (infoLevel == SMB_QUERY_FILE_BASIC_INFO) {
+    if (infoLevel == SMB_SET_FILE_BASIC_INFO) {
         FILETIME lastMod;
         unsigned int attribute;
         cm_attr_t attr;
+       smb_tran2QFileInfo_t *sfi;
 
-        /* lock the vnode with a callback; we need the current status
+       sfi = (smb_tran2QFileInfo_t *)p->datap;
+
+       /* lock the vnode with a callback; we need the current status
          * to determine what the new status is, in some cases.
          */
         lock_ObtainMutex(&scp->mx);
         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;
-        }
+       }
 
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+       lock_ReleaseMutex(&scp->mx);
        lock_ObtainMutex(&fidp->mx);
        lock_ObtainMutex(&scp->mx);
 
         /* prepare for setattr call */
         attr.mask = 0;
 
-        lastMod = *((FILETIME *)(p->datap + 16));
+        lastMod = sfi->u.QFbasicInfo.lastWriteTime;
         /* 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)
@@ -3125,16 +3382,16 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
             fidp->flags |= SMB_FID_MTIMESETDONE;
         }
                
-        attribute = *((u_long *)(p->datap + 32));
+        attribute = sfi->u.QFbasicInfo.attributes;
         if (attribute != 0) {
             if ((scp->unixModeBits & 0222)
-                 && (attribute & 1) != 0) {
+                 && (attribute & SMB_ATTR_READONLY) != 0) {
                 /* make a writable file read-only */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
                 attr.unixModeBits = scp->unixModeBits & ~0222;
             }
             else if ((scp->unixModeBits & 0222) == 0
-                      && (attribute & 1) == 0) {
+                      && (attribute & SMB_ATTR_READONLY) == 0) {
                 /* make a read-only file writable */
                 attr.mask |= CM_ATTRMASK_UNIXMODEBITS;
                 attr.unixModeBits = scp->unixModeBits | 0222;
@@ -3148,18 +3405,9 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
             code = cm_SetAttr(scp, &attr, userp, &req);
         else
             code = 0;
-    }               
-    else if (infoLevel == SMB_QUERY_FILE_EA_INFO || infoLevel == SMB_QUERY_FILE_NAME_INFO) {
-        LARGE_INTEGER size = *((LARGE_INTEGER *)(p->datap));
-        cm_attr_t attr;
-
-        attr.mask = CM_ATTRMASK_LENGTH;
-        attr.length.LowPart = size.LowPart;
-        attr.length.HighPart = size.HighPart;
-        code = cm_SetAttr(scp, &attr, userp, &req);
-    }       
-    else if (infoLevel == SMB_QUERY_FILE_STANDARD_INFO) {
-        if (*((char *)(p->datap))) {
+    }
+    else if (infoLevel == SMB_SET_FILE_DISPOSITION_INFO) {
+        if (*((char *)(p->datap))) {   /* File is Deleted */
             code = cm_CheckNTDelete(fidp->NTopen_dscp, scp, userp,
                                      &req);
             if (code == 0) {
@@ -3175,15 +3423,25 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
            lock_ReleaseMutex(&fidp->mx);
         }
     }       
+    else if (infoLevel == SMB_SET_FILE_ALLOCATION_INFO ||
+            infoLevel == SMB_SET_FILE_END_OF_FILE_INFO) {
+        LARGE_INTEGER size = *((LARGE_INTEGER *)(p->datap));
+        cm_attr_t attr;
+
+        attr.mask = CM_ATTRMASK_LENGTH;
+        attr.length.LowPart = size.LowPart;
+        attr.length.HighPart = size.HighPart;
+        code = cm_SetAttr(scp, &attr, userp, &req);
+    }       
 
   done:
     cm_ReleaseSCache(scp);
     cm_ReleaseUser(userp);
     smb_ReleaseFID(fidp);
     if (code == 0) 
-        smb_SendTran2Packet(vcp, outp, op);
+        smb_SendTran2Packet(vcp, outp, opx);
     else 
-        smb_SendTran2Error(vcp, p, op, code);
+        smb_SendTran2Error(vcp, p, opx, code);
     smb_FreeTran2Packet(outp);
 
     return 0;
@@ -3393,7 +3651,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
             /* Plug in fake timestamps. A time stamp of 0 causes 'invalid parameter'
                errors in the client. */
-            if (infoLevel >= 0x101) {
+            if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) {
                 /* 1969-12-31 23:59:59 +00 */
                 ft.dwHighDateTime = 0x19DB200;
                 ft.dwLowDateTime = 0x5BB78980;
@@ -3462,7 +3720,9 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
             }
             continue;
         }
-                
+        
+       cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
         /* now watch for a symlink */
         code = 0;
         while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) {
@@ -3483,7 +3743,7 @@ smb_ApplyV3DirListPatches(cm_scache_t *dscp,
 
         dptr = patchp->dptr;
 
-        if (infoLevel >= 0x101) {
+        if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) {
             /* get filetime */
             smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
 
@@ -3912,6 +4172,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
     int fileType;
     cm_fid_t fid;
     cm_req_t req;
+    char * s;
 
     cm_InitReq(&req);
 
@@ -3956,14 +4217,48 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         starPattern = 1;       /* assume, since required a Find Next */
     }
 
+    switch ( infoLevel ) {
+    case SMB_INFO_STANDARD:
+       s = "InfoStandard";
+       break;
+    case SMB_INFO_QUERY_EA_SIZE:
+       s = "InfoQueryEaSize";
+       break;
+    case SMB_INFO_QUERY_EAS_FROM_LIST:
+       s = "InfoQueryEasFromList";
+       break;
+    case SMB_FIND_FILE_DIRECTORY_INFO:
+       s = "FindFileDirectoryInfo";
+       break;
+    case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
+       s = "FindFileFullDirectoryInfo";
+       break;
+    case SMB_FIND_FILE_NAMES_INFO:
+       s = "FindFileNamesInfo";
+       break;
+    case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
+       s = "FindFileBothDirectoryInfo";
+       break;
+    default:
+       s = "unknownInfoLevel";
+    }
+
+    osi_Log1(smb_logp, "T2 search dir info level: %s", s);
+
     osi_Log4(smb_logp,
-              "T2 search dir attr 0x%x, info level %d, max count %d, flags 0x%x",
+              "T2 search dir attr 0x%x, info level 0x%x, max count %d, flags 0x%x",
               attribute, infoLevel, maxCount, searchFlags);
 
     osi_Log3(smb_logp, "...T2 search op %d, id %d, nextCookie 0x%x",
               p->opcode, dsp->cookie, nextCookie);
 
-    if (infoLevel >= 0x101)
+    if (infoLevel > SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
+        osi_Log1(smb_logp, "Unsupported InfoLevel 0x%x", infoLevel);
+        smb_ReleaseDirSearch(dsp);
+        return CM_ERROR_INVAL;
+    }
+
+    if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO)
         searchFlags &= ~4;     /* no resume keys */
 
     dirListPatchesp = NULL;
@@ -4084,6 +4379,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
         return code;
     }
 
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
   startsearch:
     dirLength = scp->length;
     bufferp = NULL;
@@ -4201,7 +4498,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                     osi_Log2(smb_logp, "T2 search dir cm_SyncOp scp %x failed %d", scp, code);
                     break;
                 }
-                                
+                       
+               cm_SyncOpDone(scp, bufferp, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_READ);
+
                 if (cm_HaveBuffer(scp, bufferp, 0)) {
                     osi_Log2(smb_logp, "T2 search dir !HaveBuffer scp %x bufferp %x", scp, bufferp);
                     break;
@@ -4267,7 +4566,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
         /* Need 8.3 name? */
         NeedShortName = 0;
-        if (infoLevel == SMB_QUERY_FILE_NAME_INFO
+        if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO
              && dep->fid.vnode != 0
              && !cm_Is8Dot3(dep->name)) {
             cm_Gen8Dot3Name(dep, shortName, &shortNameEnd);
@@ -4316,21 +4615,21 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             /* standard dir entry stuff */
             if (infoLevel < 0x101)
                 ohbytes = 23;  /* pre-NT */
-            else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+            else if (infoLevel == SMB_FIND_FILE_NAMES_INFO)
                 ohbytes = 12;  /* NT names only */
             else
                 ohbytes = 64;  /* NT */
 
-            if (infoLevel == SMB_QUERY_FILE_NAME_INFO)
+            if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO)
                 ohbytes += 26; /* Short name & length */
 
             if (searchFlags & 4) {
                 ohbytes += 4;  /* if resume key required */
             }   
 
-            if (infoLevel != 1
-                 && infoLevel != 0x101
-                 && infoLevel != 0x103)
+            if (infoLevel != SMB_INFO_STANDARD
+                 && infoLevel != SMB_FIND_FILE_DIRECTORY_INFO
+                 && infoLevel != SMB_FIND_FILE_NAMES_INFO)
                 ohbytes += 4;  /* EASIZE */
 
             /* add header to name & term. null */
@@ -4342,7 +4641,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
              * about an * overflow when we pad things out below).
              * That's the reason for the alignment arithmetic below.
              */
-            if (infoLevel >= 0x101)
+            if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO)
                 align = (4 - (orbytes & 3)) & 3;
             else
                 align = 0;
@@ -4359,9 +4658,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             /* First zero everything else */
             memset(origOp, 0, ohbytes);
 
-            if (infoLevel <= 0x101)
+            if (infoLevel <= SMB_FIND_FILE_DIRECTORY_INFO)
                 *(origOp + ohbytes - 1) = (unsigned char) onbytes;
-            else if (infoLevel == SMB_QUERY_FILE_EA_INFO)
+            else if (infoLevel == SMB_FIND_FILE_NAMES_INFO)
                 *((u_long *)(op + 8)) = onbytes;
             else
                 *((u_long *)(op + 60)) = onbytes;
@@ -4370,7 +4669,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 CharToOem(origOp+ohbytes, origOp+ohbytes);
 
             /* Short name if requested and needed */
-            if (infoLevel == SMB_QUERY_FILE_NAME_INFO) {
+            if (infoLevel == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
                 if (NeedShortName) {
                     strcpy(op + 70, shortName);
                     if (smb_StoreAnsiFilenames)
@@ -4383,7 +4682,7 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
             returnedNames++;
 
             /* NextEntryOffset and FileIndex */
-            if (infoLevel >= 101) {
+            if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO) {
                 int entryOffset = orbytes + align;
                 *((u_long *)op) = entryOffset;
                 *((u_long *)(op+4)) = nextEntryCookie;
@@ -4402,12 +4701,12 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
              * later.  The replay will happen at a time when it is
              * safe to unlock the directory.
              */
-            if (infoLevel != 0x103) {
+            if (infoLevel != SMB_FIND_FILE_NAMES_INFO) {
                 curPatchp = malloc(sizeof(*curPatchp));
                 osi_QAdd((osi_queue_t **) &dirListPatchesp,
                           &curPatchp->q);
                 curPatchp->dptr = op;
-                if (infoLevel >= 0x101)
+                if (infoLevel >= SMB_FIND_FILE_DIRECTORY_INFO)
                     curPatchp->dptr += 8;
 
                 if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
@@ -4467,8 +4766,10 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
 
     /* release the mutex */
     lock_ReleaseMutex(&scp->mx);
-    if (bufferp) 
+    if (bufferp) {
         buf_Release(bufferp);
+       bufferp = NULL;
+    }
 
     /* apply and free last set of patches; if not doing a star match, this
      * will be empty, but better safe (and freeing everything) than sorry.
@@ -4603,7 +4904,8 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
                                 /* compute initial mode bits based on read-only flag in attributes */
     initialModeBits = 0666;
-    if (attributes & 1) initialModeBits &= ~0222;
+    if (attributes & SMB_ATTR_READONLY) 
+       initialModeBits &= ~0222;
         
     pathp = smb_GetSMBData(inp, NULL);
     if (smb_StoreAnsiFilenames)
@@ -4771,7 +5073,7 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
            created = 1;
            if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
                smb_NotifyChange(FILE_ACTION_ADDED,
-                                FILE_NOTIFY_CHANGE_FILE_NAME,
+                                FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
                                 dscp, lastNamep, NULL, TRUE);
        } else if (!excl && code == CM_ERROR_EXISTS) {
             /* not an exclusive create, and someone else tried
@@ -5187,6 +5489,8 @@ long smb_ReceiveV3GetAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
     if (code) 
        goto done;
 
+    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
     /* 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.
@@ -5381,11 +5685,7 @@ long smb_ReceiveV3WriteX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
     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;
 
@@ -5520,11 +5820,7 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     /* set the packet data length the count of the # of bytes */
     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);
@@ -5768,6 +6064,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
         fidflags |= SMB_FID_OPENWRITE;
     if (createOptions & FILE_DELETE_ON_CLOSE)
         fidflags |= SMB_FID_DELONCLOSE;
+    if (createOptions & FILE_SEQUENTIAL_ONLY && !(createOptions & FILE_RANDOM_ACCESS))
+       fidflags |= SMB_FID_SEQUENTIAL;
+    if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
+       fidflags |= SMB_FID_RANDOM;
 
     /* and the share mode */
     if (shareAccess & FILE_SHARE_READ)
@@ -6039,7 +6339,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
            created = 1;
            if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
                smb_NotifyChange(FILE_ACTION_ADDED,
-                                FILE_NOTIFY_CHANGE_FILE_NAME,
+                                FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
                                 dscp, lastNamep, NULL, TRUE);
        } else if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
             /* Not an exclusive create, and someone else tried
@@ -6437,7 +6737,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
      * extended attributes
      */
     initialModeBits = 0666;
-    if (extAttributes & 1) 
+    if (extAttributes & SMB_ATTR_READONLY) 
         initialModeBits &= ~0222;
 
     pathp = parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR);
@@ -6512,6 +6812,10 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
         fidflags |= SMB_FID_OPENWRITE;
     if (createOptions & FILE_DELETE_ON_CLOSE)
         fidflags |= SMB_FID_DELONCLOSE;
+    if (createOptions & FILE_SEQUENTIAL_ONLY && !(createOptions & FILE_RANDOM_ACCESS))
+       fidflags |= SMB_FID_SEQUENTIAL;
+    if (createOptions & FILE_RANDOM_ACCESS && !(createOptions & FILE_SEQUENTIAL_ONLY))
+       fidflags |= SMB_FID_RANDOM;
 
     /* And the share mode */
     if (shareAccess & FILE_SHARE_READ)
@@ -6716,7 +7020,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
            created = 1;
            if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
                smb_NotifyChange(FILE_ACTION_ADDED,
-                                FILE_NOTIFY_CHANGE_FILE_NAME,
+                                FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_CREATION,
                                 dscp, lastNamep, NULL, TRUE);
        } else if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) {
             /* Not an exclusive create, and someone else tried