Windows: Correct alloc size SetFileExtents result
[openafs.git] / src / WINNT / afsrdr / user / RDRFunction.c
index b2151d2..1436bfd 100644 (file)
 static CHAR * RDR_extentBaseAddress = NULL;
 
 void
-RDR_InitReq(cm_req_t *reqp)
+RDR_InitReq(cm_req_t *reqp, BOOL bWow64)
 {
     cm_InitReq(reqp);
     reqp->flags |= CM_REQ_SOURCE_REDIR;
+    if (bWow64)
+        reqp->flags |= CM_REQ_WOW64;
 }
 
 void
@@ -140,6 +142,7 @@ RDR_SetInitParams( OUT AFSRedirectorInitInfo **ppRedirInitInfo, OUT DWORD * pRed
     *pRedirInitInfoLen = (DWORD) (sizeof(AFSRedirectorInitInfo) + (cm_CachePathLen + TempPathLen) * sizeof(WCHAR));
     *ppRedirInitInfo = (AFSRedirectorInitInfo *)malloc(*pRedirInitInfoLen);
     (*ppRedirInitInfo)->Flags = smb_hideDotFiles ? AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES : 0;
+    (*ppRedirInitInfo)->Flags |= cm_shortNames ? 0 : AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES;
     (*ppRedirInitInfo)->MaximumChunkLength = cm_data.chunkSize;
     (*ppRedirInitInfo)->GlobalFileId.Cell   = cm_data.rootFid.cell;
     (*ppRedirInitInfo)->GlobalFileId.Volume = cm_data.rootFid.volume;
@@ -148,8 +151,8 @@ RDR_SetInitParams( OUT AFSRedirectorInitInfo **ppRedirInitInfo, OUT DWORD * pRed
     (*ppRedirInitInfo)->GlobalFileId.Hash   = cm_data.rootFid.hash;
     (*ppRedirInitInfo)->ExtentCount.QuadPart = cm_data.buf_nbuffers;
     (*ppRedirInitInfo)->CacheBlockSize = cm_data.blockSize;
-    (*ppRedirInitInfo)->MaxPathLinkCount = 512; /* this needs to become a registry value */
-    (*ppRedirInitInfo)->NameArrayLength = 32;   /* this needs to become a registry value */
+    (*ppRedirInitInfo)->MaxPathLinkCount = MAX_FID_COUNT;
+    (*ppRedirInitInfo)->NameArrayLength = MAX_FID_COUNT;
     if (cm_virtualCache || cm_data.bufferSize <= maxMemoryCacheSize) {
         osi_Log0(afsd_logp, "RDR_SetInitParams Initializing Memory Extent Interface");
         (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = (LONGLONG)cm_data.bufDataBaseAddress;
@@ -178,17 +181,19 @@ RDR_SetInitParams( OUT AFSRedirectorInitInfo **ppRedirInitInfo, OUT DWORD * pRed
     return 0;
 }
 
+static wchar_t cname[MAX_COMPUTERNAME_LENGTH+1] = L"";
+
 cm_user_t *
 RDR_GetLocalSystemUser( void)
 {
     smb_username_t *unp;
     cm_user_t *userp = NULL;
-    wchar_t cname[MAX_COMPUTERNAME_LENGTH+1];
-    int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
-
-    GetComputerNameW(cname, &cnamelen);
-    _wcsupr(cname);
 
+    if ( cname[0] == '\0') {
+        int len = MAX_COMPUTERNAME_LENGTH+1;
+        GetComputerNameW(cname, &len);
+        _wcsupr(cname);
+    }
     unp = smb_FindUserByName(NTSID_LOCAL_SYSTEM, cname, SMB_FLAG_CREATE);
     lock_ObtainMutex(&unp->mx);
     if (!unp->userp)
@@ -220,19 +225,22 @@ RDR_UserFromAuthGroup( IN GUID *pGuid)
     smb_username_t *unp;
     cm_user_t * userp = NULL;
     RPC_WSTR UuidString = NULL;
-    wchar_t cname[MAX_COMPUTERNAME_LENGTH+1];
-    int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
 
     if (UuidToStringW((UUID *)pGuid, &UuidString) != RPC_S_OK)
         goto done;
 
-    GetComputerNameW(cname, &cnamelen);
-    _wcsupr(cname);
+    if ( cname[0] == '\0') {
+        int len = MAX_COMPUTERNAME_LENGTH+1;
+        GetComputerNameW(cname, &len);
+        _wcsupr(cname);
+    }
 
     unp = smb_FindUserByName(UuidString, cname, SMB_FLAG_CREATE);
     lock_ObtainMutex(&unp->mx);
-    if (!unp->userp)
+    if (!unp->userp) {
         unp->userp = cm_NewUser();
+        memcpy(&unp->userp->authgroup, pGuid, sizeof(GUID));
+    }
     unp->flags |= SMB_USERNAMEFLAG_SID;
     lock_ReleaseMutex(&unp->mx);
     userp = unp->userp;
@@ -280,8 +288,12 @@ RDR_FlagScpInUse( IN cm_scache_t *scp, IN BOOL bLocked )
 }
 
 /*
- * Obtain the status information for the specified object and
- *
+ * Obtain the status information for the specified object using
+ * an inline bulk status rpc.  cm_BPlusDirEnumBulkStatOne() will
+ * obtain current status for the directory object, the object
+ * which is the focus of the inquiry and as many other objects
+ * in the directory for which there are not callbacks registered
+ * since we are likely to be asked for other objects in the directory.
  */
 static afs_uint32
 RDR_BulkStatLookup( cm_scache_t *dscp,
@@ -306,7 +318,6 @@ RDR_BulkStatLookup( cm_scache_t *dscp,
                   code);
     }
 
-
     if (enump)
     {
         code = cm_BPlusDirEnumBulkStatOne(enump, scp);
@@ -326,7 +337,7 @@ RDR_BulkStatLookup( cm_scache_t *dscp,
 #define RDR_POP_WOW64              0x04
 #define RDR_POP_NO_GETSTATUS       0x08
 
-afs_uint32
+static afs_uint32
 RDR_PopulateCurrentEntry( IN  AFSDirEnumEntry * pCurrentEntry,
                           IN  DWORD             dwMaxEntryLength,
                           IN  cm_scache_t     * dscp,
@@ -336,6 +347,7 @@ RDR_PopulateCurrentEntry( IN  AFSDirEnumEntry * pCurrentEntry,
                           IN  wchar_t         * name,
                           IN  wchar_t         * shortName,
                           IN  DWORD             dwFlags,
+                          IN  afs_uint32        cmError,
                           OUT AFSDirEnumEntry **ppNextEntry,
                           OUT DWORD           * pdwRemainingLength)
 {
@@ -395,13 +407,13 @@ RDR_PopulateCurrentEntry( IN  AFSDirEnumEntry * pCurrentEntry,
              * status information.  If not, perform a bulk status lookup of multiple
              * entries in order to reduce the number of RPCs issued to the file server.
              */
-            if ((scp->flags & CM_SCACHEFLAG_EACCESS))
+            if (cm_EAccesFindEntry(userp, &scp->fid))
                 bMustFake = TRUE;
             else if (!cm_HaveCallback(scp)) {
                 lock_ReleaseWrite(&scp->rw);
                 code = RDR_BulkStatLookup(dscp, scp, userp, reqp);
                 if (code) {
-                    osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RXR_BulkStatLookup failed for scp=0x%p code=0x%x",
+                    osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RDR_BulkStatLookup failed for scp=0x%p code=0x%x",
                              scp, code);
                     return code;
                 }
@@ -415,9 +427,11 @@ RDR_PopulateCurrentEntry( IN  AFSDirEnumEntry * pCurrentEntry,
                     bMustFake = TRUE;
             }
         }
-
     }
 
+    /* Populate the error code */
+    smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
+
     /* Populate the real or fake data */
     pCurrentEntry->FileId.Cell = scp->fid.cell;
     pCurrentEntry->FileId.Volume = scp->fid.volume;
@@ -496,8 +510,8 @@ RDR_PopulateCurrentEntry( IN  AFSDirEnumEntry * pCurrentEntry,
     wcsncpy(wname, name, len);
     pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
 
-    osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry scp=0x%p fileType=%d",
-              scp, scp->fileType);
+    osi_Log3(afsd_logp, "RDR_PopulateCurrentEntry scp=0x%p fileType=%d dv=%u",
+              scp, scp->fileType, (afs_uint32)scp->dataVersion);
 
     if (!(dwFlags & RDR_POP_NO_GETSTATUS))
         cm_SyncOpDone( scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -618,7 +632,7 @@ RDR_PopulateCurrentEntry( IN  AFSDirEnumEntry * pCurrentEntry,
     return code;
 }
 
-afs_uint32
+static afs_uint32
 RDR_PopulateCurrentEntryNoScp( IN  AFSDirEnumEntry * pCurrentEntry,
                                IN  DWORD             dwMaxEntryLength,
                                IN  cm_scache_t     * dscp,
@@ -628,6 +642,7 @@ RDR_PopulateCurrentEntryNoScp( IN  AFSDirEnumEntry * pCurrentEntry,
                                IN  wchar_t         * name,
                                IN  wchar_t         * shortName,
                                IN  DWORD             dwFlags,
+                               IN  afs_uint32        cmError,
                                OUT AFSDirEnumEntry **ppNextEntry,
                                OUT DWORD           * pdwRemainingLength)
 {
@@ -659,6 +674,10 @@ RDR_PopulateCurrentEntryNoScp( IN  AFSDirEnumEntry * pCurrentEntry,
 
     dwEntryLength = sizeof(AFSDirEnumEntry);
 
+    /* Populate the error code */
+    smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
+
+    /* Populate the fake data */
     pCurrentEntry->FileId.Cell = fidp->cell;
     pCurrentEntry->FileId.Volume = fidp->volume;
     pCurrentEntry->FileId.Vnode = fidp->vnode;
@@ -732,9 +751,7 @@ RDR_EnumerateDirectory( IN cm_user_t *userp,
     cm_scache_t * dscp = NULL;
     cm_req_t      req;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_EnumerateDirectory FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
              DirID.Cell, DirID.Volume, DirID.Vnode, DirID.Unique);
@@ -768,7 +785,7 @@ RDR_EnumerateDirectory( IN cm_user_t *userp,
         fid.unique = DirID.Unique;
         fid.hash   = DirID.Hash;
 
-        code = cm_GetSCache(&fid, &dscp, userp, &req);
+        code = cm_GetSCache(&fid, NULL, &dscp, userp, &req);
         if (code) {
             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
             (*ResultCB)->ResultStatus = status;
@@ -807,16 +824,20 @@ RDR_EnumerateDirectory( IN cm_user_t *userp,
         return;
     }
 
+    osi_Log1(afsd_logp, "RDR_EnumerateDirectory dv=%u", (afs_uint32)dscp->dataVersion);
+
     /*
      * If there is no enumeration handle, then this is a new query
-     * and we must perform an enumeration for the specified object
+     * and we must perform an enumeration for the specified object.
      */
     if (QueryCB->EnumHandle == (ULONG_PTR)NULL) {
         cm_dirOp_t    dirop;
 
         code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
         if (code == 0) {
-            code = cm_BPlusDirEnumerate(dscp, userp, &req, TRUE, NULL, !bSkipStatus, &enump);
+            code = cm_BPlusDirEnumerate(dscp, userp, &req,
+                                        TRUE /* dir locked */, NULL /* no mask */,
+                                        TRUE /* fetch status? */, &enump);
             if (code) {
                 osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumerate failure code=0x%x",
                           code);
@@ -830,73 +851,74 @@ RDR_EnumerateDirectory( IN cm_user_t *userp,
         enump = (cm_direnum_t *)QueryCB->EnumHandle;
     }
 
-    if (enump && ResultBufferLength) {
-        cm_direnum_entry_t * entryp = NULL;
+    if (enump) {
+        if (ResultBufferLength == 0) {
+            code = cm_BPlusDirEnumBulkStat(enump);
+            if (code) {
+                osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumBulkStat failure code=0x%x",
+                          code);
+            }
+        } else {
+            cm_direnum_entry_t * entryp = NULL;
 
-      getnextentry:
-        if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
-            osi_Log0(afsd_logp, "RDR_EnumerateDirectory out of space, returning");
-            goto outofspace;
-        }
+            pDirEnumResp->SnapshotDataVersion.QuadPart = enump->dataVersion;
 
-        code = cm_BPlusDirNextEnumEntry(enump, &entryp);
+          getnextentry:
+            if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
+                osi_Log0(afsd_logp, "RDR_EnumerateDirectory out of space, returning");
+                goto outofspace;
+            }
 
-        if ((code == 0 || code == CM_ERROR_STOPNOW) && entryp) {
-            cm_scache_t *scp;
-            int stopnow = (code == CM_ERROR_STOPNOW);
+            code = cm_BPlusDirNextEnumEntry(enump, &entryp);
 
-            if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
-                osi_Log0(afsd_logp, "RDR_EnumerateDirectory skipping . or ..");
-                if (stopnow)
-                    goto outofspace;
-                goto getnextentry;
-            }
+            if ((code == 0 || code == CM_ERROR_STOPNOW) && entryp) {
+                cm_scache_t *scp = NULL;
+                int stopnow = (code == CM_ERROR_STOPNOW);
 
-            if ( FALSE /* bSkipStatus */) {
-                scp = cm_FindSCache(&entryp->fid);
-                code = 0;
-            } else {
-                code = cm_GetSCache(&entryp->fid, &scp, userp, &req);
-            }
+                if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
+                    osi_Log0(afsd_logp, "RDR_EnumerateDirectory skipping . or ..");
+                    if (stopnow)
+                        goto outofspace;
+                    goto getnextentry;
+                }
+
+                if (bSkipStatus) {
+                    code = cm_GetSCache(&entryp->fid, &dscp->fid, &scp, userp, &req);
+                    if (code) {
+                        osi_Log5(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure cell %u vol %u vnode %u uniq %u code=0x%x",
+                                 entryp->fid.cell, entryp->fid.volume, entryp->fid.vnode, entryp->fid.unique, code);
+                    }
+                } else {
+                    code = entryp->errorCode;
+                    scp = code ? NULL : cm_FindSCache(&entryp->fid);
+                }
 
-            if (!code) {
                 if (scp) {
-                    code = RDR_PopulateCurrentEntry(pCurrentEntry, dwMaxEntryLength,
+                    code = RDR_PopulateCurrentEntry( pCurrentEntry, dwMaxEntryLength,
                                                      dscp, scp, userp, &req,
                                                      entryp->name,
-                                                     cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
+                                                     cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
                                                      (bWow64 ? RDR_POP_WOW64 : 0) |
                                                      (bSkipStatus ? RDR_POP_NO_GETSTATUS : 0),
+                                                     code,
                                                      &pCurrentEntry, &dwMaxEntryLength);
                     cm_ReleaseSCache(scp);
                 } else {
                     code = RDR_PopulateCurrentEntryNoScp( pCurrentEntry, dwMaxEntryLength,
                                                           dscp, &entryp->fid, userp, &req,
                                                           entryp->name,
-                                                          cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
+                                                          cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
                                                           (bWow64 ? RDR_POP_WOW64 : 0),
+                                                          code,
                                                           &pCurrentEntry, &dwMaxEntryLength);
                 }
                 if (stopnow)
                     goto outofspace;
                 goto getnextentry;
-            } else {
-                osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure scp=0x%p code=0x%x",
-                          scp, code);
-                if (stopnow)
-                    goto outofspace;
-                goto getnextentry;
             }
         }
     }
 
-    if (enump && ResultBufferLength == 0) {
-        code = cm_BPlusDirEnumBulkStat(enump);
-        if (code) {
-            osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumBulkStat failure code=0x%x",
-                      code);
-        }
-    }
   outofspace:
 
     if (code || enump->next == enump->count || ResultBufferLength == 0) {
@@ -918,6 +940,7 @@ RDR_EnumerateDirectory( IN cm_user_t *userp,
         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwMaxEntryLength;
 
         pDirEnumResp->EnumHandle = (ULONG_PTR) enump;
+        pDirEnumResp->CurrentDataVersion.QuadPart = dscp->dataVersion;
     }
 
     if (dscp)
@@ -938,8 +961,9 @@ RDR_EvaluateNodeByName( IN cm_user_t *userp,
                         IN DWORD    ResultBufferLength,
                         IN OUT AFSCommResult **ResultCB)
 {
+    AFSFileEvalResultCB *pEvalResultCB = NULL;
     AFSDirEnumEntry * pCurrentEntry;
-    size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
+    size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
     afs_uint32  code = 0;
     cm_scache_t * scp = NULL;
     cm_scache_t * dscp = NULL;
@@ -954,9 +978,7 @@ RDR_EvaluateNodeByName( IN cm_user_t *userp,
 
     StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_EvaluateNodeByName parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
              ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
@@ -979,9 +1001,13 @@ RDR_EvaluateNodeByName( IN cm_user_t *userp,
     }
 
     memset(*ResultCB, 0, size);
-    (*ResultCB)->ResultBufferLength = ResultBufferLength;
-    if (ResultBufferLength)
-        pCurrentEntry = (AFSDirEnumEntry *)&(*ResultCB)->ResultData;
+    (*ResultCB)->ResultBufferLength = 0;
+    dwRemaining = ResultBufferLength;
+    if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
+        pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
+        pCurrentEntry = &pEvalResultCB->DirEnum;
+        dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
+    }
 
     if (ParentID.Cell != 0) {
         parentFid.cell   = ParentID.Cell;
@@ -990,10 +1016,12 @@ RDR_EvaluateNodeByName( IN cm_user_t *userp,
         parentFid.unique = ParentID.Unique;
         parentFid.hash   = ParentID.Hash;
 
-        code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+        code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
         if (code) {
             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
             (*ResultCB)->ResultStatus = status;
+            if ( status == STATUS_INVALID_HANDLE)
+                status = STATUS_OBJECT_PATH_INVALID;
             osi_Log2(afsd_logp, "RDR_EvaluateNodeByName cm_GetSCache parentFID failure code=0x%x status=0x%x",
                       code, status);
             free(wszName);
@@ -1040,7 +1068,6 @@ RDR_EvaluateNodeByName( IN cm_user_t *userp,
          */
         StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
         StringCbCatNW(wszName, cbName, FileName, FileNameLength);
-        cm_strlwr_utf16(wszName);
         bVol = TRUE;
 
         code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
@@ -1049,7 +1076,9 @@ RDR_EvaluateNodeByName( IN cm_user_t *userp,
     if (code == 0 && scp) {
         wchar_t shortName[13]=L"";
 
-        if (bVol) {
+        if (!cm_shortNames) {
+            shortName[0] = L'\0';
+        } else if (bVol) {
             cm_Gen8Dot3VolNameW(scp->fid.cell, scp->fid.volume, shortName, NULL);
         } else if (!cm_Is8Dot3(wszName)) {
             cm_dirFid_t dfid;
@@ -1059,15 +1088,15 @@ RDR_EvaluateNodeByName( IN cm_user_t *userp,
 
             cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
         } else {
-            shortName[0] = '\0';
+            shortName[0] = L'\0';
         }
 
-        code = RDR_PopulateCurrentEntry(pCurrentEntry, ResultBufferLength,
+        code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
                                         dscp, scp, userp, &req,
                                         FileName, shortName,
                                         (bWow64 ? RDR_POP_WOW64 : 0) |
                                         (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
-                                        NULL, &dwRemaining);
+                                        0, NULL, &dwRemaining);
         if (bHoldFid)
             RDR_FlagScpInUse( scp, FALSE );
         cm_ReleaseSCache(scp);
@@ -1078,6 +1107,7 @@ RDR_EvaluateNodeByName( IN cm_user_t *userp,
             osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
                       code, status);
         } else {
+            pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
             (*ResultCB)->ResultStatus = STATUS_SUCCESS;
             (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
             osi_Log0(afsd_logp, "RDR_EvaluateNodeByName SUCCESS");
@@ -1107,8 +1137,9 @@ RDR_EvaluateNodeByID( IN cm_user_t *userp,
                       IN DWORD     ResultBufferLength,
                       IN OUT AFSCommResult **ResultCB)
 {
-    AFSDirEnumEntry * pCurrentEntry;
-    size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
+    AFSFileEvalResultCB *pEvalResultCB = NULL;
+    AFSDirEnumEntry * pCurrentEntry = NULL;
+    size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
     afs_uint32  code = 0;
     cm_scache_t * scp = NULL;
     cm_scache_t * dscp = NULL;
@@ -1130,23 +1161,19 @@ RDR_EvaluateNodeByID( IN cm_user_t *userp,
     }
 
     memset(*ResultCB, 0, size);
-    (*ResultCB)->ResultBufferLength = ResultBufferLength;
+    (*ResultCB)->ResultBufferLength = 0;
     dwRemaining = ResultBufferLength;
-    if (ResultBufferLength)
-        pCurrentEntry = (AFSDirEnumEntry *)&(*ResultCB)->ResultData;
+    if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
+        pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
+        pCurrentEntry = &pEvalResultCB->DirEnum;
+        dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
+    }
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     if (SourceID.Cell != 0) {
-        Fid.cell   = SourceID.Cell;
-        Fid.volume = SourceID.Volume;
-        Fid.vnode  = SourceID.Vnode;
-        Fid.unique = SourceID.Unique;
-        Fid.hash   = SourceID.Hash;
-
-        code = cm_GetSCache(&Fid, &scp, userp, &req);
+        cm_SetFid(&Fid, SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
+        code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
         if (code) {
             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
             (*ResultCB)->ResultStatus = status;
@@ -1162,10 +1189,12 @@ RDR_EvaluateNodeByID( IN cm_user_t *userp,
 
     if (ParentID.Cell != 0) {
         cm_SetFid(&parentFid, ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
-        code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+        code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
         if (code) {
             cm_ReleaseSCache(scp);
             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+            if ( status == STATUS_INVALID_HANDLE)
+                status = STATUS_OBJECT_PATH_INVALID;
             (*ResultCB)->ResultStatus = status;
             osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
                       code, status);
@@ -1176,10 +1205,12 @@ RDR_EvaluateNodeByID( IN cm_user_t *userp,
         cm_HoldSCache(dscp);
     } else if (scp->parentVnode) {
         cm_SetFid(&parentFid, SourceID.Cell, SourceID.Volume, scp->parentVnode, scp->parentUnique);
-        code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+        code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
         if (code) {
             cm_ReleaseSCache(scp);
             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+            if ( status == STATUS_INVALID_HANDLE)
+                status = STATUS_OBJECT_PATH_INVALID;
             (*ResultCB)->ResultStatus = status;
             osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
                       code, status);
@@ -1217,11 +1248,11 @@ RDR_EvaluateNodeByID( IN cm_user_t *userp,
         return;
     }
 
-    code = RDR_PopulateCurrentEntry(pCurrentEntry, ResultBufferLength,
+    code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
                                     dscp, scp, userp, &req, NULL, NULL,
                                     (bWow64 ? RDR_POP_WOW64 : 0) |
                                     (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
-                                    NULL, &dwRemaining);
+                                    0, NULL, &dwRemaining);
 
     if (bHoldFid)
         RDR_FlagScpInUse( scp, FALSE );
@@ -1234,6 +1265,8 @@ RDR_EvaluateNodeByID( IN cm_user_t *userp,
         osi_Log2(afsd_logp, "RDR_EvaluateNodeByID FAILURE code=0x%x status=0x%x",
                  code, status);
     } else {
+        pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
+
         (*ResultCB)->ResultStatus = STATUS_SUCCESS;
         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
         osi_Log0(afsd_logp, "RDR_EvaluateNodeByID SUCCESS");
@@ -1270,9 +1303,7 @@ RDR_CreateFileEntry( IN cm_user_t *userp,
               CreateCB->ParentId.Vnode, CreateCB->ParentId.Unique);
     osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
     memset(&setAttr, 0, sizeof(cm_attr_t));
 
     *ResultCB = (AFSCommResult *)malloc(size);
@@ -1291,10 +1322,12 @@ RDR_CreateFileEntry( IN cm_user_t *userp,
     parentFid.unique = CreateCB->ParentId.Unique;
     parentFid.hash   = CreateCB->ParentId.Hash;
 
-    code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+    code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
+        if ( status == STATUS_INVALID_HANDLE)
+            status = STATUS_OBJECT_PATH_INVALID;
         osi_Log2(afsd_logp, "RDR_CreateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
                   code, status);
         return;
@@ -1382,18 +1415,20 @@ RDR_CreateFileEntry( IN cm_user_t *userp,
         cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         lock_ReleaseWrite(&dscp->rw);
 
-        dfid.vnode = htonl(scp->fid.vnode);
-        dfid.unique = htonl(scp->fid.unique);
+        if (cm_shortNames) {
+            dfid.vnode = htonl(scp->fid.vnode);
+            dfid.unique = htonl(scp->fid.unique);
 
-        if (!cm_Is8Dot3(FileName))
-            cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
-        else
-            shortName[0] = '\0';
+            if (!cm_Is8Dot3(FileName))
+                cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
+            else
+                shortName[0] = '\0';
+        }
 
         code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
                                         dscp, scp, userp, &req, FileName, shortName,
                                         RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
-                                        NULL, &dwRemaining);
+                                        0, NULL, &dwRemaining);
 
         if (bHoldFid)
             RDR_FlagScpInUse( scp, FALSE );
@@ -1436,9 +1471,7 @@ RDR_UpdateFileEntry( IN cm_user_t *userp,
     DWORD               status;
     BOOL                bScpLocked = FALSE;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
     memset(&setAttr, 0, sizeof(cm_attr_t));
 
     osi_Log4(afsd_logp, "RDR_UpdateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
@@ -1464,10 +1497,12 @@ RDR_UpdateFileEntry( IN cm_user_t *userp,
     parentFid.unique = UpdateCB->ParentId.Unique;
     parentFid.hash   = UpdateCB->ParentId.Hash;
 
-    code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+    code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
+        if ( status == STATUS_INVALID_HANDLE)
+            status = STATUS_OBJECT_PATH_INVALID;
         osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
                   code, status);
         return;
@@ -1505,7 +1540,7 @@ RDR_UpdateFileEntry( IN cm_user_t *userp,
     Fid.unique = FileId.Unique;
     Fid.hash   = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, &dscp->fid, &scp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -1598,10 +1633,12 @@ RDR_UpdateFileEntry( IN cm_user_t *userp,
 
         pResultCB = (AFSFileUpdateResultCB *)(*ResultCB)->ResultData;
 
+        pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
+
         code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
                                         dscp, scp, userp, &req, NULL, NULL,
                                         RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
-                                        NULL, &dwRemaining);
+                                        0, NULL, &dwRemaining);
         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
         osi_Log0(afsd_logp, "RDR_UpdateFileEntry SUCCESS");
     } else {
@@ -1630,7 +1667,8 @@ RDR_CleanupFileEntry( IN cm_user_t *userp,
                       IN DWORD ResultBufferLength,
                       IN OUT AFSCommResult **ResultCB)
 {
-    size_t size = sizeof(AFSCommResult);
+    AFSFileCleanupResultCB *pResultCB = NULL;
+    size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
     cm_fid_t            Fid;
     cm_fid_t            parentFid;
     afs_uint32          code = 0;
@@ -1647,9 +1685,7 @@ RDR_CleanupFileEntry( IN cm_user_t *userp,
     BOOL                bFlushFile = FALSE;
     cm_key_t            key;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
     memset(&setAttr, 0, sizeof(cm_attr_t));
 
     osi_Log4(afsd_logp, "RDR_CleanupFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
@@ -1676,9 +1712,11 @@ RDR_CleanupFileEntry( IN cm_user_t *userp,
     parentFid.hash   = CleanupCB->ParentId.Hash;
 
     if (parentFid.cell) {
-        code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+        code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
         if (code) {
             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+            if ( status == STATUS_INVALID_HANDLE)
+                status = STATUS_OBJECT_PATH_INVALID;
             (*ResultCB)->ResultStatus = status;
             osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
                      code, status);
@@ -1716,7 +1754,7 @@ RDR_CleanupFileEntry( IN cm_user_t *userp,
     Fid.unique = FileId.Unique;
     Fid.hash   = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, dscp ? &dscp->fid : NULL, &scp, userp, &req);
     if (code) {
         osi_Log1(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache object FID failure code=0x%x",
                  code);
@@ -1734,7 +1772,9 @@ RDR_CleanupFileEntry( IN cm_user_t *userp,
     }
     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
 
-    if (scp->redirBufCount > 0) {
+    if ((bLastHandle || bFlushFile) &&
+        scp->redirBufCount > 0)
+    {
         LARGE_INTEGER heldExtents;
         AFSFileExtentCB extentList[1024];
         DWORD extentCount = 0;
@@ -1796,97 +1836,85 @@ RDR_CleanupFileEntry( IN cm_user_t *userp,
         scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
     }
 
-    if (bLastHandle || bFlushFile) {
-        if (bScpLocked) {
-            lock_ReleaseWrite(&scp->rw);
-            bScpLocked = FALSE;
-        }
-        code = cm_FSync(scp, userp, &req, bScpLocked);
-        if (bLastHandle && code)
-            goto on_error;
-    }
+    /* If not a readonly object, flush dirty data and update metadata */
+    if (!(scp->flags & CM_SCACHEFLAG_RO)) {
+        if ((bLastHandle || bFlushFile) &&
+             buf_DirtyBuffersExist(&scp->fid)) {
+            if (!bScpLocked) {
+                lock_ObtainWrite(&scp->rw);
+                bScpLocked = TRUE;
+            }
+            code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
+                             CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+            if (code == 0) {
+                if (bScpLocked) {
+                    lock_ReleaseWrite(&scp->rw);
+                    bScpLocked = FALSE;
+                }
 
-    if (bUnlockFile || bDeleteFile) {
-        if (!bScpLocked) {
-            lock_ObtainWrite(&scp->rw);
-            bScpLocked = TRUE;
-        }
-        code = cm_SyncOp(scp, NULL, userp, &req, 0,
-                          CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
-        if (code) {
-            osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
-                     scp, code);
-            goto on_error;
+                code = cm_FSync(scp, userp, &req, bScpLocked);
+            }
+            if (bLastHandle && code)
+                goto unlock;
         }
 
-        key = cm_GenerateKey(CM_SESSION_IFS, CleanupCB->ProcessId, 0);
-
-        /* the scp is now locked and current */
-        code = cm_UnlockByKey(scp, key,
-                              bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
-                              userp, &req);
-
-        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
-
-        if (code)
-            goto on_error;
-    }
+        if (CleanupCB->ChangeTime.QuadPart) {
 
-    if (CleanupCB->ChangeTime.QuadPart) {
+            if (scp->fileType == CM_SCACHETYPE_FILE) {
+                /* Do not set length and other attributes at the same time */
+                if (scp->length.QuadPart != CleanupCB->AllocationSize.QuadPart) {
+                    osi_Log2(afsd_logp, "RDR_CleanupFileEntry Length Change 0x%x -> 0x%x",
+                             (afs_uint32)scp->length.QuadPart, (afs_uint32)CleanupCB->AllocationSize.QuadPart);
+                    setAttr.mask |= CM_ATTRMASK_LENGTH;
+                    setAttr.length.LowPart = CleanupCB->AllocationSize.LowPart;
+                    setAttr.length.HighPart = CleanupCB->AllocationSize.HighPart;
 
-        if (scp->fileType == CM_SCACHETYPE_FILE) {
-            /* Do not set length and other attributes at the same time */
-            if (scp->length.QuadPart != CleanupCB->AllocationSize.QuadPart) {
-                osi_Log2(afsd_logp, "RDR_CleanupFileEntry Length Change 0x%x -> 0x%x",
-                          (afs_uint32)scp->length.QuadPart, (afs_uint32)CleanupCB->AllocationSize.QuadPart);
-                setAttr.mask |= CM_ATTRMASK_LENGTH;
-                setAttr.length.LowPart = CleanupCB->AllocationSize.LowPart;
-                setAttr.length.HighPart = CleanupCB->AllocationSize.HighPart;
-
-                if (bScpLocked) {
-                    lock_ReleaseWrite(&scp->rw);
-                    bScpLocked = FALSE;
+                    if (bScpLocked) {
+                        lock_ReleaseWrite(&scp->rw);
+                        bScpLocked = FALSE;
+                    }
+                    code = cm_SetAttr(scp, &setAttr, userp, &req);
+                    if (code)
+                        goto unlock;
+                    setAttr.mask = 0;
                 }
-                code = cm_SetAttr(scp, &setAttr, userp, &req);
-                if (code)
-                    goto on_error;
-                setAttr.mask = 0;
             }
-        }
 
-        if (!bScpLocked) {
-            lock_ObtainWrite(&scp->rw);
-            bScpLocked = TRUE;
-        }
+            if (!bScpLocked) {
+                lock_ObtainWrite(&scp->rw);
+                bScpLocked = TRUE;
+            }
 
-        if ((scp->unixModeBits & 0200) && (CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
-            setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
-            setAttr.unixModeBits = scp->unixModeBits & ~0222;
-        } else if (!(scp->unixModeBits & 0200) && !(CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
-            setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
-            setAttr.unixModeBits = scp->unixModeBits | 0222;
+            if ((scp->unixModeBits & 0200) && (CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
+                setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
+                setAttr.unixModeBits = scp->unixModeBits & ~0222;
+            } else if (!(scp->unixModeBits & 0200) && !(CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
+                setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
+                setAttr.unixModeBits = scp->unixModeBits | 0222;
+            }
         }
-    }
 
-    if (CleanupCB->LastWriteTime.QuadPart) {
-        ft.dwLowDateTime = CleanupCB->LastWriteTime.LowPart;
-        ft.dwHighDateTime = CleanupCB->LastWriteTime.HighPart;
+        if (CleanupCB->LastWriteTime.QuadPart) {
+            ft.dwLowDateTime = CleanupCB->LastWriteTime.LowPart;
+            ft.dwHighDateTime = CleanupCB->LastWriteTime.HighPart;
 
-        cm_UnixTimeFromLargeSearchTime(&clientModTime, &ft);
-        if (scp->clientModTime != clientModTime) {
-            setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
-            setAttr.clientModTime = clientModTime;
+            cm_UnixTimeFromLargeSearchTime(&clientModTime, &ft);
+            if (scp->clientModTime != clientModTime) {
+                setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
+                setAttr.clientModTime = clientModTime;
+            }
         }
-    }
 
-    /* call setattr */
-    if (setAttr.mask) {
-        lock_ReleaseWrite(&scp->rw);
-        bScpLocked = FALSE;
-        code = cm_SetAttr(scp, &setAttr, userp, &req);
-    } else
-        code = 0;
+        /* call setattr */
+        if (setAttr.mask) {
+            lock_ReleaseWrite(&scp->rw);
+            bScpLocked = FALSE;
+            code = cm_SetAttr(scp, &setAttr, userp, &req);
+        } else
+            code = 0;
+    }
 
+  unlock:
     /* Now drop the lock enforcing the share access */
     if ( CleanupCB->FileAccess != AFS_FILE_ACCESS_NOLOCK) {
         unsigned int sLockType;
@@ -1925,13 +1953,39 @@ RDR_CleanupFileEntry( IN cm_user_t *userp,
         }
     }
 
+    if (bUnlockFile || bDeleteFile) {
+        if (!bScpLocked) {
+            lock_ObtainWrite(&scp->rw);
+            bScpLocked = TRUE;
+        }
+        code = cm_SyncOp(scp, NULL, userp, &req, 0,
+                          CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+        if (code) {
+            osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
+                     scp, code);
+            goto on_error;
+        }
+
+        key = cm_GenerateKey(CM_SESSION_IFS, CleanupCB->ProcessId, 0);
+
+        /* the scp is now locked and current */
+        code = cm_UnlockByKey(scp, key,
+                              bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
+                              userp, &req);
+
+        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+
+        if (code)
+            goto on_error;
+    }
+
   on_error:
     if (bDscpLocked)
         lock_ReleaseWrite(&dscp->rw);
     if (bScpLocked)
         lock_ReleaseWrite(&scp->rw);
 
-    if (dscp && bDeleteFile) {
+    if (code == 0 && dscp && bDeleteFile) {
         WCHAR FileName[260];
 
         StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
@@ -1943,16 +1997,24 @@ RDR_CleanupFileEntry( IN cm_user_t *userp,
     }
 
     if (code == 0) {
+        if ( ResultBufferLength >=  sizeof( AFSFileCleanupResultCB))
+        {
+            (*ResultCB)->ResultBufferLength = sizeof( AFSFileCleanupResultCB);
+            pResultCB = (AFSFileCleanupResultCB *)&(*ResultCB)->ResultData;
+            pResultCB->ParentDataVersion.QuadPart = dscp ? dscp->dataVersion : 0;
+        } else {
+            (*ResultCB)->ResultBufferLength = 0;
+        }
+
         (*ResultCB)->ResultStatus = 0;
-        (*ResultCB)->ResultBufferLength = 0;
         osi_Log0(afsd_logp, "RDR_CleanupFileEntry SUCCESS");
     } else {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
-        (*ResultCB)->ResultBufferLength = 0;
         osi_Log2(afsd_logp, "RDR_CleanupFileEntry FAILURE code=0x%x status=0x%x",
                   code, status);
     }
+
     if (scp)
         cm_ReleaseSCache(scp);
     if (dscp)
@@ -1995,9 +2057,7 @@ RDR_DeleteFileEntry( IN cm_user_t *userp,
              osi_LogSaveStringW(afsd_logp, FileName),
              bCheckOnly);
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
     memset(&setAttr, 0, sizeof(cm_attr_t));
 
     *ResultCB = (AFSCommResult *)malloc( size);
@@ -2016,9 +2076,11 @@ RDR_DeleteFileEntry( IN cm_user_t *userp,
     parentFid.unique = ParentId.Unique;
     parentFid.hash   = ParentId.Hash;
 
-    code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+    code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+        if ( status == STATUS_INVALID_HANDLE)
+            status = STATUS_OBJECT_PATH_INVALID;
         (*ResultCB)->ResultStatus = status;
         osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
                   code, status);
@@ -2152,8 +2214,12 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
     DWORD                  TargetFileNameLength = pRenameCB->TargetNameLength;
     cm_fid_t               SourceParentFid;
     cm_fid_t               TargetParentFid;
+    cm_fid_t              SourceFid;
+    cm_fid_t              OrigTargetFid = {0,0,0,0,0};
+    cm_fid_t              TargetFid;
     cm_scache_t *          oldDscp;
     cm_scache_t *          newDscp;
+    cm_dirOp_t dirop;
     wchar_t                shortName[13];
     wchar_t                SourceFileName[260];
     wchar_t                TargetFileName[260];
@@ -2162,9 +2228,7 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
     afs_uint32             code;
     DWORD                  status;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
     StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
@@ -2208,10 +2272,12 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
     TargetParentFid.unique = TargetParentId.Unique;
     TargetParentFid.hash   = TargetParentId.Hash;
 
-    code = cm_GetSCache(&SourceParentFid, &oldDscp, userp, &req);
+    code = cm_GetSCache(&SourceParentFid, NULL, &oldDscp, userp, &req);
     if (code) {
         osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache source parent failed code 0x%x", code);
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+        if ( status == STATUS_INVALID_HANDLE)
+            status = STATUS_OBJECT_PATH_INVALID;
         (*ResultCB)->ResultStatus = status;
         return;
     }
@@ -2222,6 +2288,8 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
     if (code) {
         osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp oldDscp 0x%p failed code 0x%x", oldDscp, code);
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+        if ( status == STATUS_INVALID_HANDLE)
+            status = STATUS_OBJECT_PATH_INVALID;
         (*ResultCB)->ResultStatus = status;
         lock_ReleaseWrite(&oldDscp->rw);
         cm_ReleaseSCache(oldDscp);
@@ -2239,7 +2307,7 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
         return;
     }
 
-    code = cm_GetSCache(&TargetParentFid, &newDscp, userp, &req);
+    code = cm_GetSCache(&TargetParentFid, NULL, &newDscp, userp, &req);
     if (code) {
         osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target parent failed code 0x%x", code);
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
@@ -2273,11 +2341,17 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
         return;
     }
 
+    /* Obtain the original FID just for debugging purposes */
+    code = cm_BeginDirOp( oldDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
+    if (code == 0) {
+        code = cm_BPlusDirLookup(&dirop, SourceFileName, &SourceFid);
+        code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
+        cm_EndDirOp(&dirop);
+    }
+
     code = cm_Rename( oldDscp, NULL, SourceFileName,
                       newDscp, TargetFileName, userp, &req);
     if (code == 0) {
-        cm_dirOp_t dirop;
-        cm_fid_t   targetFid;
         cm_scache_t *scp = 0;
         DWORD dwRemaining;
 
@@ -2293,7 +2367,7 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
 
         code = cm_BeginDirOp( newDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
         if (code == 0) {
-            code = cm_BPlusDirLookup(&dirop, TargetFileName, &targetFid);
+            code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
             cm_EndDirOp(&dirop);
         }
 
@@ -2307,10 +2381,10 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
         }
 
         osi_Log4(afsd_logp, "RDR_RenameFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
-                  targetFid.cell,  targetFid.volume,
-                  targetFid.vnode, targetFid.unique);
+                  TargetFid.cell,  TargetFid.volume,
+                  TargetFid.vnode, TargetFid.unique);
 
-        code = cm_GetSCache(&targetFid, &scp, userp, &req);
+        code = cm_GetSCache(&TargetFid, &newDscp->fid, &scp, userp, &req);
         if (code) {
             osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target failed code 0x%x", code);
             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
@@ -2338,18 +2412,20 @@ RDR_RenameFileEntry( IN cm_user_t *userp,
         cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
         lock_ReleaseWrite(&scp->rw);
 
-        dfid.vnode = htonl(scp->fid.vnode);
-        dfid.unique = htonl(scp->fid.unique);
+        if (cm_shortNames) {
+            dfid.vnode = htonl(scp->fid.vnode);
+            dfid.unique = htonl(scp->fid.unique);
 
-        if (!cm_Is8Dot3(TargetFileName))
-            cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
-        else
-            shortName[0] = '\0';
+            if (!cm_Is8Dot3(TargetFileName))
+                cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
+            else
+                shortName[0] = '\0';
+        }
 
         RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
                                  newDscp, scp, userp, &req, TargetFileName, shortName,
                                  RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
-                                 NULL, &dwRemaining);
+                                 0, NULL, &dwRemaining);
         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
         cm_ReleaseSCache(scp);
 
@@ -2383,9 +2459,7 @@ RDR_FlushFileEntry( IN cm_user_t *userp,
     char        dbgstr[1024];
 #endif
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_FlushFileEntry File FID cell 0x%x vol 0x%x vno 0x%x uniq 0x%x",
               FileId.Cell, FileId.Volume,
@@ -2415,7 +2489,7 @@ RDR_FlushFileEntry( IN cm_user_t *userp,
     Fid.unique = FileId.Unique;
     Fid.hash = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -2564,9 +2638,7 @@ RDR_OpenFileEntry( IN cm_user_t *userp,
     cm_req_t    req;
     DWORD       status;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_OpenFileEntry File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
               FileId.Cell, FileId.Volume,
@@ -2591,7 +2663,7 @@ RDR_OpenFileEntry( IN cm_user_t *userp,
     Fid.unique = FileId.Unique;
     Fid.hash = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -2742,9 +2814,7 @@ RDR_ReleaseFileAccess( IN cm_user_t *userp,
     cm_req_t    req;
     DWORD       status;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_ReleaseFileAccess File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
               FileId.Cell, FileId.Volume,
@@ -2768,7 +2838,7 @@ RDR_ReleaseFileAccess( IN cm_user_t *userp,
     Fid.unique = FileId.Unique;
     Fid.hash = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -2887,11 +2957,6 @@ RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_
     FileId.Unique = scp->fid.unique;
     FileId.Hash = scp->fid.hash;
 
-    if ((GetTickCount() - reqp->startTime) / 1000 > HardDeadtimeout * 5) {
-        RDR_SetFileStatus( &scp->fid, STATUS_IO_TIMEOUT);
-        return 0;
-    }
-
     fetched.LowPart = 0;
     fetched.HighPart = 0;
     tblocksize = ConvertLongToLargeInteger(cm_data.buf_blockSize);
@@ -2918,12 +2983,12 @@ RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_
         osi_Log2(afsd_logp, "RDR_BkgFetch cm_SyncOp failure scp=0x%p code=0x%x",
                  scp, code);
         smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
-        RDR_SetFileStatus( &scp->fid, status);
+        RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
         return code;
     }
     lock_ReleaseWrite(&scp->rw);
 
-    dwResultBufferLength = (DWORD)(sizeof( AFSSetFileExtentsCB) + sizeof( AFSSetFileExtentsCB) * (length.QuadPart / cm_data.blockSize + 1));
+    dwResultBufferLength = (DWORD)(sizeof( AFSSetFileExtentsCB) + sizeof( AFSFileExtentCB) * (length.QuadPart / cm_data.blockSize + 1));
     pResultCB = (AFSSetFileExtentsCB *)malloc( dwResultBufferLength );
     if (!pResultCB)
         return CM_ERROR_RETRY;
@@ -2949,7 +3014,7 @@ RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_
              * we need to re-queue this extent fetch.
              */
             force_retry = 1;
-            continue;
+            break;
         }
 
         if (!rwheld) {
@@ -2959,9 +3024,6 @@ RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_
 
         code = cm_GetBuffer(scp, bufp, NULL, userp, reqp);
         if (code == 0) {
-            if (bufp->flags & CM_BUF_DIRTY)
-                cm_BufWrite(scp, &bufp->offset, cm_chunkSize, CM_BUF_WRITE_SCP_LOCKED, userp, reqp);
-
             if (!(bufp->qFlags & CM_BUF_QREDIR)) {
 #ifdef VALIDATE_CHECK_SUM
 #ifdef ODS_DEBUG
@@ -2969,6 +3031,9 @@ RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_
                 char dbgstr[1024];
 #endif
 #endif
+                if (bufp->flags & CM_BUF_DIRTY)
+                    cm_BufWrite(scp, &bufp->offset, cm_data.buf_blockSize, CM_BUF_WRITE_SCP_LOCKED, userp, reqp);
+
                 lock_ObtainWrite(&buf_globalLock);
                 if (!(bufp->flags & CM_BUF_DIRTY) &&
                     bufp->cmFlags == 0 &&
@@ -3050,6 +3115,7 @@ RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_
                  * non-fatal errors.  re-queue the exent
                  */
                 code = CM_ERROR_RETRY;
+                force_retry = 1;
             }
         }
 
@@ -3077,7 +3143,7 @@ RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_
 
     if (reportErrorToRedir) {
         smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
-        RDR_SetFileStatus( &scp->fid, status);
+        RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
     }
 
     osi_Log4(afsd_logp, "Ending BKG Fetch scp 0x%p code 0x%x fetched 0x%x:%x",
@@ -3109,9 +3175,7 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
     cm_req_t    req;
     BOOLEAN     bBufRelease = TRUE;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
     req.flags |= CM_REQ_NORETRY;
 
     osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
@@ -3139,7 +3203,7 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
     Fid.unique = FileId.Unique;
     Fid.hash = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         osi_Log1(afsd_logp, "RDR_RequestFileExtentsAsync cm_GetSCache FID failure code=0x%x",
                   code);
@@ -3161,7 +3225,7 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
         osi_Log2(afsd_logp, "RDR_RequestFileExtentsAsync cm_SyncOp failure scp=0x%p code=0x%x",
                  scp, code);
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
-        RDR_SetFileStatus( &scp->fid, status);
+        RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
         return FALSE;
     }
 
@@ -3199,7 +3263,7 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
                     break;
                 default:
                     smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
-                    RDR_SetFileStatus(&FileId, status);
+                    RDR_SetFileStatus(&FileId, &userp->authgroup, status);
                     bHaveBuffer = FALSE;
                     code = 0;
                 }
@@ -3216,20 +3280,25 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
                     minLength = scp->length;
 
                 if (LargeIntegerGreaterThanOrEqualTo(bufp->offset, minLength)) {
-                    memset(bufp->datap, 0, cm_data.buf_blockSize);
-                    bufp->dataVersion = scp->dataVersion;
-                    bHaveBuffer = TRUE;
+                    if (!bHaveBuffer) {
+                        memset(bufp->datap, 0, cm_data.buf_blockSize);
+                        bufp->dataVersion = scp->dataVersion;
+                        bHaveBuffer = TRUE;
+                    }
+                    else if (bufp->dataVersion == CM_BUF_VERSION_BAD) {
+                        bufp->dataVersion = scp->dataVersion;
+                    }
                 }
-                lock_ReleaseRead(&scp->rw);
-
-                if ((RequestExtentsCB->Flags & AFS_EXTENT_FLAG_CLEAN) &&
-                     ByteOffset.QuadPart <= bufp->offset.QuadPart &&
-                     EndOffset.QuadPart >= bufp->offset.QuadPart + cm_data.blockSize) {
+                else if ((RequestExtentsCB->Flags & AFS_EXTENT_FLAG_CLEAN) &&
+                         ByteOffset.QuadPart <= bufp->offset.QuadPart &&
+                         EndOffset.QuadPart >= bufp->offset.QuadPart + cm_data.blockSize)
+                {
                     memset(bufp->datap, 0, cm_data.blockSize);
                     bufp->dataVersion = scp->dataVersion;
                     buf_SetDirty(bufp, &req, 0, cm_data.blockSize, userp);
                     bHaveBuffer = TRUE;
                 }
+                lock_ReleaseRead(&scp->rw);
             }
 
             /*
@@ -3359,6 +3428,7 @@ RDR_ReleaseFileExtents( IN cm_user_t *userp,
     cm_req_t    req;
     int         dirty = 0;
     int         released = 0;
+    int         deleted = 0;
     DWORD       status;
 #ifdef ODS_DEBUG
 #ifdef VALIDATE_CHECK_SUM
@@ -3367,9 +3437,7 @@ RDR_ReleaseFileExtents( IN cm_user_t *userp,
     char dbgstr[1024];
 #endif
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
               FileId.Cell, FileId.Volume,
@@ -3390,7 +3458,7 @@ RDR_ReleaseFileExtents( IN cm_user_t *userp,
     Fid.unique = FileId.Unique;
     Fid.hash = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -3398,13 +3466,20 @@ RDR_ReleaseFileExtents( IN cm_user_t *userp,
                   code, status);
     }
 
+    deleted = scp && (scp->flags & CM_SCACHEFLAG_DELETED);
+
     /*
      * We do not stop processing as a result of being unable to find the cm_scache object.
      * If this occurs something really bad has happened since the cm_scache object must have
      * been recycled while extents were held by the redirector.  However, we will be resilient
      * and carry on without it.
+     *
+     * If the file is known to be deleted, there is no point attempting to ask the
+     * file server about it or update the attributes.
      */
-    if (scp && ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart) {
+    if (scp && ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart &&
+        !deleted)
+    {
         cm_attr_t setAttr;
 
         memset(&setAttr, 0, sizeof(cm_attr_t));
@@ -3782,7 +3857,12 @@ RDR_ReleaseFileExtents( IN cm_user_t *userp,
 
     if (scp) {
         if (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_FLUSH) {
-            code = buf_CleanVnode(scp, userp, &req);
+            lock_ObtainWrite(&scp->rw);
+            code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
+                             CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+            lock_ReleaseWrite(&scp->rw);
+            if (code == 0)
+                code = cm_FSync(scp, userp, &req, FALSE);
         }
         else if (dirty) {
             osi_hyper_t offset = {0,0};
@@ -3851,7 +3931,7 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
 #endif
     char dbgstr[1024];
 #endif
-    RDR_InitReq(&req);
+    RDR_InitReq(&req, FALSE);
 
     for ( fileno = 0, pNextFileCB = &ReleaseFileExtentsResultCB->Files[0];
           fileno < ReleaseFileExtentsResultCB->FileCount;
@@ -3862,6 +3942,7 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
         cm_scache_t *    scp = NULL;
         int              dirty = 0;
         int              released = 0;
+        int              deleted = 0;
         char * p;
 
         userp = RDR_UserFromAuthGroup( &pFileCB->AuthGroup);
@@ -3884,7 +3965,7 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
             goto cleanup_file;
         }
 
-        code = cm_GetSCache(&Fid, &scp, userp, &req);
+        code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
         if (code) {
             osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult cm_GetSCache FID failure code=0x%x",
                      code);
@@ -3894,6 +3975,8 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
              */
         }
 
+        deleted = scp && (scp->flags & CM_SCACHEFLAG_DELETED);
+
         /* if the scp was not found, do not perform the length check */
         if (scp && (pFileCB->AllocationSize.QuadPart != scp->length.QuadPart)) {
             cm_attr_t setAttr;
@@ -4031,8 +4114,8 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
 #endif
                             }
 
-                            if ( (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
-                                 (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY) )
+                            if ((ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
+                                (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY))
                             {
 #ifdef VALIDATE_CHECK_SUM
                                 if ( buf_ValidateCheckSum(bufp) ) {
@@ -4070,8 +4153,10 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
                                                       pExtent->CacheOffset.HighPart,
                                                       pExtent->CacheOffset.LowPart);
 
-                                            buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
-                                            dirty++;
+                                            if (!deleted) {
+                                                buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
+                                                dirty++;
+                                            }
                                         } else {
 #ifdef ODS_DEBUG
                                             snprintf(dbgstr, 1024,
@@ -4097,8 +4182,10 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
                                     }
                                 }
 #else /* !VALIDATE_CHECK_SUM */
-                                buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
-                                dirty++;
+                                if (!deleted) {
+                                    buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
+                                    dirty++;
+                                }
 #ifdef ODS_DEBUG
                                 snprintf(dbgstr, 1024,
                                           "RDR_ProcessReleaseFileExtentsResult dirty! vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
@@ -4116,7 +4203,7 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
 #ifdef ODS_DEBUG
                                 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
 #endif
-                                if ( !buf_ValidateCheckSum(bufp) ) {
+                                if (!buf_ValidateCheckSum(bufp) ) {
                                     buf_ComputeCheckSum(bufp);
 #ifdef ODS_DEBUG
                                     HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
@@ -4140,8 +4227,10 @@ RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFi
 #ifdef DEBUG
                                     DebugBreak();
 #endif
-                                    buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
-                                    dirty++;
+                                    if (!deleted) {
+                                        buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
+                                        dirty++;
+                                    }
                                 } else {
                                     buf_ComputeCheckSum(bufp);
 #ifdef ODS_DEBUG
@@ -4298,7 +4387,7 @@ RDR_ReleaseFailedSetFileExtents( IN cm_user_t *userp,
     cm_scache_t *    scp = NULL;
     int              dirty = 0;
 
-    RDR_InitReq(&req);
+    RDR_InitReq(&req, FALSE);
 
     osi_Log4(afsd_logp, "RDR_ReleaseFailedSetFileExtents %d.%d.%d.%d",
               SetFileExtentsResultCB->FileId.Cell, SetFileExtentsResultCB->FileId.Volume,
@@ -4318,7 +4407,7 @@ RDR_ReleaseFailedSetFileExtents( IN cm_user_t *userp,
         goto cleanup_file;
     }
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         osi_Log1(afsd_logp, "RDR_ReleaseFailedSetFileExtents cm_GetSCache FID failure code=0x%x",
                   code);
@@ -4372,6 +4461,9 @@ RDR_PioctlOpen( IN cm_user_t *userp,
 {
     cm_fid_t    ParentFid;
     cm_fid_t    RootFid;
+    cm_req_t    req;
+
+    RDR_InitReq(&req, bWow64);
 
     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
     if (!(*ResultCB))
@@ -4396,7 +4488,7 @@ RDR_PioctlOpen( IN cm_user_t *userp,
     RootFid.hash = pPioctlCB->RootId.Hash;
 
     /* Create the pioctl index */
-    RDR_SetupIoctl(pPioctlCB->RequestId, &ParentFid, &RootFid, userp);
+    RDR_SetupIoctl(pPioctlCB->RequestId, &ParentFid, &RootFid, userp, &req);
 
     return;
 }
@@ -4439,9 +4531,7 @@ RDR_PioctlWrite( IN cm_user_t *userp,
     cm_req_t    req;
     DWORD       status;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
     if (!(*ResultCB))
@@ -4453,7 +4543,7 @@ RDR_PioctlWrite( IN cm_user_t *userp,
 
     pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
 
-    code = RDR_IoctlWrite(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer, &req);
+    code = RDR_IoctlWrite(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -4480,9 +4570,7 @@ RDR_PioctlRead( IN cm_user_t *userp,
     DWORD       status;
     afs_uint32  pflags = (bIsLocalSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
     if (!(*ResultCB))
@@ -4495,7 +4583,7 @@ RDR_PioctlRead( IN cm_user_t *userp,
     pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
 
     code = RDR_IoctlRead(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer,
-                         &pResultCB->BytesProcessed, &req, pflags);
+                         &pResultCB->BytesProcessed, pflags);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -4526,9 +4614,7 @@ RDR_ByteRangeLockSync( IN cm_user_t     *userp,
 
     ProcessId.QuadPart = pBRLRequestCB->ProcessId;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_ByteRangeLockSync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
               FileId.Cell, FileId.Volume,
@@ -4563,7 +4649,7 @@ RDR_ByteRangeLockSync( IN cm_user_t     *userp,
     Fid.unique = FileId.Unique;
     Fid.hash = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -4655,9 +4741,7 @@ RDR_ByteRangeUnlock( IN cm_user_t     *userp,
 
     ProcessId.QuadPart = pBRURequestCB->ProcessId;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_ByteRangeUnlock File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
               FileId.Cell, FileId.Volume,
@@ -4691,7 +4775,7 @@ RDR_ByteRangeUnlock( IN cm_user_t     *userp,
     Fid.unique = FileId.Unique;
     Fid.hash = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -4771,9 +4855,7 @@ RDR_ByteRangeUnlockAll( IN cm_user_t     *userp,
 
     ProcessId.QuadPart = pBRURequestCB->ProcessId;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_ByteRangeUnlockAll File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
               FileId.Cell, FileId.Volume,
@@ -4794,7 +4876,7 @@ RDR_ByteRangeUnlockAll( IN cm_user_t     *userp,
     Fid.unique = FileId.Unique;
     Fid.hash = FileId.Hash;
 
-    code = cm_GetSCache(&Fid, &scp, userp, &req);
+    code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
     if (code) {
         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
         (*ResultCB)->ResultStatus = status;
@@ -4850,7 +4932,6 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
     DWORD       Length;
     cm_scache_t *scp = NULL;
     cm_volume_t *volp = NULL;
-    cm_vol_state_t *volstatep = NULL;
     afs_uint32   volType;
     cm_cell_t   *cellp = NULL;
     cm_fid_t    Fid;
@@ -4868,10 +4949,10 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
     char *OfflineMsg;
     char *MOTD;
     struct rx_connection * rxconnp;
+    int sync_done = 0;
+    int scp_locked = 0;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     osi_Log4(afsd_logp, "RDR_GetVolumeInfo File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
              FileId.Cell, FileId.Volume,
@@ -4894,15 +4975,9 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
     (*ResultCB)->ResultBufferLength = sizeof(AFSVolumeInfoCB);
     pResultCB = (AFSVolumeInfoCB *)(*ResultCB)->ResultData;
 
-    /* Allocate the extents from the buffer package */
     if (FileId.Cell != 0) {
-        Fid.cell = FileId.Cell;
-        Fid.volume = FileId.Volume;
-        Fid.vnode = FileId.Vnode;
-        Fid.unique = FileId.Unique;
-        Fid.hash = FileId.Hash;
-
-        code = cm_GetSCache(&Fid, &scp, userp, &req);
+        cm_SetFid(&Fid, FileId.Cell, FileId.Volume, 1, 1);
+        code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
         if (code) {
             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
             (*ResultCB)->ResultStatus = status;
@@ -4917,21 +4992,8 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
         return;
     }
     lock_ObtainWrite(&scp->rw);
+    scp_locked = 1;
 
-    /* start by looking up the file's end */
-    code = cm_SyncOp(scp, NULL, userp, &req, 0,
-                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-    if (code) {
-        lock_ReleaseWrite(&scp->rw);
-        smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
-        (*ResultCB)->ResultStatus = status;
-        (*ResultCB)->ResultBufferLength = 0;
-        osi_Log3(afsd_logp, "RDR_GetVolumeInfo cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
-                 scp, code, status);
-        return;
-    }
-
-    /* Fake for now */
     pResultCB->SectorsPerAllocationUnit = 1;
     pResultCB->BytesPerSector = 1024;
 
@@ -4962,51 +5024,87 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
             code = CM_ERROR_NOSUCHVOLUME;
             goto _done;
         }
-        volstatep = cm_VolumeStateByID(volp, scp->fid.volume);
         volType = cm_VolumeType(volp, scp->fid.volume);
 
         pResultCB->Characteristics |= ((volType == ROVOL || volType == BACKVOL) ? FILE_READ_ONLY_DEVICE : 0);
 
-        Name = volName;
-       OfflineMsg = offLineMsg;
-       MOTD = motd;
-       lock_ReleaseWrite(&scp->rw);
-       do {
-           code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
-           if (code) continue;
-
-           rxconnp = cm_GetRxConn(connp);
-           code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
-                                        &volStat, &Name, &OfflineMsg, &MOTD);
-           rx_PutConnection(rxconnp);
-
-       } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
-       code = cm_MapRPCError(code, &req);
-        if (code == 0) {
-            pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
-            pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
+        code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
+                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+        if (code == 0)
+        {
+            sync_done = 1;
+
+            Name = volName;
+            OfflineMsg = offLineMsg;
+            MOTD = motd;
+            lock_ReleaseWrite(&scp->rw);
+            scp_locked = 0;
+
+            do {
+                code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
+                if (code) continue;
+
+                rxconnp = cm_GetRxConn(connp);
+                code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
+                                              &volStat, &Name, &OfflineMsg, &MOTD);
+                rx_PutConnection(rxconnp);
+
+            } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, code));
+            code = cm_MapRPCError(code, &req);
+        }
 
-            pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( Name, -1, pResultCB->VolumeLabel,
-                                                           (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
+        if (code == 0) {
+            if (volStat.MaxQuota)
+            {
+                pResultCB->TotalAllocationUnits.QuadPart = volStat.MaxQuota;
+                if (volType == ROVOL || volType == BACKVOL) {
+                    pResultCB->AvailableAllocationUnits.QuadPart = 0;
+                }
+                else
+                {
+                    pResultCB->AvailableAllocationUnits.QuadPart =
+                        min(volStat.MaxQuota - volStat.BlocksInUse, volStat.PartBlocksAvail);
+                }
+            }
+            else
+            {
+                pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
+                if (volType == ROVOL || volType == BACKVOL) {
+                    pResultCB->AvailableAllocationUnits.QuadPart = 0;
+                }
+                else
+                {
+                    pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
+                }
+            }
         } else {
+            /*
+             * Lie about the available space.  Out of quota errors will need
+             * detected when the file server rejects the store data.
+             */
             pResultCB->TotalAllocationUnits.QuadPart = 0x7FFFFFFF;
             pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
-
-            pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( volp->namep, -1, pResultCB->VolumeLabel,
-                                                           (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
             code = 0;
         }
+
+        pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( volp->namep, -1, pResultCB->VolumeLabel,
+                                                       (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
         if ( pResultCB->VolumeLabelLength )
             pResultCB->VolumeLabelLength--;
 
-        lock_ObtainWrite(&scp->rw);
+        if (sync_done) {
+            if (!scp_locked) {
+                lock_ObtainWrite(&scp->rw);
+                scp_locked = 1;
+            }
+            cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+        }
     }
     pResultCB->VolumeLabelLength *= sizeof(WCHAR);  /* convert to bytes from chars */
 
-    cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-
   _done:
-    lock_ReleaseWrite(&scp->rw);
+    if (scp_locked)
+        lock_ReleaseWrite(&scp->rw);
     if (volp)
        cm_PutVolume(volp);
     cm_ReleaseSCache(scp);
@@ -5018,6 +5116,176 @@ RDR_GetVolumeInfo( IN cm_user_t     *userp,
 }
 
 void
+RDR_GetVolumeSizeInfo( IN cm_user_t     *userp,
+                   IN AFSFileID     FileId,
+                   IN BOOL bWow64,
+                   IN DWORD ResultBufferLength,
+                   IN OUT AFSCommResult **ResultCB)
+{
+    AFSVolumeSizeInfoCB *pResultCB = NULL;
+    DWORD       Length;
+    cm_scache_t *scp = NULL;
+    cm_volume_t *volp = NULL;
+    afs_uint32   volType;
+    cm_cell_t   *cellp = NULL;
+    cm_fid_t    Fid;
+    afs_uint32  code;
+    cm_req_t    req;
+    DWORD       status;
+
+    char volName[32]="(unknown)";
+    char offLineMsg[256]="server temporarily inaccessible";
+    char motd[256]="server temporarily inaccessible";
+    cm_conn_t *connp;
+    AFSFetchVolumeStatus volStat;
+    char *Name;
+    char *OfflineMsg;
+    char *MOTD;
+    struct rx_connection * rxconnp;
+    int sync_done = 0;
+    int scp_locked = 0;
+
+    RDR_InitReq(&req, bWow64);
+
+    osi_Log4(afsd_logp, "RDR_GetVolumeSizeInfo File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+             FileId.Cell, FileId.Volume,
+             FileId.Vnode, FileId.Unique);
+
+    Length = sizeof( AFSCommResult) + sizeof(AFSVolumeSizeInfoCB);
+    if (sizeof(AFSVolumeSizeInfoCB) > ResultBufferLength) {
+        *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
+        if (!(*ResultCB))
+            return;
+        memset( *ResultCB, 0, sizeof(AFSCommResult));
+        (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
+        return;
+    }
+
+    *ResultCB = (AFSCommResult *)malloc( Length );
+    if (!(*ResultCB))
+       return;
+    memset( *ResultCB, '\0', Length );
+    (*ResultCB)->ResultBufferLength = sizeof(AFSVolumeSizeInfoCB);
+    pResultCB = (AFSVolumeSizeInfoCB *)(*ResultCB)->ResultData;
+
+    if (FileId.Cell != 0) {
+        cm_SetFid(&Fid, FileId.Cell, FileId.Volume, 1, 1);
+        code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
+        if (code) {
+            smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+            (*ResultCB)->ResultStatus = status;
+            (*ResultCB)->ResultBufferLength = 0;
+            osi_Log2(afsd_logp, "RDR_GetVolumeSizeInfo cm_GetSCache FID failure code=0x%x status=0x%x",
+                      code, status);
+            return;
+        }
+    } else {
+        (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
+        osi_Log0(afsd_logp, "RDR_GetVolumeSizeInfo Object Name Invalid - Cell = 0");
+        return;
+    }
+    lock_ObtainWrite(&scp->rw);
+    scp_locked = 1;
+
+    pResultCB->SectorsPerAllocationUnit = 1;
+    pResultCB->BytesPerSector = 1024;
+
+    if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+        scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
+    {
+        pResultCB->TotalAllocationUnits.QuadPart = 100;
+        pResultCB->AvailableAllocationUnits.QuadPart = 0;
+    } else {
+        volp = cm_GetVolumeByFID(&scp->fid);
+        if (!volp) {
+            code = CM_ERROR_NOSUCHVOLUME;
+            goto _done;
+        }
+
+        volType = cm_VolumeType(volp, scp->fid.volume);
+
+        code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
+                         CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+        if (code == 0)
+        {
+            sync_done = 1;
+
+            Name = volName;
+            OfflineMsg = offLineMsg;
+            MOTD = motd;
+            lock_ReleaseWrite(&scp->rw);
+            scp_locked = 0;
+
+            do {
+                code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
+                if (code) continue;
+
+                rxconnp = cm_GetRxConn(connp);
+                code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
+                                              &volStat, &Name, &OfflineMsg, &MOTD);
+                rx_PutConnection(rxconnp);
+
+            } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, code));
+            code = cm_MapRPCError(code, &req);
+        }
+
+        if (code == 0) {
+            if (volStat.MaxQuota)
+            {
+                pResultCB->TotalAllocationUnits.QuadPart = volStat.MaxQuota;
+                if (volType == ROVOL || volType == BACKVOL) {
+                    pResultCB->AvailableAllocationUnits.QuadPart = 0;
+                }
+                else
+                {
+                    pResultCB->AvailableAllocationUnits.QuadPart =
+                        min(volStat.MaxQuota - volStat.BlocksInUse, volStat.PartBlocksAvail);
+                }
+            }
+            else
+            {
+                pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
+                if (volType == ROVOL || volType == BACKVOL) {
+                    pResultCB->AvailableAllocationUnits.QuadPart = 0;
+                }
+                else
+                {
+                    pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
+                }
+            }
+        } else {
+            /*
+             * Lie about the available space.  Out of quota errors will need
+             * detected when the file server rejects the store data.
+             */
+            pResultCB->TotalAllocationUnits.QuadPart = 0x7FFFFFFF;
+            pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
+            code = 0;
+        }
+
+        if (sync_done) {
+            if (!scp_locked) {
+                lock_ObtainWrite(&scp->rw);
+                scp_locked = 1;
+            }
+            cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+        }
+    }
+
+  _done:
+    if (scp_locked)
+        lock_ReleaseWrite(&scp->rw);
+    if (volp)
+       cm_PutVolume(volp);
+    cm_ReleaseSCache(scp);
+
+    smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+    (*ResultCB)->ResultStatus = status;
+    osi_Log0(afsd_logp, "RDR_GetVolumeSizeInfo SUCCESS");
+    return;
+}
+
+void
 RDR_HoldFid( IN cm_user_t     *userp,
              IN AFSHoldFidRequestCB * pHoldFidCB,
              IN BOOL bFast,
@@ -5029,7 +5297,7 @@ RDR_HoldFid( IN cm_user_t     *userp,
     DWORD       Length;
     cm_req_t    req;
 
-    RDR_InitReq(&req);
+    RDR_InitReq(&req, FALSE);
 
     osi_Log1(afsd_logp, "RDR_HoldFid Count=%u", pHoldFidCB->Count);
 
@@ -5089,7 +5357,7 @@ RDR_ReleaseFid( IN cm_user_t     *userp,
     DWORD       Length;
     cm_req_t    req;
 
-    RDR_InitReq(&req);
+    RDR_InitReq(&req, FALSE);
 
     osi_Log1(afsd_logp, "RDR_ReleaseFid Count=%u", pReleaseFidCB->Count);
 
@@ -5252,9 +5520,7 @@ RDR_PipeWrite( IN cm_user_t *userp,
     cm_req_t    req;
     DWORD       status;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
     if (!(*ResultCB))
@@ -5292,9 +5558,7 @@ RDR_PipeRead( IN cm_user_t *userp,
     cm_req_t    req;
     DWORD       status;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
     if (!(*ResultCB))
@@ -5329,9 +5593,7 @@ RDR_PipeSetInfo( IN cm_user_t *userp,
     cm_req_t    req;
     DWORD       status;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
     if (!(*ResultCB))
@@ -5361,9 +5623,7 @@ RDR_PipeQueryInfo( IN cm_user_t *userp,
     cm_req_t    req;
     DWORD       status;
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
     if (!(*ResultCB))
@@ -5429,9 +5689,7 @@ RDR_PipeTransceive( IN cm_user_t     *userp,
     DWORD       status;
     DWORD Length = ResultBufferLength + sizeof( AFSCommResult);
 
-    RDR_InitReq(&req);
-    if ( bWow64 )
-        req.flags |= CM_REQ_WOW64;
+    RDR_InitReq(&req, bWow64);
 
     *ResultCB = (AFSCommResult *)malloc( Length);
     if (!(*ResultCB))