Windows: Request extents readability
[openafs.git] / src / WINNT / afsrdr / user / RDRFunction.c
1 /*
2  * Copyright (c) 2008 Secure Endpoints, Inc.
3  * Copyright (c) 2009-2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * - Redistributions of source code must retain the above copyright notice,
10  *   this list of conditions and the following disclaimer.
11  * - Redistributions in binary form must reproduce the above copyright notice,
12  *   this list of conditions and the following disclaimer in the documentation
13  *   and/or other materials provided with the distribution.
14  * - Neither the name of Secure Endpoints Inc. nor the names of its contributors
15  *   may be used to endorse or promote products derived from this software without
16  *   specific prior written permission from Secure Endpoints, Inc. and
17  *   Your File System, Inc.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
23  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <afsconfig.h>
33 #include <afs/param.h>
34
35 #ifndef _WIN32_WINNT
36 #define _WIN32_WINNT 0x0500
37 #endif
38 #define _CRT_SECURE_NO_DEPRECATE
39 #define _CRT_NON_CONFORMING_SWPRINTFS
40 #define INITGUID        /* define AFS_AUTH_GUID_NO_PAG */
41
42 #include <ntstatus.h>
43 #define WIN32_NO_STATUS
44 #include <windows.h>
45
46 #include <roken.h>
47
48 #include <afs/stds.h>
49
50 #include <ntsecapi.h>
51 #include <sddl.h>
52 #pragma warning(push)
53 #pragma warning(disable: 4005)
54
55 #include <devioctl.h>
56
57 #include "..\\Common\\AFSUserDefines.h"
58 #include "..\\Common\\AFSUserStructs.h"
59
60 #pragma warning(pop)
61
62 #include <tchar.h>
63 #include <wchar.h>
64 #include <winbase.h>
65 #include <winreg.h>
66
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <stdarg.h>
70 #include <strsafe.h>
71
72 #include "afsd.h"
73 #include "smb.h"
74 #include "cm_btree.h"
75 #include "msrpc.h"
76 #include <RDRPrototypes.h>
77 #include <RDRIoctl.h>
78 #include <RDRPipe.h>
79
80 static CHAR * RDR_extentBaseAddress = NULL;
81
82 void
83 RDR_InitReq(cm_req_t *reqp)
84 {
85     cm_InitReq(reqp);
86     reqp->flags |= CM_REQ_SOURCE_REDIR;
87 }
88
89 void
90 RDR_fid2FID( cm_fid_t *fid, AFSFileID *FileId)
91 {
92     FileId->Cell = fid->cell;
93     FileId->Volume = fid->volume;
94     FileId->Vnode = fid->vnode;
95     FileId->Unique = fid->unique;
96     FileId->Hash = fid->hash;
97 }
98
99 void
100 RDR_FID2fid( AFSFileID *FileId, cm_fid_t *fid)
101 {
102     fid->cell = FileId->Cell;
103     fid->volume = FileId->Volume;
104     fid->vnode = FileId->Vnode;
105     fid->unique = FileId->Unique;
106     fid->hash = FileId->Hash;
107 }
108
109 DWORD
110 RDR_SetInitParams( OUT AFSRedirectorInitInfo **ppRedirInitInfo, OUT DWORD * pRedirInitInfoLen )
111 {
112     extern char cm_CachePath[];
113     extern cm_config_data_t cm_data;
114     extern int smb_hideDotFiles;
115     size_t cm_CachePathLen = strlen(cm_CachePath);
116     size_t err;
117     DWORD TempPathLen = ExpandEnvironmentStringsW(L"%TEMP%", NULL, 0);
118     MEMORYSTATUSEX memStatus;
119     DWORD maxMemoryCacheSize;
120
121     memStatus.dwLength = sizeof(memStatus);
122     if (GlobalMemoryStatusEx(&memStatus)) {
123         /*
124          * Use the memory extent interface in the afs redirector
125          * whenever the cache size is less than equal to 10% of
126          * physical memory.  Do not use too much because this memory
127          * will be locked by the redirector so it can't be swapped
128          * out.
129          */
130         maxMemoryCacheSize = (DWORD)(memStatus.ullTotalPhys / 1024 / 10);
131     } else {
132         /*
133          * If we can't determine the amount of physical memory
134          * in the system, be conservative and limit the use of
135          * memory extent interface to 64MB data caches.
136          */
137         maxMemoryCacheSize = 65536;
138     }
139
140     *pRedirInitInfoLen = (DWORD) (sizeof(AFSRedirectorInitInfo) + (cm_CachePathLen + TempPathLen) * sizeof(WCHAR));
141     *ppRedirInitInfo = (AFSRedirectorInitInfo *)malloc(*pRedirInitInfoLen);
142     (*ppRedirInitInfo)->Flags = smb_hideDotFiles ? AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES : 0;
143     (*ppRedirInitInfo)->MaximumChunkLength = cm_data.chunkSize;
144     (*ppRedirInitInfo)->GlobalFileId.Cell   = cm_data.rootFid.cell;
145     (*ppRedirInitInfo)->GlobalFileId.Volume = cm_data.rootFid.volume;
146     (*ppRedirInitInfo)->GlobalFileId.Vnode  = cm_data.rootFid.vnode;
147     (*ppRedirInitInfo)->GlobalFileId.Unique = cm_data.rootFid.unique;
148     (*ppRedirInitInfo)->GlobalFileId.Hash   = cm_data.rootFid.hash;
149     (*ppRedirInitInfo)->ExtentCount.QuadPart = cm_data.buf_nbuffers;
150     (*ppRedirInitInfo)->CacheBlockSize = cm_data.blockSize;
151     (*ppRedirInitInfo)->MaxPathLinkCount = 512; /* this needs to become a registry value */
152     (*ppRedirInitInfo)->NameArrayLength = 32;   /* this needs to become a registry value */
153     if (cm_virtualCache || cm_data.bufferSize <= maxMemoryCacheSize) {
154         osi_Log0(afsd_logp, "RDR_SetInitParams Initializing Memory Extent Interface");
155         (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = (LONGLONG)cm_data.bufDataBaseAddress;
156         (*ppRedirInitInfo)->MemoryCacheLength.QuadPart = cm_data.bufEndOfData - cm_data.bufDataBaseAddress;
157         (*ppRedirInitInfo)->CacheFileNameLength = 0;
158         RDR_extentBaseAddress = cm_data.bufDataBaseAddress;
159     } else {
160         (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = 0;
161         (*ppRedirInitInfo)->MemoryCacheLength.QuadPart = 0;
162         (*ppRedirInitInfo)->CacheFileNameLength = (ULONG) (cm_CachePathLen * sizeof(WCHAR));
163         err = mbstowcs((*ppRedirInitInfo)->CacheFileName, cm_CachePath, (cm_CachePathLen + 1) *sizeof(WCHAR));
164         if (err == -1) {
165             free(*ppRedirInitInfo);
166             osi_Log0(afsd_logp, "RDR_SetInitParams Invalid Object Name");
167             return STATUS_OBJECT_NAME_INVALID;
168         }
169         RDR_extentBaseAddress = cm_data.baseAddress;
170     }
171     (*ppRedirInitInfo)->DumpFileLocationOffset = FIELD_OFFSET(AFSRedirectorInitInfo, CacheFileName) + (*ppRedirInitInfo)->CacheFileNameLength;
172     (*ppRedirInitInfo)->DumpFileLocationLength = (TempPathLen - 1) * sizeof(WCHAR);
173     ExpandEnvironmentStringsW(L"%TEMP%",
174                               (LPWSTR)(((PBYTE)(*ppRedirInitInfo)) + (*ppRedirInitInfo)->DumpFileLocationOffset),
175                               TempPathLen);
176
177     osi_Log0(afsd_logp,"RDR_SetInitParams Success");
178     return 0;
179 }
180
181 cm_user_t *
182 RDR_GetLocalSystemUser( void)
183 {
184     smb_username_t *unp;
185     cm_user_t *userp = NULL;
186     wchar_t cname[MAX_COMPUTERNAME_LENGTH+1];
187     int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
188
189     GetComputerNameW(cname, &cnamelen);
190     _wcsupr(cname);
191
192     unp = smb_FindUserByName(NTSID_LOCAL_SYSTEM, cname, SMB_FLAG_CREATE);
193     lock_ObtainMutex(&unp->mx);
194     if (!unp->userp)
195         unp->userp = cm_NewUser();
196     unp->flags |= SMB_USERNAMEFLAG_SID;
197     lock_ReleaseMutex(&unp->mx);
198     userp = unp->userp;
199     cm_HoldUser(userp);
200     smb_ReleaseUsername(unp);
201
202     if (!userp) {
203         userp = cm_rootUserp;
204         cm_HoldUser(userp);
205     }
206
207     return userp;
208 }
209
210 cm_user_t *
211 RDR_UserFromCommRequest( IN AFSCommRequest *RequestBuffer)
212 {
213
214     return RDR_UserFromAuthGroup( &RequestBuffer->AuthGroup);
215 }
216
217 cm_user_t *
218 RDR_UserFromAuthGroup( IN GUID *pGuid)
219 {
220     smb_username_t *unp;
221     cm_user_t * userp = NULL;
222     RPC_WSTR UuidString = NULL;
223     wchar_t cname[MAX_COMPUTERNAME_LENGTH+1];
224     int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
225
226     if (UuidToStringW((UUID *)pGuid, &UuidString) != RPC_S_OK)
227         goto done;
228
229     GetComputerNameW(cname, &cnamelen);
230     _wcsupr(cname);
231
232     unp = smb_FindUserByName(UuidString, cname, SMB_FLAG_CREATE);
233     lock_ObtainMutex(&unp->mx);
234     if (!unp->userp) {
235         unp->userp = cm_NewUser();
236         memcpy(&unp->userp->authgroup, pGuid, sizeof(GUID));
237     }
238     unp->flags |= SMB_USERNAMEFLAG_SID;
239     lock_ReleaseMutex(&unp->mx);
240     userp = unp->userp;
241     cm_HoldUser(userp);
242     smb_ReleaseUsername(unp);
243
244   done:
245     if (!userp) {
246         userp = cm_rootUserp;
247         cm_HoldUser(userp);
248     }
249
250     osi_Log2(afsd_logp, "RDR_UserFromCommRequest Guid %S userp = 0x%p",
251              osi_LogSaveStringW(afsd_logp, UuidString),
252              userp);
253
254     if (UuidString)
255         RpcStringFreeW(&UuidString);
256
257     return userp;
258 }
259
260 void
261 RDR_ReleaseUser( IN cm_user_t *userp )
262 {
263     osi_Log1(afsd_logp, "RDR_ReleaseUser userp = 0x%p", userp);
264     cm_ReleaseUser(userp);
265 }
266
267
268 /*
269  * RDR_FlagScpInUse flags the scp with CM_SCACHEFLAG_RDR_IN_USE
270  */
271 static void
272 RDR_FlagScpInUse( IN cm_scache_t *scp, IN BOOL bLocked )
273 {
274     if (!bLocked)
275         lock_ObtainWrite(&scp->rw);
276
277     lock_AssertWrite(&scp->rw);
278     scp->flags |= CM_SCACHEFLAG_RDR_IN_USE;
279
280     if (!bLocked)
281         lock_ReleaseWrite(&scp->rw);
282 }
283
284 /*
285  * Obtain the status information for the specified object and
286  *
287  */
288 static afs_uint32
289 RDR_BulkStatLookup( cm_scache_t *dscp,
290                     cm_scache_t *scp,
291                     cm_user_t   *userp,
292                     cm_req_t    *reqp)
293 {
294     cm_direnum_t *      enump = NULL;
295     afs_uint32  code = 0;
296     cm_dirOp_t    dirop;
297
298     code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
299     if (code == 0) {
300         code = cm_BPlusDirEnumerate(dscp, userp, reqp, TRUE, NULL, TRUE, &enump);
301         if (code) {
302             osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BPlusDirEnumerate failure code=0x%x",
303                       code);
304         }
305         cm_EndDirOp(&dirop);
306     } else {
307         osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BeginDirOp failure code=0x%x",
308                   code);
309     }
310
311
312     if (enump)
313     {
314         code = cm_BPlusDirEnumBulkStatOne(enump, scp);
315         if (code) {
316             osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BPlusDirEnumBulkStatOne failure code=0x%x",
317                       code);
318         }
319         cm_BPlusDirFreeEnumeration(enump);
320     }
321
322     return code;
323 }
324
325
326 #define RDR_POP_FOLLOW_MOUNTPOINTS 0x01
327 #define RDR_POP_EVALUATE_SYMLINKS  0x02
328 #define RDR_POP_WOW64              0x04
329 #define RDR_POP_NO_GETSTATUS       0x08
330
331 afs_uint32
332 RDR_PopulateCurrentEntry( IN  AFSDirEnumEntry * pCurrentEntry,
333                           IN  DWORD             dwMaxEntryLength,
334                           IN  cm_scache_t     * dscp,
335                           IN  cm_scache_t     * scp,
336                           IN  cm_user_t       * userp,
337                           IN  cm_req_t        * reqp,
338                           IN  wchar_t         * name,
339                           IN  wchar_t         * shortName,
340                           IN  DWORD             dwFlags,
341                           OUT AFSDirEnumEntry **ppNextEntry,
342                           OUT DWORD           * pdwRemainingLength)
343 {
344     FILETIME ft;
345     WCHAR *  wname, *wtarget;
346     size_t   len;
347     DWORD      dwEntryLength;
348     afs_uint32 code = 0, code2 = 0;
349     BOOL          bMustFake = FALSE;
350
351     osi_Log5(afsd_logp, "RDR_PopulateCurrentEntry dscp=0x%p scp=0x%p name=%S short=%S flags=0x%x",
352              dscp, scp, osi_LogSaveStringW(afsd_logp, name),
353              osi_LogSaveStringW(afsd_logp, shortName), dwFlags);
354     osi_Log1(afsd_logp, "... maxLength=%d", dwMaxEntryLength);
355
356     if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
357         if (ppNextEntry)
358             *ppNextEntry = pCurrentEntry;
359         if (pdwRemainingLength)
360             *pdwRemainingLength = dwMaxEntryLength;
361         osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry Not Enough Room for Entry %d < %d",
362                  dwMaxEntryLength, sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t));
363         return CM_ERROR_TOOBIG;
364     }
365
366     if (!name)
367         name = L"";
368     if (!shortName)
369         shortName = L"";
370
371     dwEntryLength = sizeof(AFSDirEnumEntry);
372
373     lock_ObtainWrite(&scp->rw);
374     if (dwFlags & RDR_POP_NO_GETSTATUS) {
375         if (!cm_HaveCallback(scp))
376             bMustFake = TRUE;
377     } else {
378 #ifdef AFS_FREELANCE_CLIENT
379         if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID) {
380             /*
381              * If the FID is from the Freelance Local Root always perform
382              * a single item status check.
383              */
384             code = cm_SyncOp( scp, NULL, userp, reqp, 0,
385                               CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
386             if (code) {
387                 lock_ReleaseWrite(&scp->rw);
388                 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_SyncOp failed for scp=0x%p code=0x%x",
389                          scp, code);
390                 return code;
391             }
392         } else
393 #endif
394         {
395             /*
396              * For non-Freelance objects, check to see if we have current
397              * status information.  If not, perform a bulk status lookup of multiple
398              * entries in order to reduce the number of RPCs issued to the file server.
399              */
400             if ((scp->flags & CM_SCACHEFLAG_EACCESS))
401                 bMustFake = TRUE;
402             else if (!cm_HaveCallback(scp)) {
403                 lock_ReleaseWrite(&scp->rw);
404                 code = RDR_BulkStatLookup(dscp, scp, userp, reqp);
405                 if (code) {
406                     osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RXR_BulkStatLookup failed for scp=0x%p code=0x%x",
407                              scp, code);
408                     return code;
409                 }
410                 lock_ObtainWrite(&scp->rw);
411                 /*
412                  * RDR_BulkStatLookup can succeed but it may be the case that there
413                  * still is not valid status info.  If we get this far, generate fake
414                  * status info.
415                  */
416                 if (!cm_HaveCallback(scp))
417                     bMustFake = TRUE;
418             }
419         }
420
421     }
422
423     /* Populate the real or fake data */
424     pCurrentEntry->FileId.Cell = scp->fid.cell;
425     pCurrentEntry->FileId.Volume = scp->fid.volume;
426     pCurrentEntry->FileId.Vnode = scp->fid.vnode;
427     pCurrentEntry->FileId.Unique = scp->fid.unique;
428     pCurrentEntry->FileId.Hash = scp->fid.hash;
429
430     pCurrentEntry->FileType = scp->fileType;
431
432     pCurrentEntry->DataVersion.QuadPart = scp->dataVersion;
433
434     if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
435         scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {
436         cm_LargeSearchTimeFromUnixTime(&ft, MAX_AFS_UINT32);
437     } else {
438         cm_LargeSearchTimeFromUnixTime(&ft, scp->cbExpires);
439     }
440     pCurrentEntry->Expiration.LowPart = ft.dwLowDateTime;
441     pCurrentEntry->Expiration.HighPart = ft.dwHighDateTime;
442
443     if (bMustFake) {
444         /* 1969-12-31 23:59:59 +00 */
445         ft.dwHighDateTime = 0x19DB200;
446         ft.dwLowDateTime = 0x5BB78980;
447     } else
448         cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
449     pCurrentEntry->CreationTime.LowPart = ft.dwLowDateTime;
450     pCurrentEntry->CreationTime.HighPart = ft.dwHighDateTime;
451     pCurrentEntry->LastAccessTime = pCurrentEntry->CreationTime;
452     pCurrentEntry->LastWriteTime = pCurrentEntry->CreationTime;
453     pCurrentEntry->ChangeTime = pCurrentEntry->CreationTime;
454
455     pCurrentEntry->EndOfFile = scp->length;
456     pCurrentEntry->AllocationSize = scp->length;
457
458     if (bMustFake) {
459         switch (scp->fileType) {
460         case CM_SCACHETYPE_DIRECTORY:
461             pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
462             break;
463         case CM_SCACHETYPE_MOUNTPOINT:
464         case CM_SCACHETYPE_INVALID:
465             pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
466             break;
467         case CM_SCACHETYPE_SYMLINK:
468             if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
469                 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
470             else
471                 pCurrentEntry->FileAttributes = SMB_ATTR_REPARSE_POINT;
472             break;
473         default:
474             /* if we get here we either have a normal file
475             * or we have a file for which we have never
476             * received status info.  In this case, we can
477             * check the even/odd value of the entry's vnode.
478             * odd means it is to be treated as a directory
479             * and even means it is to be treated as a file.
480             */
481             if (scp->fid.vnode & 0x1)
482                 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
483             else
484                 pCurrentEntry->FileAttributes = SMB_ATTR_NORMAL;
485         }
486     } else
487         pCurrentEntry->FileAttributes = smb_ExtAttributes(scp);
488     pCurrentEntry->EaSize = 0;
489     pCurrentEntry->Links = scp->linkCount;
490
491     len = wcslen(shortName);
492     wcsncpy(pCurrentEntry->ShortName, shortName, len);
493     pCurrentEntry->ShortNameLength = (CCHAR)(len * sizeof(WCHAR));
494
495     pCurrentEntry->FileNameOffset = sizeof(AFSDirEnumEntry);
496     len = wcslen(name);
497     wname = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->FileNameOffset);
498     wcsncpy(wname, name, len);
499     pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
500
501     osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry scp=0x%p fileType=%d",
502               scp, scp->fileType);
503
504     if (!(dwFlags & RDR_POP_NO_GETSTATUS))
505         cm_SyncOpDone( scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
506
507     if ((dwFlags & RDR_POP_NO_GETSTATUS) || !cm_HaveCallback(scp)) {
508         pCurrentEntry->TargetNameOffset = 0;
509         pCurrentEntry->TargetNameLength = 0;
510     }
511     else
512     switch (scp->fileType) {
513     case CM_SCACHETYPE_MOUNTPOINT:
514         if (dwFlags & RDR_POP_FOLLOW_MOUNTPOINTS) {
515             if ((code2 = cm_ReadMountPoint(scp, userp, reqp)) == 0) {
516                 cm_scache_t *targetScp = NULL;
517
518                 pCurrentEntry->TargetNameOffset = pCurrentEntry->FileNameOffset + pCurrentEntry->FileNameLength;
519                 len = strlen(scp->mountPointStringp);
520                 wtarget = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->TargetNameOffset);
521
522 #ifdef UNICODE
523                 cch = MultiByteToWideChar( CP_UTF8, 0, scp->mountPointStringp,
524                                            len * sizeof(char),
525                                            wtarget,
526                                            len * sizeof(WCHAR));
527 #else
528                 mbstowcs(wtarget, scp->mountPointStringp, len);
529 #endif
530                 pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * len);
531
532                 code2 = cm_FollowMountPoint(scp, dscp, userp, reqp, &targetScp);
533
534                 if (code2 == 0) {
535                     pCurrentEntry->TargetFileId.Cell = targetScp->fid.cell;
536                     pCurrentEntry->TargetFileId.Volume = targetScp->fid.volume;
537                     pCurrentEntry->TargetFileId.Vnode = targetScp->fid.vnode;
538                     pCurrentEntry->TargetFileId.Unique = targetScp->fid.unique;
539                     pCurrentEntry->TargetFileId.Hash = targetScp->fid.hash;
540
541                     osi_Log4(afsd_logp, "RDR_PopulateCurrentEntry target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
542                               pCurrentEntry->TargetFileId.Cell, pCurrentEntry->TargetFileId.Volume,
543                               pCurrentEntry->TargetFileId.Vnode, pCurrentEntry->TargetFileId.Unique);
544
545                     cm_ReleaseSCache(targetScp);
546                 } else {
547                     osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_FollowMountPoint failed scp=0x%p code=0x%x",
548                               scp, code2);
549                 }
550             } else {
551                 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_ReadMountPoint failed scp=0x%p code=0x%x",
552                           scp, code2);
553             }
554         }
555         break;
556     case CM_SCACHETYPE_SYMLINK:
557     case CM_SCACHETYPE_DFSLINK:
558         {
559             pCurrentEntry->TargetNameOffset = pCurrentEntry->FileNameOffset + pCurrentEntry->FileNameLength;
560             wtarget = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->TargetNameOffset);
561
562             if (dwFlags & RDR_POP_EVALUATE_SYMLINKS) {
563                 char * mp;
564
565                 code2 = cm_HandleLink(scp, userp, reqp);
566                 if (code2 == 0) {
567                     mp = scp->mountPointStringp;
568                     len = strlen(mp);
569                     if ( len != 0 ) {
570                         /* Strip off the msdfs: prefix from the target name for the file system */
571                         if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
572                             osi_Log0(afsd_logp, "RDR_PopulateCurrentEntry DFSLink Detected");
573                             pCurrentEntry->FileType = scp->fileType;
574
575                             if (!strncmp("msdfs:", mp, 6)) {
576                                 mp += 6;
577                                 len -= 6;
578                             }
579                         }
580                         /* only send one slash to the redirector */
581                         if (mp[0] == '\\' && mp[1] == '\\') {
582                             mp++;
583                             len--;
584                         }
585 #ifdef UNICODE
586                         cch = MultiByteToWideChar( CP_UTF8, 0, mp,
587                                                    len * sizeof(char),
588                                                    wtarget,
589                                                    len * sizeof(WCHAR));
590 #else
591                         mbstowcs(wtarget, mp, len);
592 #endif
593                     }
594                     pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * len);
595                 } else {
596                     osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_HandleLink failed scp=0x%p code=0x%x",
597                              scp, code2);
598                 }
599             }
600
601         }
602         break;
603
604     default:
605         pCurrentEntry->TargetNameOffset = 0;
606         pCurrentEntry->TargetNameLength = 0;
607     }
608     lock_ReleaseWrite(&scp->rw);
609
610     dwEntryLength += pCurrentEntry->FileNameLength + pCurrentEntry->TargetNameLength;
611     dwEntryLength += (dwEntryLength % 8) ? 8 - (dwEntryLength % 8) : 0;   /* quad align */
612     if (ppNextEntry)
613         *ppNextEntry = (AFSDirEnumEntry *)((PBYTE)pCurrentEntry + dwEntryLength);
614     if (pdwRemainingLength)
615         *pdwRemainingLength = dwMaxEntryLength - dwEntryLength;
616
617     osi_Log3(afsd_logp, "RDR_PopulateCurrentEntry Success FileNameLength=%d TargetNameLength=%d RemainingLength=%d",
618               pCurrentEntry->FileNameLength, pCurrentEntry->TargetNameLength, *pdwRemainingLength);
619
620     return code;
621 }
622
623 afs_uint32
624 RDR_PopulateCurrentEntryNoScp( IN  AFSDirEnumEntry * pCurrentEntry,
625                                IN  DWORD             dwMaxEntryLength,
626                                IN  cm_scache_t     * dscp,
627                                IN  cm_fid_t        * fidp,
628                                IN  cm_user_t       * userp,
629                                IN  cm_req_t        * reqp,
630                                IN  wchar_t         * name,
631                                IN  wchar_t         * shortName,
632                                IN  DWORD             dwFlags,
633                                OUT AFSDirEnumEntry **ppNextEntry,
634                                OUT DWORD           * pdwRemainingLength)
635 {
636     FILETIME ft;
637     WCHAR *  wname;
638     size_t   len;
639     DWORD      dwEntryLength;
640     afs_uint32 code = 0, code2 = 0;
641
642     osi_Log4(afsd_logp, "RDR_PopulateCurrentEntryNoEntry dscp=0x%p name=%S short=%S flags=0x%x",
643              dscp, osi_LogSaveStringW(afsd_logp, name),
644              osi_LogSaveStringW(afsd_logp, shortName), dwFlags);
645     osi_Log1(afsd_logp, "... maxLength=%d", dwMaxEntryLength);
646
647     if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
648         if (ppNextEntry)
649             *ppNextEntry = pCurrentEntry;
650         if (pdwRemainingLength)
651             *pdwRemainingLength = dwMaxEntryLength;
652         osi_Log2(afsd_logp, "RDR_PopulateCurrentEntryNoEntry Not Enough Room for Entry %d < %d",
653                  dwMaxEntryLength, sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t));
654         return CM_ERROR_TOOBIG;
655     }
656
657     if (!name)
658         name = L"";
659     if (!shortName)
660         shortName = L"";
661
662     dwEntryLength = sizeof(AFSDirEnumEntry);
663
664     pCurrentEntry->FileId.Cell = fidp->cell;
665     pCurrentEntry->FileId.Volume = fidp->volume;
666     pCurrentEntry->FileId.Vnode = fidp->vnode;
667     pCurrentEntry->FileId.Unique = fidp->unique;
668     pCurrentEntry->FileId.Hash = fidp->hash;
669
670     pCurrentEntry->FileType = CM_SCACHETYPE_UNKNOWN;
671
672     pCurrentEntry->DataVersion.QuadPart = CM_SCACHE_VERSION_BAD;
673
674     cm_LargeSearchTimeFromUnixTime(&ft, 0);
675     pCurrentEntry->Expiration.LowPart = ft.dwLowDateTime;
676     pCurrentEntry->Expiration.HighPart = ft.dwHighDateTime;
677
678     cm_LargeSearchTimeFromUnixTime(&ft, 0);
679     pCurrentEntry->CreationTime.LowPart = ft.dwLowDateTime;
680     pCurrentEntry->CreationTime.HighPart = ft.dwHighDateTime;
681     pCurrentEntry->LastAccessTime = pCurrentEntry->CreationTime;
682     pCurrentEntry->LastWriteTime = pCurrentEntry->CreationTime;
683     pCurrentEntry->ChangeTime = pCurrentEntry->CreationTime;
684
685     pCurrentEntry->EndOfFile.QuadPart = 0;
686     pCurrentEntry->AllocationSize.QuadPart = 0;
687     pCurrentEntry->FileAttributes = 0;
688     pCurrentEntry->EaSize = 0;
689     pCurrentEntry->Links = 0;
690
691     len = wcslen(shortName);
692     wcsncpy(pCurrentEntry->ShortName, shortName, len);
693     pCurrentEntry->ShortNameLength = (CCHAR)(len * sizeof(WCHAR));
694
695     pCurrentEntry->FileNameOffset = sizeof(AFSDirEnumEntry);
696     len = wcslen(name);
697     wname = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->FileNameOffset);
698     wcsncpy(wname, name, len);
699     pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
700
701     pCurrentEntry->TargetNameOffset = 0;
702     pCurrentEntry->TargetNameLength = 0;
703
704     dwEntryLength += pCurrentEntry->FileNameLength + pCurrentEntry->TargetNameLength;
705     dwEntryLength += (dwEntryLength % 8) ? 8 - (dwEntryLength % 8) : 0;   /* quad align */
706     if (ppNextEntry)
707         *ppNextEntry = (AFSDirEnumEntry *)((PBYTE)pCurrentEntry + dwEntryLength);
708     if (pdwRemainingLength)
709         *pdwRemainingLength = dwMaxEntryLength - dwEntryLength;
710
711     osi_Log3(afsd_logp, "RDR_PopulateCurrentEntryNoScp Success FileNameLength=%d TargetNameLength=%d RemainingLength=%d",
712               pCurrentEntry->FileNameLength, pCurrentEntry->TargetNameLength, *pdwRemainingLength);
713
714     return code;
715 }
716
717 void
718 RDR_EnumerateDirectory( IN cm_user_t *userp,
719                         IN AFSFileID DirID,
720                         IN AFSDirQueryCB *QueryCB,
721                         IN BOOL bWow64,
722                         IN BOOL bSkipStatus,
723                         IN DWORD ResultBufferLength,
724                         IN OUT AFSCommResult **ResultCB)
725 {
726     DWORD status;
727     cm_direnum_t *      enump = NULL;
728     AFSDirEnumResp  * pDirEnumResp;
729     AFSDirEnumEntry * pCurrentEntry;
730     size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
731     DWORD             dwMaxEntryLength;
732     afs_uint32  code = 0;
733     cm_fid_t      fid;
734     cm_scache_t * dscp = NULL;
735     cm_req_t      req;
736
737     RDR_InitReq(&req);
738     if ( bWow64 )
739         req.flags |= CM_REQ_WOW64;
740
741     osi_Log4(afsd_logp, "RDR_EnumerateDirectory FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
742              DirID.Cell, DirID.Volume, DirID.Vnode, DirID.Unique);
743
744     *ResultCB = (AFSCommResult *)malloc(size);
745     if (!(*ResultCB)) {
746         osi_Log0(afsd_logp, "RDR_EnumerateDirectory Out of Memory");
747         return;
748     }
749
750     memset(*ResultCB, 0, size);
751
752     if (QueryCB->EnumHandle == (ULONG_PTR)-1) {
753         osi_Log0(afsd_logp, "RDR_EnumerateDirectory No More Entries");
754         (*ResultCB)->ResultStatus = STATUS_NO_MORE_ENTRIES;
755         (*ResultCB)->ResultBufferLength = 0;
756         return;
757     }
758
759     (*ResultCB)->ResultBufferLength = dwMaxEntryLength = ResultBufferLength;
760     if (ResultBufferLength) {
761         pDirEnumResp = (AFSDirEnumResp *)&(*ResultCB)->ResultData;
762         pCurrentEntry = (AFSDirEnumEntry *)&pDirEnumResp->Entry;
763         dwMaxEntryLength -= FIELD_OFFSET( AFSDirEnumResp, Entry);      /* AFSDirEnumResp */
764     }
765
766     if (DirID.Cell != 0) {
767         fid.cell   = DirID.Cell;
768         fid.volume = DirID.Volume;
769         fid.vnode  = DirID.Vnode;
770         fid.unique = DirID.Unique;
771         fid.hash   = DirID.Hash;
772
773         code = cm_GetSCache(&fid, &dscp, userp, &req);
774         if (code) {
775             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
776             (*ResultCB)->ResultStatus = status;
777             osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure code=0x%x status=0x%x",
778                       code, status);
779             return;
780         }
781     } else {
782         (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
783         osi_Log0(afsd_logp, "RDR_EnumerateDirectory Object Name Invalid - Cell = 0");
784         return;
785     }
786
787     /* get the directory size */
788     lock_ObtainWrite(&dscp->rw);
789     code = cm_SyncOp(dscp, NULL, userp, &req, PRSFS_LOOKUP,
790                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
791     if (code) {
792         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
793         (*ResultCB)->ResultStatus = status;
794         lock_ReleaseWrite(&dscp->rw);
795         cm_ReleaseSCache(dscp);
796         osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_SyncOp failure code=0x%x status=0x%x",
797                   code, status);
798         return;
799     }
800
801     cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
802     lock_ReleaseWrite(&dscp->rw);
803
804     if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
805         (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
806         cm_ReleaseSCache(dscp);
807         osi_Log1(afsd_logp, "RDR_EnumerateDirectory Not a Directory dscp=0x%p",
808                  dscp);
809         return;
810     }
811
812     /*
813      * If there is no enumeration handle, then this is a new query
814      * and we must perform an enumeration for the specified object
815      */
816     if (QueryCB->EnumHandle == (ULONG_PTR)NULL) {
817         cm_dirOp_t    dirop;
818
819         code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
820         if (code == 0) {
821             code = cm_BPlusDirEnumerate(dscp, userp, &req, TRUE, NULL, !bSkipStatus, &enump);
822             if (code) {
823                 osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumerate failure code=0x%x",
824                           code);
825             }
826             cm_EndDirOp(&dirop);
827         } else {
828             osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BeginDirOp failure code=0x%x",
829                       code);
830         }
831     } else {
832         enump = (cm_direnum_t *)QueryCB->EnumHandle;
833     }
834
835     if (enump && ResultBufferLength) {
836         cm_direnum_entry_t * entryp = NULL;
837
838       getnextentry:
839         if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
840             osi_Log0(afsd_logp, "RDR_EnumerateDirectory out of space, returning");
841             goto outofspace;
842         }
843
844         code = cm_BPlusDirNextEnumEntry(enump, &entryp);
845
846         if ((code == 0 || code == CM_ERROR_STOPNOW) && entryp) {
847             cm_scache_t *scp;
848             int stopnow = (code == CM_ERROR_STOPNOW);
849
850             if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
851                 osi_Log0(afsd_logp, "RDR_EnumerateDirectory skipping . or ..");
852                 if (stopnow)
853                     goto outofspace;
854                 goto getnextentry;
855             }
856
857             if ( FALSE /* bSkipStatus */) {
858                 scp = cm_FindSCache(&entryp->fid);
859                 code = 0;
860             } else {
861                 code = cm_GetSCache(&entryp->fid, &scp, userp, &req);
862             }
863
864             if (!code) {
865                 if (scp) {
866                     code = RDR_PopulateCurrentEntry(pCurrentEntry, dwMaxEntryLength,
867                                                      dscp, scp, userp, &req,
868                                                      entryp->name,
869                                                      cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
870                                                      (bWow64 ? RDR_POP_WOW64 : 0) |
871                                                      (bSkipStatus ? RDR_POP_NO_GETSTATUS : 0),
872                                                      &pCurrentEntry, &dwMaxEntryLength);
873                     cm_ReleaseSCache(scp);
874                 } else {
875                     code = RDR_PopulateCurrentEntryNoScp( pCurrentEntry, dwMaxEntryLength,
876                                                           dscp, &entryp->fid, userp, &req,
877                                                           entryp->name,
878                                                           cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
879                                                           (bWow64 ? RDR_POP_WOW64 : 0),
880                                                           &pCurrentEntry, &dwMaxEntryLength);
881                 }
882                 if (stopnow)
883                     goto outofspace;
884                 goto getnextentry;
885             } else {
886                 osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure scp=0x%p code=0x%x",
887                           scp, code);
888                 if (stopnow)
889                     goto outofspace;
890                 goto getnextentry;
891             }
892         }
893     }
894
895     if (enump && ResultBufferLength == 0) {
896         code = cm_BPlusDirEnumBulkStat(enump);
897         if (code) {
898             osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumBulkStat failure code=0x%x",
899                       code);
900         }
901     }
902   outofspace:
903
904     if (code || enump->next == enump->count || ResultBufferLength == 0) {
905         cm_BPlusDirFreeEnumeration(enump);
906         enump = (cm_direnum_t *)(ULONG_PTR)-1;
907     }
908
909     if (code == 0 || code == CM_ERROR_STOPNOW) {
910         (*ResultCB)->ResultStatus = STATUS_SUCCESS;
911         osi_Log0(afsd_logp, "RDR_EnumerateDirectory SUCCESS");
912     } else {
913         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
914         (*ResultCB)->ResultStatus = status;
915         osi_Log2(afsd_logp, "RDR_EnumerateDirectory Failure code=0x%x status=0x%x",
916                   code, status);
917     }
918
919     if (ResultBufferLength) {
920         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwMaxEntryLength;
921
922         pDirEnumResp->EnumHandle = (ULONG_PTR) enump;
923     }
924
925     if (dscp)
926         cm_ReleaseSCache(dscp);
927
928     return;
929 }
930
931 void
932 RDR_EvaluateNodeByName( IN cm_user_t *userp,
933                         IN AFSFileID ParentID,
934                         IN WCHAR   *FileNameCounted,
935                         IN DWORD    FileNameLength,
936                         IN BOOL     CaseSensitive,
937                         IN BOOL     bWow64,
938                         IN BOOL     bHoldFid,
939                         IN BOOL     bNoFollow,
940                         IN DWORD    ResultBufferLength,
941                         IN OUT AFSCommResult **ResultCB)
942 {
943     AFSDirEnumEntry * pCurrentEntry;
944     size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
945     afs_uint32  code = 0;
946     cm_scache_t * scp = NULL;
947     cm_scache_t * dscp = NULL;
948     cm_req_t      req;
949     cm_fid_t      parentFid;
950     DWORD         status;
951     DWORD         dwRemaining;
952     WCHAR       * wszName = NULL;
953     size_t        cbName;
954     BOOL          bVol = FALSE;
955     wchar_t       FileName[260];
956
957     StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
958
959     RDR_InitReq(&req);
960     if ( bWow64 )
961         req.flags |= CM_REQ_WOW64;
962
963     osi_Log4(afsd_logp, "RDR_EvaluateNodeByName parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
964              ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
965
966     /* Allocate enough room to add a volume prefix if necessary */
967     cbName = FileNameLength + (CM_PREFIX_VOL_CCH + 1) * sizeof(WCHAR);
968     wszName = malloc(cbName);
969     if (!wszName) {
970         osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
971         return;
972     }
973     StringCbCopyNW(wszName, cbName, FileName, FileNameLength);
974     osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, wszName));
975
976     *ResultCB = (AFSCommResult *)malloc(size);
977     if (!(*ResultCB)) {
978         osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
979         free(wszName);
980         return;
981     }
982
983     memset(*ResultCB, 0, size);
984     (*ResultCB)->ResultBufferLength = ResultBufferLength;
985     if (ResultBufferLength)
986         pCurrentEntry = (AFSDirEnumEntry *)&(*ResultCB)->ResultData;
987
988     if (ParentID.Cell != 0) {
989         parentFid.cell   = ParentID.Cell;
990         parentFid.volume = ParentID.Volume;
991         parentFid.vnode  = ParentID.Vnode;
992         parentFid.unique = ParentID.Unique;
993         parentFid.hash   = ParentID.Hash;
994
995         code = cm_GetSCache(&parentFid, &dscp, userp, &req);
996         if (code) {
997             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
998             (*ResultCB)->ResultStatus = status;
999             osi_Log2(afsd_logp, "RDR_EvaluateNodeByName cm_GetSCache parentFID failure code=0x%x status=0x%x",
1000                       code, status);
1001             free(wszName);
1002             return;
1003         }
1004     } else {
1005         (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
1006         osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Object Name Invalid - Cell = 0");
1007         return;
1008     }
1009
1010     /* get the directory size */
1011     lock_ObtainWrite(&dscp->rw);
1012     code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1013                      CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1014     if (code) {
1015         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1016         (*ResultCB)->ResultStatus = status;
1017         lock_ReleaseWrite(&dscp->rw);
1018         cm_ReleaseSCache(dscp);
1019         osi_Log3(afsd_logp, "RDR_EvaluateNodeByName cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1020                  dscp, code, status);
1021         free(wszName);
1022         return;
1023     }
1024     cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1025     lock_ReleaseWrite(&dscp->rw);
1026
1027     if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1028         (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1029         cm_ReleaseSCache(dscp);
1030         osi_Log1(afsd_logp, "RDR_EvaluateNodeByName Not a Directory dscp=0x%p",
1031                  dscp);
1032         free(wszName);
1033         return;
1034     }
1035
1036     code = cm_Lookup(dscp, wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1037
1038     if ((code == CM_ERROR_NOSUCHPATH || code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) &&
1039          (wcschr(wszName, '%') != NULL || wcschr(wszName, '#') != NULL)) {
1040         /*
1041          * A volume reference:  <cell>{%,#}<volume> -> @vol:<cell>{%,#}<volume>
1042          */
1043         StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
1044         StringCbCatNW(wszName, cbName, FileName, FileNameLength);
1045         cm_strlwr_utf16(wszName);
1046         bVol = TRUE;
1047
1048         code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1049     }
1050
1051     if (code == 0 && scp) {
1052         wchar_t shortName[13]=L"";
1053
1054         if (bVol) {
1055             cm_Gen8Dot3VolNameW(scp->fid.cell, scp->fid.volume, shortName, NULL);
1056         } else if (!cm_Is8Dot3(wszName)) {
1057             cm_dirFid_t dfid;
1058
1059             dfid.vnode = htonl(scp->fid.vnode);
1060             dfid.unique = htonl(scp->fid.unique);
1061
1062             cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
1063         } else {
1064             shortName[0] = '\0';
1065         }
1066
1067         code = RDR_PopulateCurrentEntry(pCurrentEntry, ResultBufferLength,
1068                                         dscp, scp, userp, &req,
1069                                         FileName, shortName,
1070                                         (bWow64 ? RDR_POP_WOW64 : 0) |
1071                                         (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
1072                                         NULL, &dwRemaining);
1073         if (bHoldFid)
1074             RDR_FlagScpInUse( scp, FALSE );
1075         cm_ReleaseSCache(scp);
1076
1077         if (code) {
1078             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1079             (*ResultCB)->ResultStatus = status;
1080             osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
1081                       code, status);
1082         } else {
1083             (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1084             (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1085             osi_Log0(afsd_logp, "RDR_EvaluateNodeByName SUCCESS");
1086         }
1087     } else if (code) {
1088         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1089         (*ResultCB)->ResultStatus = status;
1090         osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
1091                  code, status);
1092     } else {
1093         (*ResultCB)->ResultStatus = STATUS_NO_SUCH_FILE;
1094         osi_Log0(afsd_logp, "RDR_EvaluateNodeByName No Such File");
1095     }
1096     cm_ReleaseSCache(dscp);
1097     free(wszName);
1098
1099     return;
1100 }
1101
1102 void
1103 RDR_EvaluateNodeByID( IN cm_user_t *userp,
1104                       IN AFSFileID ParentID,            /* not used */
1105                       IN AFSFileID SourceID,
1106                       IN BOOL      bWow64,
1107                       IN BOOL      bNoFollow,
1108                       IN BOOL      bHoldFid,
1109                       IN DWORD     ResultBufferLength,
1110                       IN OUT AFSCommResult **ResultCB)
1111 {
1112     AFSDirEnumEntry * pCurrentEntry;
1113     size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1114     afs_uint32  code = 0;
1115     cm_scache_t * scp = NULL;
1116     cm_scache_t * dscp = NULL;
1117     cm_req_t      req;
1118     cm_fid_t      Fid;
1119     cm_fid_t      parentFid;
1120     DWORD         status;
1121     DWORD         dwRemaining;
1122
1123     osi_Log4(afsd_logp, "RDR_EvaluateNodeByID source FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1124               SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
1125     osi_Log4(afsd_logp, "... parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1126               ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1127
1128     *ResultCB = (AFSCommResult *)malloc(size);
1129     if (!(*ResultCB)) {
1130         osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Out of Memory");
1131         return;
1132     }
1133
1134     memset(*ResultCB, 0, size);
1135     (*ResultCB)->ResultBufferLength = ResultBufferLength;
1136     dwRemaining = ResultBufferLength;
1137     if (ResultBufferLength)
1138         pCurrentEntry = (AFSDirEnumEntry *)&(*ResultCB)->ResultData;
1139
1140     RDR_InitReq(&req);
1141     if ( bWow64 )
1142         req.flags |= CM_REQ_WOW64;
1143
1144     if (SourceID.Cell != 0) {
1145         Fid.cell   = SourceID.Cell;
1146         Fid.volume = SourceID.Volume;
1147         Fid.vnode  = SourceID.Vnode;
1148         Fid.unique = SourceID.Unique;
1149         Fid.hash   = SourceID.Hash;
1150
1151         code = cm_GetSCache(&Fid, &scp, userp, &req);
1152         if (code) {
1153             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1154             (*ResultCB)->ResultStatus = status;
1155             osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache SourceFID failure code=0x%x status=0x%x",
1156                       code, status);
1157             return;
1158         }
1159     } else {
1160         (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
1161         osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Object Name Invalid - Cell = 0");
1162         return;
1163     }
1164
1165     if (ParentID.Cell != 0) {
1166         cm_SetFid(&parentFid, ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1167         code = cm_GetSCache(&parentFid, &dscp, userp, &req);
1168         if (code) {
1169             cm_ReleaseSCache(scp);
1170             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1171             (*ResultCB)->ResultStatus = status;
1172             osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
1173                       code, status);
1174             return;
1175         }
1176     } else if (SourceID.Vnode == 1) {
1177         dscp = scp;
1178         cm_HoldSCache(dscp);
1179     } else if (scp->parentVnode) {
1180         cm_SetFid(&parentFid, SourceID.Cell, SourceID.Volume, scp->parentVnode, scp->parentUnique);
1181         code = cm_GetSCache(&parentFid, &dscp, userp, &req);
1182         if (code) {
1183             cm_ReleaseSCache(scp);
1184             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1185             (*ResultCB)->ResultStatus = status;
1186             osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
1187                       code, status);
1188             return;
1189         }
1190     } else {
1191         (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
1192         osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Object Path Invalid - Unknown Parent");
1193         return;
1194     }
1195
1196     /* Make sure the directory is current */
1197     lock_ObtainWrite(&dscp->rw);
1198     code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1199                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1200     if (code) {
1201         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1202         (*ResultCB)->ResultStatus = status;
1203         lock_ReleaseWrite(&dscp->rw);
1204         cm_ReleaseSCache(dscp);
1205         cm_ReleaseSCache(scp);
1206         osi_Log3(afsd_logp, "RDR_EvaluateNodeByID cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1207                  dscp, code, status);
1208         return;
1209     }
1210
1211     cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1212     lock_ReleaseWrite(&dscp->rw);
1213
1214     if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1215         (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1216         cm_ReleaseSCache(dscp);
1217         cm_ReleaseSCache(scp);
1218         osi_Log1(afsd_logp, "RDR_EvaluateNodeByID Not a Directory dscp=0x%p", dscp);
1219         return;
1220     }
1221
1222     code = RDR_PopulateCurrentEntry(pCurrentEntry, ResultBufferLength,
1223                                     dscp, scp, userp, &req, NULL, NULL,
1224                                     (bWow64 ? RDR_POP_WOW64 : 0) |
1225                                     (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
1226                                     NULL, &dwRemaining);
1227
1228     if (bHoldFid)
1229         RDR_FlagScpInUse( scp, FALSE );
1230     cm_ReleaseSCache(scp);
1231     cm_ReleaseSCache(dscp);
1232
1233     if (code) {
1234         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1235         (*ResultCB)->ResultStatus = status;
1236         osi_Log2(afsd_logp, "RDR_EvaluateNodeByID FAILURE code=0x%x status=0x%x",
1237                  code, status);
1238     } else {
1239         (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1240         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1241         osi_Log0(afsd_logp, "RDR_EvaluateNodeByID SUCCESS");
1242     }
1243     return;
1244 }
1245
1246 void
1247 RDR_CreateFileEntry( IN cm_user_t *userp,
1248                      IN WCHAR *FileNameCounted,
1249                      IN DWORD FileNameLength,
1250                      IN AFSFileCreateCB *CreateCB,
1251                      IN BOOL bWow64,
1252                      IN BOOL bHoldFid,
1253                      IN DWORD ResultBufferLength,
1254                      IN OUT AFSCommResult **ResultCB)
1255 {
1256     AFSFileCreateResultCB *pResultCB = NULL;
1257     size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1258     cm_fid_t            parentFid;
1259     afs_uint32          code;
1260     cm_scache_t *       dscp = NULL;
1261     afs_uint32          flags = 0;
1262     cm_attr_t           setAttr;
1263     cm_scache_t *       scp = NULL;
1264     cm_req_t            req;
1265     DWORD               status;
1266     wchar_t             FileName[260];
1267
1268     StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
1269
1270     osi_Log4(afsd_logp, "RDR_CreateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1271               CreateCB->ParentId.Cell, CreateCB->ParentId.Volume,
1272               CreateCB->ParentId.Vnode, CreateCB->ParentId.Unique);
1273     osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
1274
1275     RDR_InitReq(&req);
1276     if ( bWow64 )
1277         req.flags |= CM_REQ_WOW64;
1278     memset(&setAttr, 0, sizeof(cm_attr_t));
1279
1280     *ResultCB = (AFSCommResult *)malloc(size);
1281     if (!(*ResultCB)) {
1282         osi_Log0(afsd_logp, "RDR_CreateFileEntry out of memory");
1283         return;
1284     }
1285
1286     memset( *ResultCB,
1287             '\0',
1288             size);
1289
1290     parentFid.cell   = CreateCB->ParentId.Cell;
1291     parentFid.volume = CreateCB->ParentId.Volume;
1292     parentFid.vnode  = CreateCB->ParentId.Vnode;
1293     parentFid.unique = CreateCB->ParentId.Unique;
1294     parentFid.hash   = CreateCB->ParentId.Hash;
1295
1296     code = cm_GetSCache(&parentFid, &dscp, userp, &req);
1297     if (code) {
1298         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1299         (*ResultCB)->ResultStatus = status;
1300         osi_Log2(afsd_logp, "RDR_CreateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1301                   code, status);
1302         return;
1303     }
1304
1305     lock_ObtainWrite(&dscp->rw);
1306     code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1307                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1308     if (code) {
1309         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1310         (*ResultCB)->ResultStatus = status;
1311         lock_ReleaseWrite(&dscp->rw);
1312         cm_ReleaseSCache(dscp);
1313         osi_Log3(afsd_logp, "RDR_CreateFileEntry cm_SyncOp failure (1) dscp=0x%p code=0x%x status=0x%x",
1314                  dscp, code, status);
1315         return;
1316     }
1317
1318     cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1319     lock_ReleaseWrite(&dscp->rw);
1320
1321     if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1322         (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1323         cm_ReleaseSCache(dscp);
1324         osi_Log1(afsd_logp, "RDR_CreateFileEntry Not a Directory dscp=0x%p",
1325                  dscp);
1326         return;
1327     }
1328
1329     /* Use current time */
1330     setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
1331     setAttr.clientModTime = time(NULL);
1332
1333     if (CreateCB->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1334         if (smb_unixModeDefaultDir) {
1335             setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1336             setAttr.unixModeBits = smb_unixModeDefaultDir;
1337             if (CreateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)
1338                 setAttr.unixModeBits &= ~0222;          /* disable the write bits */
1339         }
1340
1341         code = cm_MakeDir(dscp, FileName, flags, &setAttr, userp, &req, &scp);
1342     } else {
1343         if (smb_unixModeDefaultFile) {
1344             setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1345             setAttr.unixModeBits = smb_unixModeDefaultFile;
1346             if (CreateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)
1347                 setAttr.unixModeBits &= ~0222;          /* disable the write bits */
1348         }
1349
1350         setAttr.mask |= CM_ATTRMASK_LENGTH;
1351         setAttr.length.LowPart = CreateCB->AllocationSize.LowPart;
1352         setAttr.length.HighPart = CreateCB->AllocationSize.HighPart;
1353         code = cm_Create(dscp, FileName, flags, &setAttr, &scp, userp, &req);
1354     }
1355     if (code == 0) {
1356         wchar_t shortName[13]=L"";
1357         cm_dirFid_t dfid;
1358         DWORD dwRemaining;
1359
1360         (*ResultCB)->ResultStatus = 0;  // We will be able to fit all the data in here
1361
1362         (*ResultCB)->ResultBufferLength = sizeof( AFSFileCreateResultCB);
1363
1364         pResultCB = (AFSFileCreateResultCB *)(*ResultCB)->ResultData;
1365
1366         dwRemaining = ResultBufferLength - sizeof( AFSFileCreateResultCB) + sizeof( AFSDirEnumEntry);
1367
1368         lock_ObtainWrite(&dscp->rw);
1369         code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1370                           CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1371         if (code) {
1372             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1373             (*ResultCB)->ResultStatus = status;
1374             lock_ReleaseWrite(&dscp->rw);
1375             cm_ReleaseSCache(dscp);
1376             cm_ReleaseSCache(scp);
1377             osi_Log3(afsd_logp, "RDR_CreateFileEntry cm_SyncOp failure (2) dscp=0x%p code=0x%x status=0x%x",
1378                       dscp, code, status);
1379             return;
1380         }
1381
1382         pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1383
1384         cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1385         lock_ReleaseWrite(&dscp->rw);
1386
1387         dfid.vnode = htonl(scp->fid.vnode);
1388         dfid.unique = htonl(scp->fid.unique);
1389
1390         if (!cm_Is8Dot3(FileName))
1391             cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
1392         else
1393             shortName[0] = '\0';
1394
1395         code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
1396                                         dscp, scp, userp, &req, FileName, shortName,
1397                                         RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
1398                                         NULL, &dwRemaining);
1399
1400         if (bHoldFid)
1401             RDR_FlagScpInUse( scp, FALSE );
1402         cm_ReleaseSCache(scp);
1403         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1404         osi_Log0(afsd_logp, "RDR_CreateFileEntry SUCCESS");
1405     } else {
1406         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1407         (*ResultCB)->ResultStatus = status;
1408         (*ResultCB)->ResultBufferLength = 0;
1409         osi_Log2(afsd_logp, "RDR_CreateFileEntry FAILURE code=0x%x status=0x%x",
1410                   code, status);
1411     }
1412
1413     cm_ReleaseSCache(dscp);
1414
1415     return;
1416 }
1417
1418 void
1419 RDR_UpdateFileEntry( IN cm_user_t *userp,
1420                      IN AFSFileID FileId,
1421                      IN AFSFileUpdateCB *UpdateCB,
1422                      IN BOOL bWow64,
1423                      IN DWORD ResultBufferLength,
1424                      IN OUT AFSCommResult **ResultCB)
1425 {
1426     AFSFileUpdateResultCB *pResultCB = NULL;
1427     size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1428     cm_fid_t            Fid;
1429     cm_fid_t            parentFid;
1430     afs_uint32          code;
1431     afs_uint32          flags = 0;
1432     cm_attr_t           setAttr;
1433     cm_scache_t *       scp = NULL;
1434     cm_scache_t *       dscp = NULL;
1435     cm_req_t            req;
1436     time_t              clientModTime;
1437     FILETIME            ft;
1438     DWORD               status;
1439     BOOL                bScpLocked = FALSE;
1440
1441     RDR_InitReq(&req);
1442     if ( bWow64 )
1443         req.flags |= CM_REQ_WOW64;
1444     memset(&setAttr, 0, sizeof(cm_attr_t));
1445
1446     osi_Log4(afsd_logp, "RDR_UpdateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1447               UpdateCB->ParentId.Cell, UpdateCB->ParentId.Volume,
1448               UpdateCB->ParentId.Vnode, UpdateCB->ParentId.Unique);
1449     osi_Log4(afsd_logp, "... object FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1450               FileId.Cell, FileId.Volume,
1451               FileId.Vnode, FileId.Unique);
1452
1453     *ResultCB = (AFSCommResult *)malloc( size);
1454     if (!(*ResultCB)) {
1455         osi_Log0(afsd_logp, "RDR_UpdateFileEntry Out of Memory");
1456         return;
1457     }
1458
1459     memset( *ResultCB,
1460             '\0',
1461             size);
1462
1463     parentFid.cell   = UpdateCB->ParentId.Cell;
1464     parentFid.volume = UpdateCB->ParentId.Volume;
1465     parentFid.vnode  = UpdateCB->ParentId.Vnode;
1466     parentFid.unique = UpdateCB->ParentId.Unique;
1467     parentFid.hash   = UpdateCB->ParentId.Hash;
1468
1469     code = cm_GetSCache(&parentFid, &dscp, userp, &req);
1470     if (code) {
1471         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1472         (*ResultCB)->ResultStatus = status;
1473         osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1474                   code, status);
1475         return;
1476     }
1477
1478     lock_ObtainWrite(&dscp->rw);
1479     bScpLocked = TRUE;
1480     code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1481                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1482     if (code) {
1483         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1484         (*ResultCB)->ResultStatus = status;
1485         lock_ReleaseWrite(&dscp->rw);
1486         cm_ReleaseSCache(dscp);
1487         osi_Log3(afsd_logp, "RDR_UpdateFileEntry cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1488                  dscp, code, status);
1489         return;
1490     }
1491
1492     cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1493     lock_ReleaseWrite(&dscp->rw);
1494     bScpLocked = FALSE;
1495
1496     if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1497         (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1498         cm_ReleaseSCache(dscp);
1499         osi_Log1(afsd_logp, "RDR_UpdateFileEntry Not a Directory dscp=0x%p",
1500                  dscp);
1501         return;
1502     }
1503
1504     Fid.cell   = FileId.Cell;
1505     Fid.volume = FileId.Volume;
1506     Fid.vnode  = FileId.Vnode;
1507     Fid.unique = FileId.Unique;
1508     Fid.hash   = FileId.Hash;
1509
1510     code = cm_GetSCache(&Fid, &scp, userp, &req);
1511     if (code) {
1512         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1513         (*ResultCB)->ResultStatus = status;
1514         cm_ReleaseSCache(dscp);
1515         osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache object FID failure code=0x%x status=0x%x",
1516                   code, status);
1517         return;
1518     }
1519
1520     lock_ObtainWrite(&scp->rw);
1521     bScpLocked = TRUE;
1522     code = cm_SyncOp(scp, NULL, userp, &req, 0,
1523                       CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
1524     if (code) {
1525         lock_ReleaseWrite(&scp->rw);
1526         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1527         (*ResultCB)->ResultStatus = status;
1528         (*ResultCB)->ResultBufferLength = 0;
1529         cm_ReleaseSCache(dscp);
1530         cm_ReleaseSCache(scp);
1531         osi_Log3(afsd_logp, "RDR_UpdateFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
1532                  scp, code, status);
1533         return;
1534     }
1535     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1536
1537     if (UpdateCB->ChangeTime.QuadPart) {
1538
1539         if (scp->fileType == CM_SCACHETYPE_FILE) {
1540             /* Do not set length and other attributes at the same time */
1541             if (scp->length.QuadPart != UpdateCB->AllocationSize.QuadPart) {
1542                 osi_Log2(afsd_logp, "RDR_UpdateFileEntry Length Change 0x%x -> 0x%x",
1543                           (afs_uint32)scp->length.QuadPart, (afs_uint32)UpdateCB->AllocationSize.QuadPart);
1544                 setAttr.mask |= CM_ATTRMASK_LENGTH;
1545                 setAttr.length.LowPart = UpdateCB->AllocationSize.LowPart;
1546                 setAttr.length.HighPart = UpdateCB->AllocationSize.HighPart;
1547                 lock_ReleaseWrite(&scp->rw);
1548                 bScpLocked = FALSE;
1549                 code = cm_SetAttr(scp, &setAttr, userp, &req);
1550                 if (code)
1551                     goto on_error;
1552                 setAttr.mask = 0;
1553             }
1554         }
1555
1556         if (!bScpLocked) {
1557             lock_ObtainWrite(&scp->rw);
1558             bScpLocked = TRUE;
1559         }
1560         if ((scp->unixModeBits & 0200) && (UpdateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1561             setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1562             setAttr.unixModeBits = scp->unixModeBits & ~0222;
1563         } else if (!(scp->unixModeBits & 0200) && !(UpdateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1564             setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1565             setAttr.unixModeBits = scp->unixModeBits | 0222;
1566         }
1567     }
1568
1569     if (UpdateCB->LastWriteTime.QuadPart) {
1570         ft.dwLowDateTime = UpdateCB->LastWriteTime.LowPart;
1571         ft.dwHighDateTime = UpdateCB->LastWriteTime.HighPart;
1572
1573         cm_UnixTimeFromLargeSearchTime(& clientModTime, &ft);
1574
1575         if (!bScpLocked) {
1576             lock_ObtainWrite(&scp->rw);
1577             bScpLocked = TRUE;
1578         }
1579         if (scp->clientModTime != clientModTime) {
1580             setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
1581             setAttr.clientModTime = clientModTime;
1582         }
1583
1584         /* call setattr */
1585         if (setAttr.mask) {
1586             lock_ReleaseWrite(&scp->rw);
1587             bScpLocked = FALSE;
1588             code = cm_SetAttr(scp, &setAttr, userp, &req);
1589         } else
1590             code = 0;
1591     }
1592
1593   on_error:
1594     if (bScpLocked) {
1595         lock_ReleaseWrite(&scp->rw);
1596     }
1597
1598     if (code == 0) {
1599         DWORD dwRemaining = ResultBufferLength - sizeof( AFSFileUpdateResultCB) + sizeof( AFSDirEnumEntry);
1600
1601         pResultCB = (AFSFileUpdateResultCB *)(*ResultCB)->ResultData;
1602
1603         code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
1604                                         dscp, scp, userp, &req, NULL, NULL,
1605                                         RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
1606                                         NULL, &dwRemaining);
1607         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1608         osi_Log0(afsd_logp, "RDR_UpdateFileEntry SUCCESS");
1609     } else {
1610         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1611         (*ResultCB)->ResultStatus = status;
1612         (*ResultCB)->ResultBufferLength = 0;
1613         osi_Log2(afsd_logp, "RDR_UpdateFileEntry FAILURE code=0x%x status=0x%x",
1614                   code, status);
1615     }
1616     cm_ReleaseSCache(scp);
1617     cm_ReleaseSCache(dscp);
1618
1619     return;
1620 }
1621
1622 void
1623 RDR_CleanupFileEntry( IN cm_user_t *userp,
1624                       IN AFSFileID FileId,
1625                       IN WCHAR *FileNameCounted,
1626                       IN DWORD FileNameLength,
1627                       IN AFSFileCleanupCB *CleanupCB,
1628                       IN BOOL bWow64,
1629                       IN BOOL bLastHandle,
1630                       IN BOOL bDeleteFile,
1631                       IN BOOL bUnlockFile,
1632                       IN DWORD ResultBufferLength,
1633                       IN OUT AFSCommResult **ResultCB)
1634 {
1635     size_t size = sizeof(AFSCommResult);
1636     cm_fid_t            Fid;
1637     cm_fid_t            parentFid;
1638     afs_uint32          code = 0;
1639     afs_uint32          flags = 0;
1640     cm_attr_t           setAttr;
1641     cm_scache_t *       scp = NULL;
1642     cm_scache_t *       dscp = NULL;
1643     cm_req_t            req;
1644     time_t              clientModTime;
1645     FILETIME            ft;
1646     DWORD               status;
1647     BOOL                bScpLocked = FALSE;
1648     BOOL                bDscpLocked = FALSE;
1649     BOOL                bFlushFile = FALSE;
1650     cm_key_t            key;
1651
1652     RDR_InitReq(&req);
1653     if ( bWow64 )
1654         req.flags |= CM_REQ_WOW64;
1655     memset(&setAttr, 0, sizeof(cm_attr_t));
1656
1657     osi_Log4(afsd_logp, "RDR_CleanupFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1658               CleanupCB->ParentId.Cell, CleanupCB->ParentId.Volume,
1659               CleanupCB->ParentId.Vnode, CleanupCB->ParentId.Unique);
1660     osi_Log4(afsd_logp, "... object FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1661               FileId.Cell, FileId.Volume,
1662               FileId.Vnode, FileId.Unique);
1663
1664     *ResultCB = (AFSCommResult *)malloc( size);
1665     if (!(*ResultCB)) {
1666         osi_Log0(afsd_logp, "RDR_CleanupFileEntry Out of Memory");
1667         return;
1668     }
1669
1670     memset( *ResultCB,
1671             '\0',
1672             size);
1673
1674     parentFid.cell   = CleanupCB->ParentId.Cell;
1675     parentFid.volume = CleanupCB->ParentId.Volume;
1676     parentFid.vnode  = CleanupCB->ParentId.Vnode;
1677     parentFid.unique = CleanupCB->ParentId.Unique;
1678     parentFid.hash   = CleanupCB->ParentId.Hash;
1679
1680     if (parentFid.cell) {
1681         code = cm_GetSCache(&parentFid, &dscp, userp, &req);
1682         if (code) {
1683             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1684             (*ResultCB)->ResultStatus = status;
1685             osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1686                      code, status);
1687             return;
1688         }
1689
1690         lock_ObtainWrite(&dscp->rw);
1691         bDscpLocked = TRUE;
1692         code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1693                          CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1694         if (code) {
1695             osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp failure dscp=0x%p code=0x%x",
1696                     dscp, code);
1697             if (code)
1698                 goto on_error;
1699         }
1700
1701         cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1702         lock_ReleaseWrite(&dscp->rw);
1703         bDscpLocked = FALSE;
1704
1705         if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1706             (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1707             cm_ReleaseSCache(dscp);
1708             osi_Log1(afsd_logp, "RDR_CleanupFileEntry Not a Directory dscp=0x%p",
1709                      dscp);
1710             if (code)
1711                 goto on_error;
1712         }
1713     }
1714
1715     Fid.cell   = FileId.Cell;
1716     Fid.volume = FileId.Volume;
1717     Fid.vnode  = FileId.Vnode;
1718     Fid.unique = FileId.Unique;
1719     Fid.hash   = FileId.Hash;
1720
1721     code = cm_GetSCache(&Fid, &scp, userp, &req);
1722     if (code) {
1723         osi_Log1(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache object FID failure code=0x%x",
1724                  code);
1725         goto on_error;
1726     }
1727
1728     lock_ObtainWrite(&scp->rw);
1729     bScpLocked = TRUE;
1730     code = cm_SyncOp(scp, NULL, userp, &req, 0,
1731                       CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
1732     if (code) {
1733         osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp failure scp=0x%p code=0x%x",
1734                  scp, code);
1735         goto on_error;
1736     }
1737     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1738
1739     if ((bLastHandle || bFlushFile) &&
1740         scp->redirBufCount > 0)
1741     {
1742         LARGE_INTEGER heldExtents;
1743         AFSFileExtentCB extentList[1024];
1744         DWORD extentCount = 0;
1745         cm_buf_t *srbp;
1746         time_t now;
1747
1748         time(&now);
1749         heldExtents.QuadPart = 0;
1750
1751         for ( srbp = redirq_to_cm_buf_t(scp->redirQueueT);
1752               srbp;
1753               srbp = redirq_to_cm_buf_t(osi_QPrev(&srbp->redirq)))
1754         {
1755             extentList[extentCount].Flags = 0;
1756             extentList[extentCount].Length = cm_data.blockSize;
1757             extentList[extentCount].FileOffset.QuadPart = srbp->offset.QuadPart;
1758             extentList[extentCount].CacheOffset.QuadPart = srbp->datap - RDR_extentBaseAddress;
1759             lock_ObtainWrite(&buf_globalLock);
1760             srbp->redirReleaseRequested = now;
1761             lock_ReleaseWrite(&buf_globalLock);
1762             extentCount++;
1763
1764             if (extentCount == 1024) {
1765                 lock_ReleaseWrite(&scp->rw);
1766                 code = RDR_RequestExtentRelease(&scp->fid, heldExtents, extentCount, extentList);
1767                 if (code) {
1768                     if (code == CM_ERROR_RETRY) {
1769                         /*
1770                          * The redirector either is not holding the extents or cannot let them
1771                          * go because they are otherwise in use.  At the moment, do nothing.
1772                          */
1773                     } else
1774                         break;
1775                 }
1776                 extentCount = 0;
1777                 bFlushFile = TRUE;
1778                 lock_ObtainWrite(&scp->rw);
1779             }
1780         }
1781
1782         if (code == 0 && extentCount > 0) {
1783             if (bScpLocked) {
1784                 lock_ReleaseWrite(&scp->rw);
1785                 bScpLocked = FALSE;
1786             }
1787             code = RDR_RequestExtentRelease(&scp->fid, heldExtents, extentCount, extentList);
1788             bFlushFile = TRUE;
1789         }
1790     }
1791
1792     /* No longer in use by redirector */
1793     if (!bScpLocked) {
1794         lock_ObtainWrite(&scp->rw);
1795         bScpLocked = TRUE;
1796     }
1797
1798     if (bLastHandle) {
1799         lock_AssertWrite(&scp->rw);
1800         scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
1801     }
1802
1803     if (bLastHandle || bFlushFile) {
1804         if (!bScpLocked) {
1805             lock_ObtainWrite(&scp->rw);
1806             bScpLocked = TRUE;
1807         }
1808         code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
1809                           CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1810         if (code == 0) {
1811             if (bScpLocked) {
1812                 lock_ReleaseWrite(&scp->rw);
1813                 bScpLocked = FALSE;
1814             }
1815
1816             code = cm_FSync(scp, userp, &req, bScpLocked);
1817         }
1818         if (bLastHandle && code)
1819             goto on_error;
1820     }
1821
1822     if (bUnlockFile || bDeleteFile) {
1823         if (!bScpLocked) {
1824             lock_ObtainWrite(&scp->rw);
1825             bScpLocked = TRUE;
1826         }
1827         code = cm_SyncOp(scp, NULL, userp, &req, 0,
1828                           CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
1829         if (code) {
1830             osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
1831                      scp, code);
1832             goto on_error;
1833         }
1834
1835         key = cm_GenerateKey(CM_SESSION_IFS, CleanupCB->ProcessId, 0);
1836
1837         /* the scp is now locked and current */
1838         code = cm_UnlockByKey(scp, key,
1839                               bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
1840                               userp, &req);
1841
1842         cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
1843
1844         if (code)
1845             goto on_error;
1846     }
1847
1848     if (CleanupCB->ChangeTime.QuadPart) {
1849
1850         if (scp->fileType == CM_SCACHETYPE_FILE) {
1851             /* Do not set length and other attributes at the same time */
1852             if (scp->length.QuadPart != CleanupCB->AllocationSize.QuadPart) {
1853                 osi_Log2(afsd_logp, "RDR_CleanupFileEntry Length Change 0x%x -> 0x%x",
1854                           (afs_uint32)scp->length.QuadPart, (afs_uint32)CleanupCB->AllocationSize.QuadPart);
1855                 setAttr.mask |= CM_ATTRMASK_LENGTH;
1856                 setAttr.length.LowPart = CleanupCB->AllocationSize.LowPart;
1857                 setAttr.length.HighPart = CleanupCB->AllocationSize.HighPart;
1858
1859                 if (bScpLocked) {
1860                     lock_ReleaseWrite(&scp->rw);
1861                     bScpLocked = FALSE;
1862                 }
1863                 code = cm_SetAttr(scp, &setAttr, userp, &req);
1864                 if (code)
1865                     goto on_error;
1866                 setAttr.mask = 0;
1867             }
1868         }
1869
1870         if (!bScpLocked) {
1871             lock_ObtainWrite(&scp->rw);
1872             bScpLocked = TRUE;
1873         }
1874
1875         if ((scp->unixModeBits & 0200) && (CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1876             setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1877             setAttr.unixModeBits = scp->unixModeBits & ~0222;
1878         } else if (!(scp->unixModeBits & 0200) && !(CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1879             setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1880             setAttr.unixModeBits = scp->unixModeBits | 0222;
1881         }
1882     }
1883
1884     if (CleanupCB->LastWriteTime.QuadPart) {
1885         ft.dwLowDateTime = CleanupCB->LastWriteTime.LowPart;
1886         ft.dwHighDateTime = CleanupCB->LastWriteTime.HighPart;
1887
1888         cm_UnixTimeFromLargeSearchTime(&clientModTime, &ft);
1889         if (scp->clientModTime != clientModTime) {
1890             setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
1891             setAttr.clientModTime = clientModTime;
1892         }
1893     }
1894
1895     /* call setattr */
1896     if (setAttr.mask) {
1897         lock_ReleaseWrite(&scp->rw);
1898         bScpLocked = FALSE;
1899         code = cm_SetAttr(scp, &setAttr, userp, &req);
1900     } else
1901         code = 0;
1902
1903     /* Now drop the lock enforcing the share access */
1904     if ( CleanupCB->FileAccess != AFS_FILE_ACCESS_NOLOCK) {
1905         unsigned int sLockType;
1906         LARGE_INTEGER LOffset, LLength;
1907
1908         if (CleanupCB->FileAccess == AFS_FILE_ACCESS_SHARED)
1909             sLockType = LOCKING_ANDX_SHARED_LOCK;
1910         else
1911             sLockType = 0;
1912
1913         key = cm_GenerateKey(CM_SESSION_IFS, SMB_FID_QLOCK_PID, CleanupCB->Identifier);
1914
1915         LOffset.HighPart = SMB_FID_QLOCK_HIGH;
1916         LOffset.LowPart = SMB_FID_QLOCK_LOW;
1917         LLength.HighPart = 0;
1918         LLength.LowPart = SMB_FID_QLOCK_LENGTH;
1919
1920         if (!bScpLocked) {
1921             lock_ObtainWrite(&scp->rw);
1922             bScpLocked = TRUE;
1923         }
1924
1925         code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_LOCK);
1926         if (code == 0)
1927         {
1928             code = cm_Unlock(scp, sLockType, LOffset, LLength, key, 0, userp, &req);
1929
1930             cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
1931
1932             if (code == CM_ERROR_RANGE_NOT_LOCKED)
1933             {
1934                 osi_Log3(afsd_logp, "RDR_CleanupFileEntry Range Not Locked -- FileAccess 0x%x ProcessId 0x%x HandleId 0x%x",
1935                          CleanupCB->FileAccess, CleanupCB->ProcessId, CleanupCB->Identifier);
1936
1937             }
1938         }
1939     }
1940
1941   on_error:
1942     if (bDscpLocked)
1943         lock_ReleaseWrite(&dscp->rw);
1944     if (bScpLocked)
1945         lock_ReleaseWrite(&scp->rw);
1946
1947     if (dscp && bDeleteFile) {
1948         WCHAR FileName[260];
1949
1950         StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
1951
1952         if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
1953             code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
1954         else
1955             code = cm_Unlink(dscp, NULL, FileName, userp, &req);
1956     }
1957
1958     if (code == 0) {
1959         (*ResultCB)->ResultStatus = 0;
1960         (*ResultCB)->ResultBufferLength = 0;
1961         osi_Log0(afsd_logp, "RDR_CleanupFileEntry SUCCESS");
1962     } else {
1963         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1964         (*ResultCB)->ResultStatus = status;
1965         (*ResultCB)->ResultBufferLength = 0;
1966         osi_Log2(afsd_logp, "RDR_CleanupFileEntry FAILURE code=0x%x status=0x%x",
1967                   code, status);
1968     }
1969     if (scp)
1970         cm_ReleaseSCache(scp);
1971     if (dscp)
1972         cm_ReleaseSCache(dscp);
1973
1974     return;
1975 }
1976
1977 void
1978 RDR_DeleteFileEntry( IN cm_user_t *userp,
1979                      IN AFSFileID ParentId,
1980                      IN ULONGLONG ProcessId,
1981                      IN WCHAR *FileNameCounted,
1982                      IN DWORD FileNameLength,
1983                      IN BOOL bWow64,
1984                      IN BOOL bCheckOnly,
1985                      IN DWORD ResultBufferLength,
1986                      IN OUT AFSCommResult **ResultCB)
1987 {
1988
1989     AFSFileDeleteResultCB *pResultCB = NULL;
1990     size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1991     cm_fid_t            parentFid;
1992     afs_uint32          code;
1993     cm_scache_t *       dscp = NULL;
1994     cm_scache_t *       scp = NULL;
1995     afs_uint32          flags = 0;
1996     cm_attr_t           setAttr;
1997     cm_req_t            req;
1998     DWORD               status;
1999     wchar_t             FileName[260];
2000     cm_key_t            key;
2001
2002     StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
2003
2004     osi_Log4(afsd_logp, "RDR_DeleteFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2005               ParentId.Cell,  ParentId.Volume,
2006               ParentId.Vnode, ParentId.Unique);
2007     osi_Log2(afsd_logp, "... name=%S checkOnly=%x",
2008              osi_LogSaveStringW(afsd_logp, FileName),
2009              bCheckOnly);
2010
2011     RDR_InitReq(&req);
2012     if ( bWow64 )
2013         req.flags |= CM_REQ_WOW64;
2014     memset(&setAttr, 0, sizeof(cm_attr_t));
2015
2016     *ResultCB = (AFSCommResult *)malloc( size);
2017     if (!(*ResultCB)) {
2018         osi_Log0(afsd_logp, "RDR_DeleteFileEntry out of memory");
2019         return;
2020     }
2021
2022     memset( *ResultCB,
2023             '\0',
2024             size);
2025
2026     parentFid.cell   = ParentId.Cell;
2027     parentFid.volume = ParentId.Volume;
2028     parentFid.vnode  = ParentId.Vnode;
2029     parentFid.unique = ParentId.Unique;
2030     parentFid.hash   = ParentId.Hash;
2031
2032     code = cm_GetSCache(&parentFid, &dscp, userp, &req);
2033     if (code) {
2034         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2035         (*ResultCB)->ResultStatus = status;
2036         osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
2037                   code, status);
2038         return;
2039     }
2040
2041     lock_ObtainWrite(&dscp->rw);
2042
2043     code = cm_SyncOp(dscp, NULL, userp, &req, 0,
2044                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2045     if (code) {
2046         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2047         (*ResultCB)->ResultStatus = status;
2048         (*ResultCB)->ResultBufferLength = 0;
2049         lock_ReleaseWrite(&dscp->rw);
2050         cm_ReleaseSCache(dscp);
2051         osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
2052                  dscp, code, status);
2053         return;
2054     }
2055
2056     cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2057     lock_ReleaseWrite(&dscp->rw);
2058
2059     if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2060         (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2061         cm_ReleaseSCache(dscp);
2062         osi_Log1(afsd_logp, "RDR_DeleteFileEntry Not a Directory dscp=0x%p",
2063                  dscp);
2064         return;
2065     }
2066
2067     code = cm_Lookup(dscp, FileName, 0, userp, &req, &scp);
2068     if (code) {
2069         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2070         (*ResultCB)->ResultStatus = status;
2071         (*ResultCB)->ResultBufferLength = 0;
2072         cm_ReleaseSCache(dscp);
2073         osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_Lookup failure code=0x%x status=0x%x",
2074                  code, status);
2075         return;
2076     }
2077
2078     lock_ObtainWrite(&scp->rw);
2079     code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_DELETE,
2080                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2081     if (code) {
2082         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2083         (*ResultCB)->ResultStatus = status;
2084         (*ResultCB)->ResultBufferLength = 0;
2085         lock_ReleaseWrite(&scp->rw);
2086         cm_ReleaseSCache(scp);
2087         cm_ReleaseSCache(dscp);
2088         osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2089                  scp, code, status);
2090         return;
2091     }
2092
2093     if (!bCheckOnly) {
2094         /* Drop all locks since the file is being deleted */
2095         code = cm_SyncOp(scp, NULL, userp, &req, 0,
2096                          CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2097         if (code) {
2098             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2099             (*ResultCB)->ResultStatus = status;
2100             (*ResultCB)->ResultBufferLength = 0;
2101             lock_ReleaseWrite(&scp->rw);
2102             cm_ReleaseSCache(scp);
2103             cm_ReleaseSCache(dscp);
2104             osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp Lock failure scp=0x%p code=0x%x status=0x%x",
2105                      scp, code, status);
2106         }
2107
2108         /* the scp is now locked and current */
2109         key = cm_GenerateKey(CM_SESSION_IFS, ProcessId, 0);
2110
2111         code = cm_UnlockByKey(scp, key,
2112                               CM_UNLOCK_FLAG_BY_FID,
2113                               userp, &req);
2114
2115         cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2116         lock_ReleaseWrite(&scp->rw);
2117
2118         if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
2119             code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
2120         else
2121             code = cm_Unlink(dscp, NULL, FileName, userp, &req);
2122     } else {
2123         lock_ReleaseWrite(&scp->rw);
2124     }
2125
2126     if (code == 0) {
2127         (*ResultCB)->ResultStatus = 0;  // We will be able to fit all the data in here
2128
2129         (*ResultCB)->ResultBufferLength = sizeof( AFSFileDeleteResultCB);
2130
2131         pResultCB = (AFSFileDeleteResultCB *)(*ResultCB)->ResultData;
2132
2133         pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
2134         osi_Log0(afsd_logp, "RDR_DeleteFileEntry SUCCESS");
2135     } else {
2136         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2137         (*ResultCB)->ResultStatus = status;
2138         (*ResultCB)->ResultBufferLength = 0;
2139         osi_Log2(afsd_logp, "RDR_DeleteFileEntry FAILURE code=0x%x status=0x%x",
2140                   code, status);
2141     }
2142
2143     cm_ReleaseSCache(dscp);
2144     cm_ReleaseSCache(scp);
2145
2146     return;
2147 }
2148
2149 void
2150 RDR_RenameFileEntry( IN cm_user_t *userp,
2151                      IN WCHAR    *SourceFileNameCounted,
2152                      IN DWORD     SourceFileNameLength,
2153                      IN AFSFileID SourceFileId,
2154                      IN AFSFileRenameCB *pRenameCB,
2155                      IN BOOL bWow64,
2156                      IN DWORD ResultBufferLength,
2157                      IN OUT AFSCommResult **ResultCB)
2158 {
2159
2160     AFSFileRenameResultCB *pResultCB = NULL;
2161     size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2162     AFSFileID              SourceParentId   = pRenameCB->SourceParentId;
2163     AFSFileID              TargetParentId   = pRenameCB->TargetParentId;
2164     WCHAR *                TargetFileNameCounted = pRenameCB->TargetName;
2165     DWORD                  TargetFileNameLength = pRenameCB->TargetNameLength;
2166     cm_fid_t               SourceParentFid;
2167     cm_fid_t               TargetParentFid;
2168     cm_scache_t *          oldDscp;
2169     cm_scache_t *          newDscp;
2170     wchar_t                shortName[13];
2171     wchar_t                SourceFileName[260];
2172     wchar_t                TargetFileName[260];
2173     cm_dirFid_t            dfid;
2174     cm_req_t               req;
2175     afs_uint32             code;
2176     DWORD                  status;
2177
2178     RDR_InitReq(&req);
2179     if ( bWow64 )
2180         req.flags |= CM_REQ_WOW64;
2181
2182     StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
2183     StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
2184
2185     osi_Log4(afsd_logp, "RDR_RenameFileEntry Source Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2186               SourceParentId.Cell,  SourceParentId.Volume,
2187               SourceParentId.Vnode, SourceParentId.Unique);
2188     osi_Log2(afsd_logp, "... Source Name=%S Length %u", osi_LogSaveStringW(afsd_logp, SourceFileName), SourceFileNameLength);
2189     osi_Log4(afsd_logp, "... Target Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2190               TargetParentId.Cell,  TargetParentId.Volume,
2191               TargetParentId.Vnode, TargetParentId.Unique);
2192     osi_Log2(afsd_logp, "... Target Name=%S Length %u", osi_LogSaveStringW(afsd_logp, TargetFileName), TargetFileNameLength);
2193
2194     *ResultCB = (AFSCommResult *)malloc( size);
2195     if (!(*ResultCB))
2196         return;
2197
2198     memset( *ResultCB,
2199             '\0',
2200             size);
2201
2202     pResultCB = (AFSFileRenameResultCB *)(*ResultCB)->ResultData;
2203
2204     if (SourceFileNameLength == 0 || TargetFileNameLength == 0)
2205     {
2206         osi_Log2(afsd_logp, "RDR_RenameFileEntry Invalid Name Length: src %u target %u",
2207                  SourceFileNameLength, TargetFileNameLength);
2208         (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
2209         return;
2210     }
2211
2212     SourceParentFid.cell   = SourceParentId.Cell;
2213     SourceParentFid.volume = SourceParentId.Volume;
2214     SourceParentFid.vnode  = SourceParentId.Vnode;
2215     SourceParentFid.unique = SourceParentId.Unique;
2216     SourceParentFid.hash   = SourceParentId.Hash;
2217
2218     TargetParentFid.cell   = TargetParentId.Cell;
2219     TargetParentFid.volume = TargetParentId.Volume;
2220     TargetParentFid.vnode  = TargetParentId.Vnode;
2221     TargetParentFid.unique = TargetParentId.Unique;
2222     TargetParentFid.hash   = TargetParentId.Hash;
2223
2224     code = cm_GetSCache(&SourceParentFid, &oldDscp, userp, &req);
2225     if (code) {
2226         osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache source parent failed code 0x%x", code);
2227         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2228         (*ResultCB)->ResultStatus = status;
2229         return;
2230     }
2231
2232     lock_ObtainWrite(&oldDscp->rw);
2233     code = cm_SyncOp(oldDscp, NULL, userp, &req, 0,
2234                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2235     if (code) {
2236         osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp oldDscp 0x%p failed code 0x%x", oldDscp, code);
2237         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2238         (*ResultCB)->ResultStatus = status;
2239         lock_ReleaseWrite(&oldDscp->rw);
2240         cm_ReleaseSCache(oldDscp);
2241         return;
2242     }
2243
2244     cm_SyncOpDone(oldDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2245     lock_ReleaseWrite(&oldDscp->rw);
2246
2247
2248     if (oldDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2249         osi_Log1(afsd_logp, "RDR_RenameFileEntry oldDscp 0x%p not a directory", oldDscp);
2250         (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2251         cm_ReleaseSCache(oldDscp);
2252         return;
2253     }
2254
2255     code = cm_GetSCache(&TargetParentFid, &newDscp, userp, &req);
2256     if (code) {
2257         osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target parent failed code 0x%x", code);
2258         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2259         (*ResultCB)->ResultStatus = status;
2260         cm_ReleaseSCache(oldDscp);
2261         return;
2262     }
2263
2264     lock_ObtainWrite(&newDscp->rw);
2265     code = cm_SyncOp(newDscp, NULL, userp, &req, 0,
2266                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2267     if (code) {
2268         osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp newDscp 0x%p failed code 0x%x", newDscp, code);
2269         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2270         (*ResultCB)->ResultStatus = status;
2271         lock_ReleaseWrite(&newDscp->rw);
2272         cm_ReleaseSCache(oldDscp);
2273         cm_ReleaseSCache(newDscp);
2274         return;
2275     }
2276
2277     cm_SyncOpDone(newDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2278     lock_ReleaseWrite(&newDscp->rw);
2279
2280
2281     if (newDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2282         osi_Log1(afsd_logp, "RDR_RenameFileEntry newDscp 0x%p not a directory", newDscp);
2283         (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2284         cm_ReleaseSCache(oldDscp);
2285         cm_ReleaseSCache(newDscp);
2286         return;
2287     }
2288
2289     code = cm_Rename( oldDscp, NULL, SourceFileName,
2290                       newDscp, TargetFileName, userp, &req);
2291     if (code == 0) {
2292         cm_dirOp_t dirop;
2293         cm_fid_t   targetFid;
2294         cm_scache_t *scp = 0;
2295         DWORD dwRemaining;
2296
2297         (*ResultCB)->ResultBufferLength = ResultBufferLength;
2298         dwRemaining = ResultBufferLength - sizeof( AFSFileRenameResultCB) + sizeof( AFSDirEnumEntry);
2299         (*ResultCB)->ResultStatus = 0;
2300
2301         pResultCB->SourceParentDataVersion.QuadPart = oldDscp->dataVersion;
2302         pResultCB->TargetParentDataVersion.QuadPart = newDscp->dataVersion;
2303
2304         osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p SUCCESS",
2305                  oldDscp, newDscp);
2306
2307         code = cm_BeginDirOp( newDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2308         if (code == 0) {
2309             code = cm_BPlusDirLookup(&dirop, TargetFileName, &targetFid);
2310             cm_EndDirOp(&dirop);
2311         }
2312
2313         if (code != 0) {
2314             osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_BPlusDirLookup failed code 0x%x",
2315                      code);
2316             (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
2317             cm_ReleaseSCache(oldDscp);
2318             cm_ReleaseSCache(newDscp);
2319             return;
2320         }
2321
2322         osi_Log4(afsd_logp, "RDR_RenameFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2323                   targetFid.cell,  targetFid.volume,
2324                   targetFid.vnode, targetFid.unique);
2325
2326         code = cm_GetSCache(&targetFid, &scp, userp, &req);
2327         if (code) {
2328             osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target failed code 0x%x", code);
2329             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2330             (*ResultCB)->ResultStatus = status;
2331             cm_ReleaseSCache(oldDscp);
2332             cm_ReleaseSCache(newDscp);
2333             return;
2334         }
2335
2336         /* Make sure the source vnode is current */
2337         lock_ObtainWrite(&scp->rw);
2338         code = cm_SyncOp(scp, NULL, userp, &req, 0,
2339                           CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2340         if (code) {
2341             osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp scp 0x%p failed code 0x%x", scp, code);
2342             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2343             (*ResultCB)->ResultStatus = status;
2344             lock_ReleaseWrite(&scp->rw);
2345             cm_ReleaseSCache(oldDscp);
2346             cm_ReleaseSCache(newDscp);
2347             cm_ReleaseSCache(scp);
2348             return;
2349         }
2350
2351         cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2352         lock_ReleaseWrite(&scp->rw);
2353
2354         dfid.vnode = htonl(scp->fid.vnode);
2355         dfid.unique = htonl(scp->fid.unique);
2356
2357         if (!cm_Is8Dot3(TargetFileName))
2358             cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
2359         else
2360             shortName[0] = '\0';
2361
2362         RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
2363                                  newDscp, scp, userp, &req, TargetFileName, shortName,
2364                                  RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
2365                                  NULL, &dwRemaining);
2366         (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
2367         cm_ReleaseSCache(scp);
2368
2369         osi_Log0(afsd_logp, "RDR_RenameFileEntry SUCCESS");
2370     } else {
2371         osi_Log3(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p failed code 0x%x",
2372                  oldDscp, newDscp, code);
2373         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2374         (*ResultCB)->ResultStatus = status;
2375         (*ResultCB)->ResultBufferLength = 0;
2376     }
2377
2378     cm_ReleaseSCache(oldDscp);
2379     cm_ReleaseSCache(newDscp);
2380     return;
2381 }
2382
2383 void
2384 RDR_FlushFileEntry( IN cm_user_t *userp,
2385                     IN AFSFileID FileId,
2386                     IN BOOL bWow64,
2387                     IN DWORD ResultBufferLength,
2388                     IN OUT AFSCommResult **ResultCB)
2389 {
2390     cm_scache_t *scp = NULL;
2391     cm_fid_t    Fid;
2392     afs_uint32  code;
2393     cm_req_t    req;
2394     DWORD       status;
2395 #ifdef ODS_DEBUG
2396     char        dbgstr[1024];
2397 #endif
2398
2399     RDR_InitReq(&req);
2400     if ( bWow64 )
2401         req.flags |= CM_REQ_WOW64;
2402
2403     osi_Log4(afsd_logp, "RDR_FlushFileEntry File FID cell 0x%x vol 0x%x vno 0x%x uniq 0x%x",
2404               FileId.Cell, FileId.Volume,
2405               FileId.Vnode, FileId.Unique);
2406 #ifdef ODS_DEBUG
2407     snprintf( dbgstr, 1024,
2408               "RDR_FlushFileEntry File FID cell 0x%x vol 0x%x vno 0x%x uniq 0x%x\n",
2409               FileId.Cell, FileId.Volume,
2410               FileId.Vnode, FileId.Unique);
2411     OutputDebugStringA( dbgstr);
2412 #endif
2413
2414     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
2415     if (!(*ResultCB)) {
2416         osi_Log0(afsd_logp, "RDR_FlushFileEntry out of memory");
2417         return;
2418     }
2419
2420     memset( *ResultCB,
2421             '\0',
2422             sizeof( AFSCommResult));
2423
2424     /* Process the release */
2425     Fid.cell = FileId.Cell;
2426     Fid.volume = FileId.Volume;
2427     Fid.vnode = FileId.Vnode;
2428     Fid.unique = FileId.Unique;
2429     Fid.hash = FileId.Hash;
2430
2431     code = cm_GetSCache(&Fid, &scp, userp, &req);
2432     if (code) {
2433         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2434         (*ResultCB)->ResultStatus = status;
2435         osi_Log2(afsd_logp, "RDR_FlushFileEntry cm_GetSCache FID failure code=0x%x status=0x%x",
2436                   code, status);
2437         return;
2438     }
2439
2440     lock_ObtainWrite(&scp->rw);
2441     if (scp->flags & CM_SCACHEFLAG_DELETED) {
2442         lock_ReleaseWrite(&scp->rw);
2443         (*ResultCB)->ResultStatus = STATUS_INVALID_HANDLE;
2444         return;
2445     }
2446
2447     code = cm_SyncOp(scp, NULL, userp, &req, 0,
2448                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2449     if (code) {
2450         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2451         (*ResultCB)->ResultStatus = status;
2452         lock_ReleaseWrite(&scp->rw);
2453         cm_ReleaseSCache(scp);
2454         osi_Log3(afsd_logp, "RDR_FlushFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2455                  scp, code, status);
2456         return;
2457     }
2458
2459     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2460     lock_ReleaseWrite(&scp->rw);
2461
2462     code = cm_FSync(scp, userp, &req, FALSE);
2463     cm_ReleaseSCache(scp);
2464
2465     if (code) {
2466         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2467         (*ResultCB)->ResultStatus = status;
2468         osi_Log2(afsd_logp, "RDR_FlushFileEntry FAILURE code=0x%x status=0x%x",
2469                   code, status);
2470     } else {
2471         (*ResultCB)->ResultStatus = 0;
2472         osi_Log0(afsd_logp, "RDR_FlushFileEntry SUCCESS");
2473     }
2474     (*ResultCB)->ResultBufferLength = 0;
2475
2476     return;
2477 }
2478
2479 afs_uint32
2480 RDR_CheckAccess( IN cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
2481                  ULONG access,
2482                  ULONG *granted)
2483 {
2484     ULONG afs_acc, afs_gr;
2485     BOOLEAN file, dir;
2486     afs_uint32 code = 0;
2487
2488     file = (scp->fileType == CM_SCACHETYPE_FILE);
2489     dir = !file;
2490
2491     /* access definitions from prs_fs.h */
2492     afs_acc = 0;
2493     if (access & FILE_READ_DATA)
2494         afs_acc |= PRSFS_READ;
2495     if (access & FILE_READ_EA || access & FILE_READ_ATTRIBUTES)
2496         afs_acc |= PRSFS_READ;
2497     if (file && ((access & FILE_WRITE_DATA) || (access & FILE_APPEND_DATA)))
2498         afs_acc |= PRSFS_WRITE;
2499     if (access & FILE_WRITE_EA || access & FILE_WRITE_ATTRIBUTES)
2500         afs_acc |= PRSFS_WRITE;
2501     if (dir && ((access & FILE_ADD_FILE) || (access & FILE_ADD_SUBDIRECTORY)))
2502         afs_acc |= PRSFS_INSERT;
2503     if (dir && (access & FILE_LIST_DIRECTORY))
2504         afs_acc |= PRSFS_LOOKUP;
2505     if (file && (access & FILE_EXECUTE))
2506         afs_acc |= PRSFS_WRITE;
2507     if (dir && (access & FILE_TRAVERSE))
2508         afs_acc |= PRSFS_READ;
2509     if (dir && (access & FILE_DELETE_CHILD))
2510         afs_acc |= PRSFS_DELETE;
2511     if ((access & DELETE))
2512         afs_acc |= PRSFS_DELETE;
2513
2514     /* check ACL with server */
2515     lock_ObtainWrite(&scp->rw);
2516     while (1)
2517     {
2518         if (cm_HaveAccessRights(scp, userp, reqp, afs_acc, &afs_gr))
2519         {
2520             break;
2521         }
2522         else
2523         {
2524             /* we don't know the required access rights */
2525             code = cm_GetAccessRights(scp, userp, reqp);
2526             if (code)
2527                 break;
2528             continue;
2529         }
2530     }
2531     lock_ReleaseWrite(&(scp->rw));
2532
2533     if (code == 0) {
2534         *granted = 0;
2535         if (afs_gr & PRSFS_READ)
2536             *granted |= FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES | FILE_EXECUTE;
2537         if (afs_gr & PRSFS_WRITE)
2538             *granted |= FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES | FILE_EXECUTE;
2539         if (afs_gr & PRSFS_INSERT)
2540             *granted |= (dir ? FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY : 0) | (file ? FILE_ADD_SUBDIRECTORY : 0);
2541         if (afs_gr & PRSFS_LOOKUP)
2542             *granted |= (dir ? FILE_LIST_DIRECTORY : 0);
2543         if (afs_gr & PRSFS_DELETE)
2544             *granted |= FILE_DELETE_CHILD | DELETE;
2545         if (afs_gr & PRSFS_LOCK)
2546             *granted |= 0;
2547         if (afs_gr & PRSFS_ADMINISTER)
2548             *granted |= 0;
2549
2550         *granted |= SYNCHRONIZE | READ_CONTROL;
2551
2552         /* don't give more access than what was requested */
2553         *granted &= access;
2554         osi_Log3(afsd_logp, "RDR_CheckAccess SUCCESS scp=0x%p requested=0x%x granted=0x%x", scp, access, *granted);
2555     } else
2556         osi_Log2(afsd_logp, "RDR_CheckAccess FAILURE scp=0x%p code=0x%x",
2557                  scp, code);
2558
2559     return code;
2560 }
2561
2562 void
2563 RDR_OpenFileEntry( IN cm_user_t *userp,
2564                    IN AFSFileID FileId,
2565                    IN AFSFileOpenCB *OpenCB,
2566                    IN BOOL bWow64,
2567                    IN BOOL bHoldFid,
2568                    IN DWORD ResultBufferLength,
2569                    IN OUT AFSCommResult **ResultCB)
2570 {
2571     AFSFileOpenResultCB *pResultCB = NULL;
2572     cm_scache_t *scp = NULL;
2573     cm_user_t   *sysUserp = NULL;
2574     cm_fid_t    Fid;
2575     cm_lock_data_t      *ldp = NULL;
2576     afs_uint32  code;
2577     cm_req_t    req;
2578     DWORD       status;
2579
2580     RDR_InitReq(&req);
2581     if ( bWow64 )
2582         req.flags |= CM_REQ_WOW64;
2583
2584     osi_Log4(afsd_logp, "RDR_OpenFileEntry File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2585               FileId.Cell, FileId.Volume,
2586               FileId.Vnode, FileId.Unique);
2587
2588     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof( AFSFileOpenResultCB));
2589     if (!(*ResultCB)) {
2590         osi_Log0(afsd_logp, "RDR_OpenFileEntry out of memory");
2591         return;
2592     }
2593
2594     memset( *ResultCB,
2595             '\0',
2596             sizeof( AFSCommResult) + sizeof( AFSFileOpenResultCB));
2597
2598     pResultCB = (AFSFileOpenResultCB *)(*ResultCB)->ResultData;
2599
2600     /* Process the release */
2601     Fid.cell = FileId.Cell;
2602     Fid.volume = FileId.Volume;
2603     Fid.vnode = FileId.Vnode;
2604     Fid.unique = FileId.Unique;
2605     Fid.hash = FileId.Hash;
2606
2607     code = cm_GetSCache(&Fid, &scp, userp, &req);
2608     if (code) {
2609         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2610         (*ResultCB)->ResultStatus = status;
2611         osi_Log2(afsd_logp, "RDR_OpenFileEntry cm_GetSCache FID failure code=0x%x status=0x%x",
2612                   code, status);
2613         return;
2614     }
2615
2616     lock_ObtainWrite(&scp->rw);
2617     code = cm_SyncOp(scp, NULL, userp, &req, 0,
2618                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2619     if (code) {
2620         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2621         (*ResultCB)->ResultStatus = status;
2622         lock_ReleaseWrite(&scp->rw);
2623         cm_ReleaseSCache(scp);
2624         osi_Log3(afsd_logp, "RDR_OpenFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2625                  scp, code, status);
2626         return;
2627     }
2628
2629     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2630     lock_ReleaseWrite(&scp->rw);
2631
2632     sysUserp = RDR_GetLocalSystemUser();
2633
2634     /*
2635      * Skip the open check if the request is coming from the local system account.
2636      * The local system has no tokens and therefore any requests sent to a file
2637      * server will fail.  Unfortunately, there are special system processes that
2638      * perform actions on files and directories in preparation for memory mapping
2639      * executables.  If the open check fails, the real request from the user process
2640      * will never be issued.
2641      *
2642      * Permitting the file system to allow subsequent operations to proceed does
2643      * not compromise security.  All requests to obtain file data or directory
2644      * enumerations will subsequently fail if they are not submitted under the
2645      * context of a process for that have access to the necessary credentials.
2646      */
2647
2648     if ( userp == sysUserp)
2649     {
2650         osi_Log1(afsd_logp, "RDR_OpenFileEntry LOCAL_SYSTEM access check skipped scp=0x%p",
2651                  scp);
2652         pResultCB->GrantedAccess = OpenCB->DesiredAccess;
2653         pResultCB->FileAccess = AFS_FILE_ACCESS_NOLOCK;
2654         code = 0;
2655     }
2656     else
2657     {
2658         int count = 0;
2659
2660         do {
2661             if (count++ > 0) {
2662                 Sleep(350);
2663                 osi_Log3(afsd_logp,
2664                          "RDR_OpenFileEntry repeating open check scp=0x%p userp=0x%p code=0x%x",
2665                          scp, userp, code);
2666             }
2667             code = cm_CheckNTOpen(scp, OpenCB->DesiredAccess, OpenCB->ShareAccess,
2668                                   OPEN_ALWAYS,
2669                                   OpenCB->ProcessId, OpenCB->Identifier,
2670                                   userp, &req, &ldp);
2671             if (code == 0)
2672                 code = RDR_CheckAccess(scp, userp, &req, OpenCB->DesiredAccess, &pResultCB->GrantedAccess);
2673             cm_CheckNTOpenDone(scp, userp, &req, &ldp);
2674         } while (count < 100 && (code == CM_ERROR_RETRY || code == CM_ERROR_WOULDBLOCK));
2675     }
2676
2677     /*
2678      * If we are restricting sharing, we should do so with a suitable
2679      * share lock.
2680      */
2681     if (code == 0 && scp->fileType == CM_SCACHETYPE_FILE && !(OpenCB->ShareAccess & FILE_SHARE_WRITE)) {
2682         cm_key_t key;
2683         LARGE_INTEGER LOffset, LLength;
2684         int sLockType;
2685
2686         LOffset.HighPart = SMB_FID_QLOCK_HIGH;
2687         LOffset.LowPart = SMB_FID_QLOCK_LOW;
2688         LLength.HighPart = 0;
2689         LLength.LowPart = SMB_FID_QLOCK_LENGTH;
2690
2691         /*
2692          * If we are not opening the file for writing, then we don't
2693          * try to get an exclusive lock.  No one else should be able to
2694          * get an exclusive lock on the file anyway, although someone
2695          * else can get a shared lock.
2696          */
2697         if ((OpenCB->ShareAccess & FILE_SHARE_READ) || !(OpenCB->DesiredAccess & AFS_ACCESS_WRITE))
2698         {
2699             sLockType = LOCKING_ANDX_SHARED_LOCK;
2700         } else {
2701             sLockType = 0;
2702         }
2703
2704         key = cm_GenerateKey(CM_SESSION_IFS, SMB_FID_QLOCK_PID, OpenCB->Identifier);
2705
2706         lock_ObtainWrite(&scp->rw);
2707         code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
2708         lock_ReleaseWrite(&scp->rw);
2709
2710         if (code) {
2711             code = CM_ERROR_SHARING_VIOLATION;
2712             pResultCB->FileAccess = AFS_FILE_ACCESS_NOLOCK;
2713         } else {
2714             if (sLockType == LOCKING_ANDX_SHARED_LOCK)
2715                 pResultCB->FileAccess = AFS_FILE_ACCESS_SHARED;
2716             else
2717                 pResultCB->FileAccess = AFS_FILE_ACCESS_EXCLUSIVE;
2718         }
2719     } else {
2720         pResultCB->FileAccess = AFS_FILE_ACCESS_NOLOCK;
2721     }
2722
2723     cm_ReleaseUser(sysUserp);
2724     if (code == 0 && bHoldFid)
2725         RDR_FlagScpInUse( scp, FALSE );
2726     cm_ReleaseSCache(scp);
2727
2728     if (code) {
2729         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2730         (*ResultCB)->ResultStatus = status;
2731         osi_Log2(afsd_logp, "RDR_OpenFileEntry FAILURE code=0x%x status=0x%x",
2732                   code, status);
2733     } else {
2734         (*ResultCB)->ResultStatus = 0;
2735         (*ResultCB)->ResultBufferLength = sizeof( AFSFileOpenResultCB);
2736         osi_Log0(afsd_logp, "RDR_OpenFileEntry SUCCESS");
2737     }
2738     return;
2739 }
2740
2741 void
2742 RDR_ReleaseFileAccess( IN cm_user_t *userp,
2743                        IN AFSFileID FileId,
2744                        IN AFSFileAccessReleaseCB *ReleaseFileCB,
2745                        IN BOOL bWow64,
2746                        IN DWORD ResultBufferLength,
2747                        IN OUT AFSCommResult **ResultCB)
2748 {
2749     cm_key_t key;
2750     unsigned int sLockType;
2751     LARGE_INTEGER LOffset, LLength;
2752     cm_scache_t *scp = NULL;
2753     cm_fid_t    Fid;
2754     afs_uint32  code;
2755     cm_req_t    req;
2756     DWORD       status;
2757
2758     RDR_InitReq(&req);
2759     if ( bWow64 )
2760         req.flags |= CM_REQ_WOW64;
2761
2762     osi_Log4(afsd_logp, "RDR_ReleaseFileAccess File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2763               FileId.Cell, FileId.Volume,
2764               FileId.Vnode, FileId.Unique);
2765
2766     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
2767     if (!(*ResultCB)) {
2768         osi_Log0(afsd_logp, "RDR_ReleaseFileAccess out of memory");
2769         return;
2770     }
2771
2772     memset( *ResultCB, '\0', sizeof( AFSCommResult));
2773
2774     if (ReleaseFileCB->FileAccess == AFS_FILE_ACCESS_NOLOCK)
2775         return;
2776
2777     /* Process the release */
2778     Fid.cell = FileId.Cell;
2779     Fid.volume = FileId.Volume;
2780     Fid.vnode = FileId.Vnode;
2781     Fid.unique = FileId.Unique;
2782     Fid.hash = FileId.Hash;
2783
2784     code = cm_GetSCache(&Fid, &scp, userp, &req);
2785     if (code) {
2786         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2787         (*ResultCB)->ResultStatus = status;
2788         osi_Log2(afsd_logp, "RDR_ReleaseFileAccess cm_GetSCache FID failure code=0x%x status=0x%x",
2789                   code, status);
2790         return;
2791     }
2792
2793     if (ReleaseFileCB->FileAccess == AFS_FILE_ACCESS_SHARED)
2794         sLockType = LOCKING_ANDX_SHARED_LOCK;
2795     else
2796         sLockType = 0;
2797
2798     key = cm_GenerateKey(CM_SESSION_IFS, SMB_FID_QLOCK_PID, ReleaseFileCB->Identifier);
2799
2800     LOffset.HighPart = SMB_FID_QLOCK_HIGH;
2801     LOffset.LowPart = SMB_FID_QLOCK_LOW;
2802     LLength.HighPart = 0;
2803     LLength.LowPart = SMB_FID_QLOCK_LENGTH;
2804
2805     lock_ObtainWrite(&scp->rw);
2806
2807     code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_LOCK);
2808     if (code == 0)
2809     {
2810         code = cm_Unlock(scp, sLockType, LOffset, LLength, key, 0, userp, &req);
2811
2812         cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
2813
2814         if (code == CM_ERROR_RANGE_NOT_LOCKED)
2815         {
2816             osi_Log3(afsd_logp, "RDR_ReleaseFileAccess Range Not Locked -- FileAccess 0x%x ProcessId 0x%x HandleId 0x%x",
2817                      ReleaseFileCB->FileAccess, ReleaseFileCB->ProcessId, ReleaseFileCB->Identifier);
2818         }
2819     }
2820
2821     lock_ReleaseWrite(&scp->rw);
2822
2823     osi_Log0(afsd_logp, "RDR_ReleaseFileAccessEntry SUCCESS");
2824 }
2825
2826 static const char *
2827 HexCheckSum(unsigned char * buf, int buflen, unsigned char * md5cksum)
2828 {
2829     int i, k;
2830     static char tr[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
2831
2832     if (buflen < 33)
2833         return "buffer length too small to HexCheckSum";
2834
2835     for (i=0;i<16;i++) {
2836         k = md5cksum[i];
2837
2838         buf[i*2] = tr[k / 16];
2839         buf[i*2+1] = tr[k % 16];
2840     }
2841     buf[32] = '\0';
2842
2843     return buf;
2844 }
2845
2846 /*
2847  * Extent requests from the file system are triggered when a file
2848  * page is not resident in the Windows cache.  The file system is
2849  * responsible for loading the page but cannot block the request
2850  * while doing so.  The AFS Redirector forwards the requests to
2851  * the AFS cache manager while indicating to Windows that the page
2852  * is not yet available.  A polling operation will then ensue with
2853  * the AFS Redirector issuing a RDR_RequestFileExtentsXXX call for
2854  * each poll attempt.  As each request is received and processed
2855  * by a separate worker thread in the service, this can lead to
2856  * contention by multiple threads attempting to claim the same
2857  * cm_buf_t objects.  Therefore, it is important that
2858  *
2859  *  (a) the service avoid processing more than one overlapping
2860  *      extent request at a time
2861  *  (b) background daemon processing be used to avoid blocking
2862  *      of ioctl threads
2863  *
2864  * Beginning with the 20091122 build of the redirector, the redirector
2865  * will not issue an additional RDR_RequestFileExtentsXXX call for
2866  * each poll request.  Instead, afsd_service is required to track
2867  * the requests and return them to the redirector or fail the
2868  * portions of the request that cannot be satisfied.
2869  *
2870  * The request processing returns any extents that can be returned
2871  * immediately to the redirector.  The rest of the requested range(s)
2872  * are queued as background operations using RDR_BkgFetch().
2873  */
2874
2875 /* do the background fetch. */
2876 afs_int32
2877 RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
2878              cm_user_t *userp, cm_req_t *reqp)
2879 {
2880     osi_hyper_t length;
2881     osi_hyper_t base;
2882     osi_hyper_t offset;
2883     osi_hyper_t end;
2884     osi_hyper_t fetched;
2885     osi_hyper_t tblocksize;
2886     afs_int32 code;
2887     int rwheld = 0;
2888     cm_buf_t *bufp = NULL;
2889     DWORD dwResultBufferLength;
2890     AFSSetFileExtentsCB *pResultCB;
2891     DWORD status;
2892     afs_uint32 count=0;
2893     AFSFileID FileId;
2894     int reportErrorToRedir = 0;
2895     int force_retry = 0;
2896
2897     FileId.Cell = scp->fid.cell;
2898     FileId.Volume = scp->fid.volume;
2899     FileId.Vnode = scp->fid.vnode;
2900     FileId.Unique = scp->fid.unique;
2901     FileId.Hash = scp->fid.hash;
2902
2903     if ((GetTickCount() - reqp->startTime) / 1000 > HardDeadtimeout * 5) {
2904         RDR_SetFileStatus( &scp->fid, &userp->authgroup, STATUS_IO_TIMEOUT);
2905         return 0;
2906     }
2907
2908     fetched.LowPart = 0;
2909     fetched.HighPart = 0;
2910     tblocksize = ConvertLongToLargeInteger(cm_data.buf_blockSize);
2911     base.LowPart = p1;
2912     base.HighPart = p2;
2913     length.LowPart = p3;
2914     length.HighPart = p4;
2915
2916     end = LargeIntegerAdd(base, length);
2917
2918     osi_Log5(afsd_logp, "Starting BKG Fetch scp 0x%p offset 0x%x:%x length 0x%x:%x",
2919              scp, p2, p1, p4, p3);
2920
2921     /*
2922      * Make sure we have a callback.
2923      * This is necessary so that we can return access denied
2924      * if a callback cannot be granted.
2925      */
2926     lock_ObtainWrite(&scp->rw);
2927     code = cm_SyncOp(scp, NULL, userp, reqp, PRSFS_READ,
2928                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2929     if (code) {
2930         lock_ReleaseWrite(&scp->rw);
2931         osi_Log2(afsd_logp, "RDR_BkgFetch cm_SyncOp failure scp=0x%p code=0x%x",
2932                  scp, code);
2933         smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
2934         RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
2935         return code;
2936     }
2937     lock_ReleaseWrite(&scp->rw);
2938
2939     dwResultBufferLength = (DWORD)(sizeof( AFSSetFileExtentsCB) + sizeof( AFSSetFileExtentsCB) * (length.QuadPart / cm_data.blockSize + 1));
2940     pResultCB = (AFSSetFileExtentsCB *)malloc( dwResultBufferLength );
2941     if (!pResultCB)
2942         return CM_ERROR_RETRY;
2943
2944     memset( pResultCB, '\0', dwResultBufferLength );
2945     pResultCB->FileId = FileId;
2946
2947     for ( code = 0, offset = base;
2948           code == 0 && LargeIntegerLessThan(offset, end);
2949           offset = LargeIntegerAdd(offset, tblocksize) )
2950     {
2951         int bBufRelease = TRUE;
2952
2953         if (rwheld) {
2954             lock_ReleaseWrite(&scp->rw);
2955             rwheld = 0;
2956         }
2957
2958         code = buf_Get(scp, &offset, reqp, &bufp);
2959         if (code) {
2960             /*
2961              * any error from buf_Get() is non-fatal.
2962              * we need to re-queue this extent fetch.
2963              */
2964             force_retry = 1;
2965             break;
2966         }
2967
2968         if (!rwheld) {
2969             lock_ObtainWrite(&scp->rw);
2970             rwheld = 1;
2971         }
2972
2973         code = cm_GetBuffer(scp, bufp, NULL, userp, reqp);
2974         if (code == 0) {
2975             if (!(bufp->qFlags & CM_BUF_QREDIR)) {
2976 #ifdef VALIDATE_CHECK_SUM
2977 #ifdef ODS_DEBUG
2978                 char md5dbg[33];
2979                 char dbgstr[1024];
2980 #endif
2981 #endif
2982                 if (bufp->flags & CM_BUF_DIRTY)
2983                     cm_BufWrite(scp, &bufp->offset, cm_data.buf_blockSize, CM_BUF_WRITE_SCP_LOCKED, userp, reqp);
2984
2985                 lock_ObtainWrite(&buf_globalLock);
2986                 if (!(bufp->flags & CM_BUF_DIRTY) &&
2987                     bufp->cmFlags == 0 &&
2988                     !(bufp->qFlags & CM_BUF_QREDIR)) {
2989                     buf_InsertToRedirQueue(scp, bufp);
2990                     lock_ReleaseWrite(&buf_globalLock);
2991
2992 #ifdef VALIDATE_CHECK_SUM
2993                     buf_ComputeCheckSum(bufp);
2994 #endif
2995                     pResultCB->FileExtents[count].Flags = 0;
2996                     pResultCB->FileExtents[count].FileOffset.QuadPart = bufp->offset.QuadPart;
2997                     pResultCB->FileExtents[count].CacheOffset.QuadPart = bufp->datap - RDR_extentBaseAddress;
2998                     pResultCB->FileExtents[count].Length = cm_data.blockSize;
2999                     count++;
3000                     fetched = LargeIntegerAdd(fetched, tblocksize);
3001                     bBufRelease = FALSE;
3002
3003 #ifdef VALIDATE_CHECK_SUM
3004 #ifdef ODS_DEBUG
3005                     HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3006                     snprintf( dbgstr, 1024,
3007                               "RDR_BkgFetch md5 %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3008                               md5dbg,
3009                               scp->fid.volume, scp->fid.vnode, scp->fid.unique,
3010                               pResultCB->FileExtents[count].FileOffset.HighPart,
3011                               pResultCB->FileExtents[count].FileOffset.LowPart,
3012                               pResultCB->FileExtents[count].CacheOffset.HighPart,
3013                               pResultCB->FileExtents[count].CacheOffset.LowPart);
3014                     OutputDebugStringA( dbgstr);
3015 #endif
3016 #endif
3017                     osi_Log4(afsd_logp, "RDR_BkgFetch Extent2FS bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3018                               bufp, bufp->offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3019                 } else {
3020                     lock_ReleaseWrite(&buf_globalLock);
3021                     if ((bufp->cmFlags != 0) || (bufp->flags & CM_BUF_DIRTY)) {
3022                         /* An I/O operation is already in progress */
3023                         force_retry = 1;
3024                         osi_Log4(afsd_logp, "RDR_BkgFetch Extent2FS Not delivering to Redirector Dirty or Busy bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3025                                   bufp, bufp->offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3026                     } else {
3027                         osi_Log4(afsd_logp, "RDR_BkgFetch Extent2FS Already held by Redirector bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3028                                   bufp, bufp->offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3029                     }
3030                 }
3031             } else {
3032                 osi_Log4(afsd_logp, "RDR_BkgFetch Extent2FS Already held by Redirector bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3033                           bufp, bufp->offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3034             }
3035         } else {
3036             /*
3037              * depending on what the error from cm_GetBuffer is
3038              * it may or may not be fatal.  Only return fatal errors.
3039              * Re-queue a request for others.
3040              */
3041             osi_Log5(afsd_logp, "RDR_BkgFetch Extent2FS FAILURE bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x code 0x%x",
3042                       bufp, offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize, code);
3043             switch (code) {
3044             case CM_ERROR_NOACCESS:
3045             case CM_ERROR_NOSUCHFILE:
3046             case CM_ERROR_NOSUCHPATH:
3047             case CM_ERROR_NOSUCHVOLUME:
3048             case CM_ERROR_NOSUCHCELL:
3049             case CM_ERROR_INVAL:
3050             case CM_ERROR_BADFD:
3051             case CM_ERROR_CLOCKSKEW:
3052             case RXKADNOAUTH:
3053             case CM_ERROR_QUOTA:
3054             case CM_ERROR_LOCK_CONFLICT:
3055                 /*
3056                  * these are fatal errors.  deliver what we can
3057                  * and halt.
3058                  */
3059                 reportErrorToRedir = 1;
3060                 break;
3061             default:
3062                 /*
3063                  * non-fatal errors.  re-queue the exent
3064                  */
3065                 code = CM_ERROR_RETRY;
3066                 force_retry = 1;
3067             }
3068         }
3069
3070         if (bBufRelease)
3071             buf_Release(bufp);
3072     }
3073
3074     if (!rwheld) {
3075         lock_ObtainWrite(&scp->rw);
3076         rwheld = 1;
3077     }
3078
3079     /* wakeup anyone who is waiting */
3080     if (scp->flags & CM_SCACHEFLAG_WAITING) {
3081         osi_Log1(afsd_logp, "RDR Bkg Fetch Waking scp 0x%p", scp);
3082         osi_Wakeup((LONG_PTR) &scp->flags);
3083     }
3084     lock_ReleaseWrite(&scp->rw);
3085
3086     if (count > 0) {
3087         pResultCB->ExtentCount = count;
3088         RDR_SetFileExtents( pResultCB, dwResultBufferLength);
3089     }
3090     free(pResultCB);
3091
3092     if (reportErrorToRedir) {
3093         smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
3094         RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
3095     }
3096
3097     osi_Log4(afsd_logp, "Ending BKG Fetch scp 0x%p code 0x%x fetched 0x%x:%x",
3098              scp, code, fetched.HighPart, fetched.LowPart);
3099
3100     return force_retry ? CM_ERROR_RETRY : code;
3101 }
3102
3103
3104 BOOL
3105 RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
3106                              IN AFSFileID FileId,
3107                              IN AFSRequestExtentsCB *RequestExtentsCB,
3108                              IN BOOL bWow64,
3109                              IN OUT DWORD * ResultBufferLength,
3110                              IN OUT AFSSetFileExtentsCB **ResultCB)
3111 {
3112     AFSSetFileExtentsCB *pResultCB = NULL;
3113     DWORD Length;
3114     DWORD count;
3115     DWORD status;
3116     cm_scache_t *scp = NULL;
3117     cm_fid_t    Fid;
3118     cm_buf_t    *bufp;
3119     afs_uint32  code = 0;
3120     osi_hyper_t thyper;
3121     LARGE_INTEGER ByteOffset, BeginOffset, EndOffset, QueueOffset;
3122     afs_uint32  QueueLength;
3123     cm_req_t    req;
3124     BOOLEAN     bBufRelease = TRUE;
3125
3126     RDR_InitReq(&req);
3127     if ( bWow64 )
3128         req.flags |= CM_REQ_WOW64;
3129     req.flags |= CM_REQ_NORETRY;
3130
3131     osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3132               FileId.Cell, FileId.Volume,
3133               FileId.Vnode, FileId.Unique);
3134     osi_Log4(afsd_logp, "... Flags 0x%x ByteOffset 0x%x:%x Length 0x%x",
3135              RequestExtentsCB->Flags,
3136              RequestExtentsCB->ByteOffset.HighPart, RequestExtentsCB->ByteOffset.LowPart,
3137              RequestExtentsCB->Length);
3138     Length = sizeof( AFSSetFileExtentsCB) + sizeof( AFSFileExtentCB) * (RequestExtentsCB->Length / cm_data.blockSize + 1);
3139
3140     pResultCB = *ResultCB = (AFSSetFileExtentsCB *)malloc( Length );
3141     if (*ResultCB == NULL) {
3142         *ResultBufferLength = 0;
3143         return FALSE;
3144     }
3145     *ResultBufferLength = Length;
3146
3147     memset( pResultCB, '\0', Length );
3148     pResultCB->FileId = FileId;
3149
3150     Fid.cell = FileId.Cell;
3151     Fid.volume = FileId.Volume;
3152     Fid.vnode = FileId.Vnode;
3153     Fid.unique = FileId.Unique;
3154     Fid.hash = FileId.Hash;
3155
3156     code = cm_GetSCache(&Fid, &scp, userp, &req);
3157     if (code) {
3158         osi_Log1(afsd_logp, "RDR_RequestFileExtentsAsync cm_GetSCache FID failure code=0x%x",
3159                   code);
3160         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3161         return FALSE;
3162     }
3163
3164     /*
3165      * Make sure we have a callback.
3166      * This is necessary so that we can return access denied
3167      * if a callback cannot be granted.
3168      */
3169     lock_ObtainWrite(&scp->rw);
3170     code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
3171                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3172     lock_ReleaseWrite(&scp->rw);
3173     if (code) {
3174         cm_ReleaseSCache(scp);
3175         osi_Log2(afsd_logp, "RDR_RequestFileExtentsAsync cm_SyncOp failure scp=0x%p code=0x%x",
3176                  scp, code);
3177         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3178         RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
3179         return FALSE;
3180     }
3181
3182     /* Allocate the extents from the buffer package */
3183     for ( count = 0,
3184           ByteOffset = BeginOffset = RequestExtentsCB->ByteOffset,
3185           EndOffset.QuadPart = ByteOffset.QuadPart + RequestExtentsCB->Length;
3186           code == 0 && ByteOffset.QuadPart < EndOffset.QuadPart;
3187           ByteOffset.QuadPart += cm_data.blockSize)
3188     {
3189         BOOL bHaveBuffer = FALSE;
3190
3191         QueueLength = 0;
3192         thyper.QuadPart = ByteOffset.QuadPart;
3193
3194         code = buf_Get(scp, &thyper, &req, &bufp);
3195         if (code == 0) {
3196             lock_ObtainMutex(&bufp->mx);
3197             bBufRelease = TRUE;
3198
3199             if (bufp->qFlags & CM_BUF_QREDIR) {
3200                 bHaveBuffer = TRUE;
3201             } else if (bufp->flags & CM_BUF_DIRTY) {
3202                 bHaveBuffer = FALSE;
3203 #if 0
3204                 code = buf_CleanAsyncLocked(scp, bufp, &req, 0, NULL);
3205                 switch (code) {
3206                 case 0:
3207                     bHaveBuffer = TRUE;
3208                     break;
3209                 case CM_ERROR_RETRY:
3210                     /* Couldn't flush it, obtain it asynchronously so we don't block the thread. */
3211                     bHaveBuffer = FALSE;
3212                     code = 0;
3213                     break;
3214                 default:
3215                     smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3216                     RDR_SetFileStatus(&FileId, &userp->authgroup, status);
3217                     bHaveBuffer = FALSE;
3218                     code = 0;
3219                 }
3220 #endif
3221             } else {
3222                 osi_hyper_t minLength;  /* effective end of file */
3223
3224                 lock_ObtainRead(&scp->rw);
3225                 bHaveBuffer = cm_HaveBuffer(scp, bufp, TRUE);
3226
3227                 if (LargeIntegerGreaterThan(scp->length, scp->serverLength))
3228                     minLength = scp->serverLength;
3229                 else
3230                     minLength = scp->length;
3231
3232                 if (!bHaveBuffer &&
3233                     LargeIntegerGreaterThanOrEqualTo(bufp->offset, minLength)) {
3234                     memset(bufp->datap, 0, cm_data.buf_blockSize);
3235                     bufp->dataVersion = scp->dataVersion;
3236                     bHaveBuffer = TRUE;
3237                 }
3238                 else if ((RequestExtentsCB->Flags & AFS_EXTENT_FLAG_CLEAN) &&
3239                          ByteOffset.QuadPart <= bufp->offset.QuadPart &&
3240                          EndOffset.QuadPart >= bufp->offset.QuadPart + cm_data.blockSize)
3241                 {
3242                     memset(bufp->datap, 0, cm_data.blockSize);
3243                     bufp->dataVersion = scp->dataVersion;
3244                     buf_SetDirty(bufp, &req, 0, cm_data.blockSize, userp);
3245                     bHaveBuffer = TRUE;
3246                 }
3247                 lock_ReleaseRead(&scp->rw);
3248             }
3249
3250             /*
3251              * if this buffer is already up to date, skip it.
3252              */
3253             if (bHaveBuffer) {
3254                 if (ByteOffset.QuadPart == BeginOffset.QuadPart) {
3255                     BeginOffset.QuadPart += cm_data.blockSize;
3256                 } else {
3257                     QueueLength = (afs_uint32)(ByteOffset.QuadPart - BeginOffset.QuadPart);
3258                     QueueOffset = BeginOffset;
3259                     BeginOffset = ByteOffset;
3260                 }
3261
3262                 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3263 #ifdef VALIDATE_CHECK_SUM
3264 #ifdef ODS_DEBUG
3265                     char md5dbg[33];
3266                     char dbgstr[1024];
3267 #endif
3268 #endif
3269                     lock_ObtainWrite(&buf_globalLock);
3270                     if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3271                         buf_InsertToRedirQueue(scp, bufp);
3272                         lock_ReleaseWrite(&buf_globalLock);
3273
3274 #ifdef VALIDATE_CHECK_SUM
3275                         buf_ComputeCheckSum(bufp);
3276 #endif
3277                         /* we already have the buffer, return it now */
3278                         pResultCB->FileExtents[count].Flags = 0;
3279                         pResultCB->FileExtents[count].FileOffset = ByteOffset;
3280                         pResultCB->FileExtents[count].CacheOffset.QuadPart = bufp->datap - RDR_extentBaseAddress;
3281                         pResultCB->FileExtents[count].Length = cm_data.blockSize;
3282                         count++;
3283
3284                         bBufRelease = FALSE;
3285
3286 #ifdef VALIDATE_CHECK_SUM
3287 #ifdef ODS_DEBUG
3288                         HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3289                         snprintf( dbgstr, 1024,
3290                                   "RDR_RequestFileExtentsAsync md5 %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3291                                   md5dbg,
3292                                   scp->fid.volume, scp->fid.vnode, scp->fid.unique,
3293                                   pResultCB->FileExtents[count].FileOffset.HighPart,
3294                                   pResultCB->FileExtents[count].FileOffset.LowPart,
3295                                   pResultCB->FileExtents[count].CacheOffset.HighPart,
3296                                   pResultCB->FileExtents[count].CacheOffset.LowPart);
3297                         OutputDebugStringA( dbgstr);
3298 #endif
3299 #endif
3300                         osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync Extent2FS bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3301                                  bufp, ByteOffset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3302                     } else {
3303                         lock_ReleaseWrite(&buf_globalLock);
3304                     }
3305                 } else {
3306                     if (bBufRelease) {
3307                         /*
3308                          * The service is not handing off the extent to the redirector in this pass.
3309                          * However, we know the buffer is in recent use so move the buffer to the
3310                          * front of the queue
3311                          */
3312                         lock_ObtainWrite(&buf_globalLock);
3313                         buf_MoveToHeadOfRedirQueue(scp, bufp);
3314                         lock_ReleaseWrite(&buf_globalLock);
3315
3316                         osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync Extent2FS Already held by Redirector bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3317                                  bufp, ByteOffset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3318                     }
3319                 }
3320             }
3321             lock_ReleaseMutex(&bufp->mx);
3322             if (bBufRelease)
3323                 buf_Release(bufp);
3324
3325             if (QueueLength) {
3326                 cm_QueueBKGRequest(scp, RDR_BkgFetch, QueueOffset.LowPart, QueueOffset.HighPart,
3327                                    QueueLength, 0, userp, &req);
3328                 osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
3329                          QueueOffset.HighPart, QueueOffset.LowPart, QueueLength);
3330             }
3331         } else {
3332             /* No error from buf_Get() can be fatal */
3333             osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync buf_Get FAILURE offset 0x%x:%x code 0x%x",
3334                      BeginOffset.HighPart, BeginOffset.LowPart, code);
3335         }
3336     }
3337
3338     if (BeginOffset.QuadPart != EndOffset.QuadPart) {
3339         afs_uint32 length = (afs_uint32)(EndOffset.QuadPart - BeginOffset.QuadPart);
3340
3341         cm_QueueBKGRequest(scp, RDR_BkgFetch, BeginOffset.LowPart, BeginOffset.HighPart,
3342                            length, 0, userp, &req);
3343         osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
3344                   BeginOffset.HighPart, BeginOffset.LowPart, length);
3345     }
3346     cm_ReleaseSCache(scp);
3347
3348     (*ResultCB)->ExtentCount = count;
3349     osi_Log1(afsd_logp, "RDR_RequestFileExtentsAsync replying with 0x%x extent records", count);
3350     return FALSE;
3351 }
3352
3353 /*
3354  * When processing an extent release the extents must be accepted back by
3355  * the service even if there is an error condition returned to the redirector.
3356  * For example, there may no longer be a callback present or the file may
3357  * have been deleted on the file server.  Regardless, the extents must be
3358  * put back into the pool.
3359  */
3360 void
3361 RDR_ReleaseFileExtents( IN cm_user_t *userp,
3362                         IN AFSFileID FileId,
3363                         IN AFSReleaseExtentsCB *ReleaseExtentsCB,
3364                         IN BOOL bWow64,
3365                         IN DWORD ResultBufferLength,
3366                         IN OUT AFSCommResult **ResultCB)
3367 {
3368     DWORD count;
3369     cm_scache_t *scp = NULL;
3370     cm_fid_t    Fid;
3371     cm_buf_t    *bufp;
3372     afs_uint32  code;
3373     osi_hyper_t thyper;
3374     cm_req_t    req;
3375     int         dirty = 0;
3376     int         released = 0;
3377     DWORD       status;
3378 #ifdef ODS_DEBUG
3379 #ifdef VALIDATE_CHECK_SUM
3380     char md5dbg[33], md5dbg2[33], md5dbg3[33];
3381 #endif
3382     char dbgstr[1024];
3383 #endif
3384
3385     RDR_InitReq(&req);
3386     if ( bWow64 )
3387         req.flags |= CM_REQ_WOW64;
3388
3389     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3390               FileId.Cell, FileId.Volume,
3391               FileId.Vnode, FileId.Unique);
3392
3393     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
3394     if (!(*ResultCB))
3395         return;
3396
3397     memset( *ResultCB,
3398             '\0',
3399             sizeof( AFSCommResult));
3400
3401     /* Process the release */
3402     Fid.cell = FileId.Cell;
3403     Fid.volume = FileId.Volume;
3404     Fid.vnode = FileId.Vnode;
3405     Fid.unique = FileId.Unique;
3406     Fid.hash = FileId.Hash;
3407
3408     code = cm_GetSCache(&Fid, &scp, userp, &req);
3409     if (code) {
3410         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3411         (*ResultCB)->ResultStatus = status;
3412         osi_Log2(afsd_logp, "RDR_ReleaseFileExtents cm_GetSCache FID failure code=0x%x status=0x%x",
3413                   code, status);
3414     }
3415
3416     /*
3417      * We do not stop processing as a result of being unable to find the cm_scache object.
3418      * If this occurs something really bad has happened since the cm_scache object must have
3419      * been recycled while extents were held by the redirector.  However, we will be resilient
3420      * and carry on without it.
3421      */
3422     if (scp && ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart) {
3423         cm_attr_t setAttr;
3424
3425         memset(&setAttr, 0, sizeof(cm_attr_t));
3426         lock_ObtainWrite(&scp->rw);
3427         if (ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart) {
3428
3429             osi_Log4(afsd_logp, "RDR_ReleaseFileExtents new length fid vol 0x%x vno 0x%x length 0x%x:%x",
3430                       scp->fid.volume, scp->fid.vnode,
3431                       ReleaseExtentsCB->AllocationSize.HighPart,
3432                       ReleaseExtentsCB->AllocationSize.LowPart);
3433
3434             setAttr.mask |= CM_ATTRMASK_LENGTH;
3435             setAttr.length.LowPart = ReleaseExtentsCB->AllocationSize.LowPart;
3436             setAttr.length.HighPart = ReleaseExtentsCB->AllocationSize.HighPart;
3437         }
3438         lock_ReleaseWrite(&scp->rw);
3439         if (setAttr.mask)
3440             code = cm_SetAttr(scp, &setAttr, userp, &req);
3441     }
3442
3443     for ( count = 0; count < ReleaseExtentsCB->ExtentCount; count++) {
3444         AFSFileExtentCB * pExtent = &ReleaseExtentsCB->FileExtents[count];
3445
3446         thyper.QuadPart = pExtent->FileOffset.QuadPart;
3447
3448         bufp = buf_Find(&Fid, &thyper);
3449         if (bufp) {
3450             if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
3451                 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3452                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3453                               Fid.volume, Fid.vnode,
3454                               pExtent->FileOffset.HighPart,
3455                               pExtent->FileOffset.LowPart);
3456                     osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; previously released",
3457                               pExtent->CacheOffset.HighPart,
3458                               pExtent->CacheOffset.LowPart);
3459                 } else {
3460                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3461                               Fid.volume, Fid.vnode,
3462                               pExtent->FileOffset.HighPart,
3463                               pExtent->FileOffset.LowPart);
3464                     osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; owned by redirector",
3465                               pExtent->CacheOffset.HighPart,
3466                               pExtent->CacheOffset.LowPart);
3467                 }
3468                 buf_Release(bufp);
3469                 continue;
3470             }
3471
3472             if (pExtent->Flags & AFS_EXTENT_FLAG_IN_USE) {
3473                 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3474                           Fid.volume, Fid.vnode,
3475                           pExtent->FileOffset.HighPart,
3476                           pExtent->FileOffset.LowPart);
3477                 osi_Log2(afsd_logp, "... coffset 0x%x:%x IN_USE by file system",
3478                           pExtent->CacheOffset.HighPart,
3479                           pExtent->CacheOffset.LowPart);
3480
3481                 /* Move the buffer to the front of the queue */
3482                 lock_ObtainWrite(&buf_globalLock);
3483                 buf_MoveToHeadOfRedirQueue(scp, bufp);
3484                 lock_ReleaseWrite(&buf_globalLock);
3485                 buf_Release(bufp);
3486                 continue;
3487             }
3488
3489             if (bufp->datap - RDR_extentBaseAddress == pExtent->CacheOffset.QuadPart) {
3490                 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3491                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x not held by file system",
3492                              Fid.volume, Fid.vnode, pExtent->FileOffset.HighPart,
3493                              pExtent->FileOffset.LowPart);
3494                     osi_Log2(afsd_logp, "... coffset 0x%x:%x",
3495                              pExtent->CacheOffset.HighPart,
3496                              pExtent->CacheOffset.LowPart);
3497                 } else {
3498                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents bufp 0x%p vno 0x%x foffset 0x%x:%x",
3499                               bufp, bufp->fid.vnode, pExtent->FileOffset.HighPart,
3500                               pExtent->FileOffset.LowPart);
3501                     osi_Log2(afsd_logp, "... coffset 0x%x:%x",
3502                              pExtent->CacheOffset.HighPart,
3503                              pExtent->CacheOffset.LowPart);
3504
3505                     if (pExtent->Flags || ReleaseExtentsCB->Flags) {
3506                         lock_ObtainMutex(&bufp->mx);
3507                         if ( (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_RELEASE) ||
3508                              (pExtent->Flags & AFS_EXTENT_FLAG_RELEASE) )
3509                         {
3510                             if (bufp->qFlags & CM_BUF_QREDIR) {
3511                                 lock_ObtainWrite(&buf_globalLock);
3512                                 if (bufp->qFlags & CM_BUF_QREDIR) {
3513                                     buf_RemoveFromRedirQueue(scp, bufp);
3514                                     buf_ReleaseLocked(bufp, TRUE);
3515                                 }
3516                                 lock_ReleaseWrite(&buf_globalLock);
3517                             }
3518 #ifdef ODS_DEBUG
3519                             snprintf( dbgstr, 1024,
3520                                       "RDR_ReleaseFileExtents releasing: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3521                                       Fid.volume, Fid.vnode, Fid.unique,
3522                                       pExtent->FileOffset.HighPart,
3523                                       pExtent->FileOffset.LowPart,
3524                                       pExtent->CacheOffset.HighPart,
3525                                       pExtent->CacheOffset.LowPart);
3526                             OutputDebugStringA( dbgstr);
3527 #endif
3528                             released++;
3529                         } else {
3530 #ifdef ODS_DEBUG
3531                             snprintf( dbgstr, 1024,
3532                                       "RDR_ReleaseFileExtents not releasing: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3533                                       Fid.volume, Fid.vnode, Fid.unique,
3534                                       pExtent->FileOffset.HighPart,
3535                                       pExtent->FileOffset.LowPart,
3536                                       pExtent->CacheOffset.HighPart,
3537                                       pExtent->CacheOffset.LowPart);
3538                             OutputDebugStringA( dbgstr);
3539 #endif
3540                             osi_Log4( afsd_logp, "RDR_ReleaseFileExtents not releasing vol 0x%x vno 0x%x foffset 0x%x:%x",
3541                                       Fid.volume, Fid.vnode,
3542                                       pExtent->FileOffset.HighPart,
3543                                       pExtent->FileOffset.LowPart);
3544                             osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3545                                       pExtent->CacheOffset.HighPart,
3546                                       pExtent->CacheOffset.LowPart);
3547                         }
3548
3549                         if ( (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
3550                              (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY) )
3551                         {
3552 #ifdef VALIDATE_CHECK_SUM
3553 #ifdef ODS_DEBUG
3554                             HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3555 #endif
3556
3557                             /*
3558                              * if the saved checksum matches the checksum of the current state of the buffer
3559                              * then the buffer is the same as what was given to the kernel.
3560                              */
3561                             if ( buf_ValidateCheckSum(bufp) ) {
3562                                 buf_ComputeCheckSum(bufp);
3563
3564                                 if (pExtent->Flags & AFS_EXTENT_FLAG_MD5_SET)
3565                                 {
3566 #ifdef ODS_DEBUG
3567                                     HexCheckSum(md5dbg2, sizeof(md5dbg2), pExtent->MD5);
3568                                     HexCheckSum(md5dbg3, sizeof(md5dbg3), bufp->md5cksum);
3569 #endif
3570                                     if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
3571                                     {
3572 #ifdef ODS_DEBUG
3573                                         snprintf( dbgstr, 1024,
3574                                                   "RDR_ReleaseFileExtents dirty flag set but not dirty and user != kernel: old %s kernel %s new %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3575                                                   md5dbg, md5dbg2,md5dbg3,
3576                                                   Fid.volume, Fid.vnode, Fid.unique,
3577                                                   pExtent->FileOffset.HighPart,
3578                                                   pExtent->FileOffset.LowPart,
3579                                                   pExtent->CacheOffset.HighPart,
3580                                                   pExtent->CacheOffset.LowPart);
3581                                         OutputDebugStringA( dbgstr);
3582 #endif
3583                                         osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set and checksums do not match! vol 0x%x vno 0x%x foffset 0x%x:%x",
3584                                                   Fid.volume, Fid.vnode,
3585                                                   pExtent->FileOffset.HighPart,
3586                                                   pExtent->FileOffset.LowPart);
3587                                         osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3588                                                   pExtent->CacheOffset.HighPart,
3589                                                   pExtent->CacheOffset.LowPart);
3590                                         buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
3591                                         dirty++;
3592                                     } else {
3593 #ifdef ODS_DEBUG
3594                                         snprintf( dbgstr, 1024,
3595                                                   "RDR_ReleaseFileExtents dirty flag set but not dirty and user == kernel: old %s kernel %s new %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3596                                                   md5dbg, md5dbg2, md5dbg3,
3597                                                   Fid.volume, Fid.vnode, Fid.unique,
3598                                                   pExtent->FileOffset.HighPart,
3599                                                   pExtent->FileOffset.LowPart,
3600                                                   pExtent->CacheOffset.HighPart,
3601                                                   pExtent->CacheOffset.LowPart);
3602                                         OutputDebugStringA( dbgstr);
3603 #endif
3604                                         osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
3605                                                   Fid.volume, Fid.vnode,
3606                                                   pExtent->FileOffset.HighPart,
3607                                                   pExtent->FileOffset.LowPart);
3608                                         osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3609                                                   pExtent->CacheOffset.HighPart,
3610                                                   pExtent->CacheOffset.LowPart);
3611                                     }
3612                                 } else {
3613 #ifdef ODS_DEBUG
3614                                         snprintf( dbgstr, 1024,
3615                                                   "RDR_ReleaseFileExtents dirty flag set but not dirty: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3616                                                   Fid.volume, Fid.vnode, Fid.unique,
3617                                                   pExtent->FileOffset.HighPart,
3618                                                   pExtent->FileOffset.LowPart,
3619                                                   pExtent->CacheOffset.HighPart,
3620                                                   pExtent->CacheOffset.LowPart);
3621                                         OutputDebugStringA( dbgstr);
3622 #endif
3623                                         osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
3624                                                   Fid.volume, Fid.vnode,
3625                                                   pExtent->FileOffset.HighPart,
3626                                                   pExtent->FileOffset.LowPart);
3627                                         osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3628                                                   pExtent->CacheOffset.HighPart,
3629                                                   pExtent->CacheOffset.LowPart);
3630                                 }
3631                             } else {
3632                                 buf_ComputeCheckSum(bufp);
3633 #ifdef ODS_DEBUG
3634                                 if (pExtent->Flags & AFS_EXTENT_FLAG_MD5_SET)
3635                                 {
3636                                     HexCheckSum(md5dbg3, sizeof(md5dbg3), bufp->md5cksum);
3637                                     if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
3638                                     {
3639                                         snprintf( dbgstr, 1024,
3640                                                   "RDR_ReleaseFileExtents dirty flag set and dirty and user != kernel: old %s kernel %s new %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3641                                                   md5dbg, md5dbg2,md5dbg3,
3642                                                   Fid.volume, Fid.vnode, Fid.unique,
3643                                                   pExtent->FileOffset.HighPart,
3644                                                   pExtent->FileOffset.LowPart,
3645                                                   pExtent->CacheOffset.HighPart,
3646                                                   pExtent->CacheOffset.LowPart);
3647                                         OutputDebugStringA( dbgstr);
3648                                     } else {
3649                                         snprintf( dbgstr, 1024,
3650                                                   "RDR_ReleaseFileExtents dirty flag set and dirty and user == kernel: old %s kernel %s new %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3651                                                   md5dbg, md5dbg2,md5dbg3,
3652                                                   Fid.volume, Fid.vnode, Fid.unique,
3653                                                   pExtent->FileOffset.HighPart,
3654                                                   pExtent->FileOffset.LowPart,
3655                                                   pExtent->CacheOffset.HighPart,
3656                                                   pExtent->CacheOffset.LowPart);
3657                                         OutputDebugStringA( dbgstr);
3658                                     }
3659                                 } else {
3660                                     snprintf( dbgstr, 1024,
3661                                               "RDR_ReleaseFileExtents dirty flag set: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3662                                               Fid.volume, Fid.vnode, Fid.unique,
3663                                               pExtent->FileOffset.HighPart,
3664                                               pExtent->FileOffset.LowPart,
3665                                               pExtent->CacheOffset.HighPart,
3666                                               pExtent->CacheOffset.LowPart);
3667                                     OutputDebugStringA( dbgstr);
3668                                 }
3669 #endif
3670                                 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
3671                                 dirty++;
3672                             }
3673 #else /* !VALIDATE_CHECK_SUM */
3674                             buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
3675                             dirty++;
3676 #endif /* VALIDATE_CHECK_SUM */
3677                         }
3678 #ifdef VALIDATE_CHECK_SUM
3679                         else {
3680 #ifdef ODS_DEBUG
3681                             HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3682 #endif
3683                             if ( !buf_ValidateCheckSum(bufp) ) {
3684                                 buf_ComputeCheckSum(bufp);
3685 #ifdef ODS_DEBUG
3686                                 HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
3687                                 snprintf( dbgstr, 1024,
3688                                           "RDR_ReleaseFileExtents dirty flag not set but dirty! old %s new %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3689                                           md5dbg, md5dbg3,
3690                                           Fid.volume, Fid.vnode, Fid.unique,
3691                                           pExtent->FileOffset.HighPart,
3692                                           pExtent->FileOffset.LowPart,
3693                                           pExtent->CacheOffset.HighPart,
3694                                           pExtent->CacheOffset.LowPart);
3695                                 OutputDebugStringA( dbgstr);
3696 #endif
3697                                 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag not set but extent has changed vol 0x%x vno 0x%x foffset 0x%x:%x",
3698                                           Fid.volume, Fid.vnode,
3699                                           pExtent->FileOffset.HighPart,
3700                                           pExtent->FileOffset.LowPart);
3701                                 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3702                                           pExtent->CacheOffset.HighPart,
3703                                           pExtent->CacheOffset.LowPart);
3704                                 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
3705                                 dirty++;
3706                             } else {
3707                                 buf_ComputeCheckSum(bufp);
3708 #ifdef ODS_DEBUG
3709                                 HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
3710                                 snprintf( dbgstr, 1024,
3711                                           "RDR_ReleaseFileExtents dirty flag not set: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3712                                           Fid.volume, Fid.vnode, Fid.unique,
3713                                           pExtent->FileOffset.HighPart,
3714                                           pExtent->FileOffset.LowPart,
3715                                           pExtent->CacheOffset.HighPart,
3716                                           pExtent->CacheOffset.LowPart);
3717                                 OutputDebugStringA( dbgstr);
3718 #endif
3719                                 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag not set: vol 0x%x vno 0x%x foffset 0x%x:%x",
3720                                           Fid.volume, Fid.vnode,
3721                                           pExtent->FileOffset.HighPart,
3722                                           pExtent->FileOffset.LowPart);
3723                                 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3724                                           pExtent->CacheOffset.HighPart,
3725                                           pExtent->CacheOffset.LowPart);
3726                             }
3727                         }
3728 #endif /* VALIDATE_CHECK_SUM */
3729                         lock_ReleaseMutex(&bufp->mx);
3730                     }
3731                 }
3732             }
3733             else {
3734                 char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
3735                 cm_buf_t *wbp;
3736
3737                 for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
3738                     if (wbp->datap == datap)
3739                         break;
3740                 }
3741
3742 #ifdef ODS_DEBUG
3743                 snprintf( dbgstr, 1024,
3744                           "RDR_ReleaseFileExtents non-matching extent vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3745                           Fid.volume, Fid.vnode, Fid.unique,
3746                           pExtent->FileOffset.HighPart,
3747                           pExtent->FileOffset.LowPart,
3748                           pExtent->CacheOffset.HighPart,
3749                           pExtent->CacheOffset.LowPart);
3750                 OutputDebugStringA( dbgstr);
3751 #endif
3752                 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents non-matching extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3753                           Fid.volume, Fid.vnode,
3754                           pExtent->FileOffset.HighPart,
3755                           pExtent->FileOffset.LowPart);
3756                 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3757                           pExtent->CacheOffset.HighPart,
3758                           pExtent->CacheOffset.LowPart);
3759                 osi_Log5( afsd_logp, "... belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
3760                           wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
3761 #ifdef DEBUG
3762                 DebugBreak();
3763 #endif
3764             }
3765             buf_Release(bufp);
3766         }
3767         else {
3768             char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
3769             cm_buf_t *wbp;
3770
3771             for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
3772                 if (wbp->datap == datap)
3773                     break;
3774             }
3775
3776 #ifdef ODS_DEBUG
3777             snprintf( dbgstr, 1024,
3778                       "RDR_ReleaseFileExtents unknown extent vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3779                       Fid.volume, Fid.vnode, Fid.unique,
3780                       pExtent->FileOffset.HighPart,
3781                       pExtent->FileOffset.LowPart,
3782                       pExtent->CacheOffset.HighPart,
3783                       pExtent->CacheOffset.LowPart);
3784             OutputDebugStringA( dbgstr);
3785 #endif
3786             osi_Log4( afsd_logp, "RDR_ReleaseFileExtents unknown extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3787                       Fid.volume, Fid.vnode,
3788                       pExtent->FileOffset.HighPart,
3789                       pExtent->FileOffset.LowPart);
3790             osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3791                       pExtent->CacheOffset.HighPart,
3792                       pExtent->CacheOffset.LowPart);
3793             osi_Log5( afsd_logp, "... belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
3794                       wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
3795         }
3796     }
3797
3798     if (scp) {
3799         if (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_FLUSH) {
3800             lock_ObtainWrite(&scp->rw);
3801             code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
3802                              CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3803             lock_ReleaseWrite(&scp->rw);
3804             if (code == 0)
3805                 code = cm_FSync(scp, userp, &req, FALSE);
3806         }
3807         else if (dirty) {
3808             osi_hyper_t offset = {0,0};
3809             afs_uint32  length = 0;
3810             afs_uint32  rights = 0;
3811
3812             lock_ObtainWrite(&scp->rw);
3813             code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
3814                              CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3815             lock_ReleaseWrite(&scp->rw);
3816             if (code == 0) {
3817                 /*
3818                  * there is at least one dirty extent on this file.  queue up background store
3819                  * requests for contiguous blocks
3820                  */
3821                 for ( count = 0; count < ReleaseExtentsCB->ExtentCount; count++) {
3822                     if (ReleaseExtentsCB->FileExtents[count].FileOffset.QuadPart == offset.QuadPart + length &&
3823                          length + cm_data.buf_blockSize <= cm_chunkSize)
3824                     {
3825                         length += cm_data.buf_blockSize;
3826                     } else {
3827                         if (!(offset.QuadPart == 0 && length == 0))
3828                             cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
3829                                                 length, 0, userp, &req);
3830                         offset.QuadPart = ReleaseExtentsCB->FileExtents[count].FileOffset.QuadPart;
3831                         length = cm_data.buf_blockSize;
3832                     }
3833                 }
3834                 cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
3835                                    length, 0, userp, &req);
3836             }
3837         }
3838         cm_ReleaseSCache(scp);
3839     }
3840
3841     osi_Log5(afsd_logp, "RDR_ReleaseFileExtents File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x Released %d",
3842               FileId.Cell, FileId.Volume,
3843               FileId.Vnode, FileId.Unique, released);
3844     if (code && code != CM_ERROR_WOULDBLOCK) {
3845         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3846         (*ResultCB)->ResultStatus = status;
3847         osi_Log2(afsd_logp, "RDR_ReleaseFileExtents FAILURE code=0x%x status=0x%x",
3848                   code, status);
3849     } else {
3850         (*ResultCB)->ResultStatus = 0;
3851         osi_Log0(afsd_logp, "RDR_ReleaseFileExtents SUCCESS");
3852     }
3853     (*ResultCB)->ResultBufferLength = 0;
3854
3855     return;
3856 }
3857
3858 DWORD
3859 RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFileExtentsResultCB,
3860                                      IN DWORD ResultBufferLength)
3861 {
3862     afs_uint32  code = 0;
3863     cm_req_t    req;
3864     osi_hyper_t thyper;
3865     cm_buf_t    *bufp;
3866     unsigned int fileno, extentno, total_extents = 0;
3867     AFSReleaseFileExtentsResultFileCB *pNextFileCB;
3868 #ifdef ODS_DEBUG
3869 #ifdef VALIDATE_CHECK_SUM
3870     char md5dbg[33], md5dbg2[33], md5dbg3[33];
3871 #endif
3872     char dbgstr[1024];
3873 #endif
3874     RDR_InitReq(&req);
3875
3876     for ( fileno = 0, pNextFileCB = &ReleaseFileExtentsResultCB->Files[0];
3877           fileno < ReleaseFileExtentsResultCB->FileCount;
3878           fileno++ ) {
3879         AFSReleaseFileExtentsResultFileCB *pFileCB = pNextFileCB;
3880         cm_user_t       *userp = NULL;
3881         cm_fid_t         Fid;
3882         cm_scache_t *    scp = NULL;
3883         int              dirty = 0;
3884         int              released = 0;
3885         char * p;
3886
3887         userp = RDR_UserFromAuthGroup( &pFileCB->AuthGroup);
3888
3889         osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult %d.%d.%d.%d",
3890                   pFileCB->FileId.Cell, pFileCB->FileId.Volume,
3891                   pFileCB->FileId.Vnode, pFileCB->FileId.Unique);
3892
3893         /* Process the release */
3894         Fid.cell = pFileCB->FileId.Cell;
3895         Fid.volume = pFileCB->FileId.Volume;
3896         Fid.vnode = pFileCB->FileId.Vnode;
3897         Fid.unique = pFileCB->FileId.Unique;
3898         Fid.hash = pFileCB->FileId.Hash;
3899
3900         if (Fid.cell == 0) {
3901             osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult Invalid FID %d.%d.%d.%d",
3902                      Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
3903             code = CM_ERROR_INVAL;
3904             goto cleanup_file;
3905         }
3906
3907         code = cm_GetSCache(&Fid, &scp, userp, &req);
3908         if (code) {
3909             osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult cm_GetSCache FID failure code=0x%x",
3910                      code);
3911             /*
3912              * A failure to find the cm_scache object cannot prevent the service
3913              * from accepting the extents back from the redirector.
3914              */
3915         }
3916
3917         /* if the scp was not found, do not perform the length check */
3918         if (scp && (pFileCB->AllocationSize.QuadPart != scp->length.QuadPart)) {
3919             cm_attr_t setAttr;
3920
3921             memset(&setAttr, 0, sizeof(cm_attr_t));
3922             lock_ObtainWrite(&scp->rw);
3923             if (pFileCB->AllocationSize.QuadPart != scp->length.QuadPart) {
3924                 osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult length change vol 0x%x vno 0x%x length 0x%x:%x",
3925                           scp->fid.volume, scp->fid.vnode,
3926                           pFileCB->AllocationSize.HighPart,
3927                           pFileCB->AllocationSize.LowPart);
3928                 setAttr.mask |= CM_ATTRMASK_LENGTH;
3929                 setAttr.length.LowPart = pFileCB->AllocationSize.LowPart;
3930                 setAttr.length.HighPart = pFileCB->AllocationSize.HighPart;
3931             }
3932             lock_ReleaseWrite(&scp->rw);
3933             if (setAttr.mask)
3934                 code = cm_SetAttr(scp, &setAttr, userp, &req);
3935         }
3936
3937         for ( extentno = 0; extentno < pFileCB->ExtentCount; total_extents++, extentno++ ) {
3938             AFSFileExtentCB *pExtent = &pFileCB->FileExtents[extentno];
3939
3940             thyper.QuadPart = pExtent->FileOffset.QuadPart;
3941
3942             bufp = buf_Find(&Fid, &thyper);
3943             if (bufp) {
3944                 if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
3945                     if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3946                         osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3947                                  Fid.volume, Fid.vnode,
3948                                  pExtent->FileOffset.HighPart,
3949                                  pExtent->FileOffset.LowPart);
3950                         osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; previously released",
3951                                  pExtent->CacheOffset.HighPart,
3952                                  pExtent->CacheOffset.LowPart);
3953                     } else {
3954                         osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3955                                  Fid.volume, Fid.vnode,
3956                                  pExtent->FileOffset.HighPart,
3957                                  pExtent->FileOffset.LowPart);
3958                         osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; owned by redirector",
3959                                  pExtent->CacheOffset.HighPart,
3960                                  pExtent->CacheOffset.LowPart);
3961                     }
3962                     buf_Release(bufp);
3963                     continue;
3964                 }
3965
3966                 if (pExtent->Flags & AFS_EXTENT_FLAG_IN_USE) {
3967                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3968                               Fid.volume, Fid.vnode,
3969                               pExtent->FileOffset.HighPart,
3970                               pExtent->FileOffset.LowPart);
3971                     osi_Log2(afsd_logp, "... coffset 0x%x:%x IN_USE by file system",
3972                               pExtent->CacheOffset.HighPart,
3973                               pExtent->CacheOffset.LowPart);
3974
3975                     /* Move the buffer to the front of the queue */
3976                     lock_ObtainWrite(&buf_globalLock);
3977                     buf_MoveToHeadOfRedirQueue(scp, bufp);
3978                     lock_ReleaseWrite(&buf_globalLock);
3979                     buf_Release(bufp);
3980                     continue;
3981                 }
3982
3983                 if (bufp->datap - RDR_extentBaseAddress == pExtent->CacheOffset.QuadPart) {
3984                     if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3985                         osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3986                                  Fid.volume, Fid.vnode,
3987                                  pExtent->FileOffset.HighPart,
3988                                  pExtent->FileOffset.LowPart);
3989                         osi_Log2(afsd_logp, "... coffset 0x%x:%x not held by file system",
3990                                  pExtent->CacheOffset.HighPart,
3991                                  pExtent->CacheOffset.LowPart);
3992 #ifdef ODS_DEBUG
3993                         snprintf(dbgstr, 1024,
3994                                   "RDR_ProcessReleaseFileExtentsResult not held by redirector! flags 0x%x:%x vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3995                                   ReleaseFileExtentsResultCB->Flags, pExtent->Flags,
3996                                   Fid.volume, Fid.vnode, Fid.unique,
3997                                   pExtent->FileOffset.HighPart,
3998                                   pExtent->FileOffset.LowPart,
3999                                   pExtent->CacheOffset.HighPart,
4000                                   pExtent->CacheOffset.LowPart);
4001                         OutputDebugStringA( dbgstr);
4002 #endif
4003                     } else {
4004                         osi_Log5(afsd_logp, "RDR_ProcessReleaseFileExtentsResult bufp 0x%p foffset 0x%x:%x coffset 0x%x:%x",
4005                                  bufp, pExtent->FileOffset.HighPart, pExtent->FileOffset.LowPart,
4006                                  pExtent->CacheOffset.HighPart, pExtent->CacheOffset.LowPart);
4007
4008                         if (pExtent->Flags || ReleaseFileExtentsResultCB->Flags) {
4009                             lock_ObtainMutex(&bufp->mx);
4010                             if ( (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_RELEASE) ||
4011                                  (pExtent->Flags & AFS_EXTENT_FLAG_RELEASE) )
4012                             {
4013                                 if (bufp->qFlags & CM_BUF_QREDIR) {
4014                                     lock_ObtainWrite(&buf_globalLock);
4015                                     if (bufp->qFlags & CM_BUF_QREDIR) {
4016                                         buf_RemoveFromRedirQueue(scp, bufp);
4017                                         buf_ReleaseLocked(bufp, TRUE);
4018                                     }
4019                                     lock_ReleaseWrite(&buf_globalLock);
4020                                 }
4021
4022 #ifdef ODS_DEBUG
4023                                 snprintf(dbgstr, 1024,
4024                                           "RDR_ProcessReleaseFileExtentsResult extent released: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4025                                           Fid.volume, Fid.vnode, Fid.unique,
4026                                           pExtent->FileOffset.HighPart,
4027                                           pExtent->FileOffset.LowPart,
4028                                           pExtent->CacheOffset.HighPart,
4029                                           pExtent->CacheOffset.LowPart);
4030                                 OutputDebugStringA( dbgstr);
4031 #endif
4032
4033                                 released++;
4034                             } else {
4035                                 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult not releasing vol 0x%x vno 0x%x foffset 0x%x:%x",
4036                                          Fid.volume, Fid.vnode,
4037                                          pExtent->FileOffset.HighPart,
4038                                          pExtent->FileOffset.LowPart);
4039                                 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4040                                          pExtent->CacheOffset.HighPart,
4041                                          pExtent->CacheOffset.LowPart);
4042 #ifdef ODS_DEBUG
4043                                 snprintf(dbgstr, 1024,
4044                                           "RDR_ProcessReleaseFileExtentsResult not released! vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4045                                           Fid.volume, Fid.vnode, Fid.unique,
4046                                           pExtent->FileOffset.HighPart,
4047                                           pExtent->FileOffset.LowPart,
4048                                           pExtent->CacheOffset.HighPart,
4049                                           pExtent->CacheOffset.LowPart);
4050                                 OutputDebugStringA( dbgstr);
4051 #endif
4052                             }
4053
4054                             if ( (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
4055                                  (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY) )
4056                             {
4057 #ifdef VALIDATE_CHECK_SUM
4058                                 if ( buf_ValidateCheckSum(bufp) ) {
4059 #ifdef ODS_DEBUG
4060                                     HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
4061                                     if (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_MD5_SET)
4062                                         HexCheckSum(md5dbg2, sizeof(md5dbg2), pExtent->MD5);
4063 #endif
4064                                     buf_ComputeCheckSum(bufp);
4065 #ifdef ODS_DEBUG
4066                                     HexCheckSum(md5dbg3, sizeof(md5dbg), bufp->md5cksum);
4067 #endif
4068                                     if (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_MD5_SET)
4069                                     {
4070                                         if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
4071                                         {
4072 #ifdef ODS_DEBUG
4073                                             snprintf(dbgstr, 1024,
4074                                                       "RDR_ProcessReleaseFileExtentsResult dirty flag set and checksums do not match! user %s kernel %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4075                                                       md5dbg3, md5dbg2,
4076                                                       Fid.volume, Fid.vnode, Fid.unique,
4077                                                       pExtent->FileOffset.HighPart,
4078                                                       pExtent->FileOffset.LowPart,
4079                                                       pExtent->CacheOffset.HighPart,
4080                                                       pExtent->CacheOffset.LowPart);
4081                                             OutputDebugStringA( dbgstr);
4082 #endif
4083                                             osi_Log4(afsd_logp,
4084                                                       "RDR_ProcessReleaseFileExtentsResult dirty flag set and checksums do not match! vol 0x%x vno 0x%x foffset 0x%x:%x",
4085                                                       Fid.volume, Fid.vnode,
4086                                                       pExtent->FileOffset.HighPart,
4087                                                       pExtent->FileOffset.LowPart);
4088                                             osi_Log2(afsd_logp,
4089                                                       "... coffset 0x%x:%x",
4090                                                       pExtent->CacheOffset.HighPart,
4091                                                       pExtent->CacheOffset.LowPart);
4092
4093                                             buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4094                                             dirty++;
4095                                         } else {
4096 #ifdef ODS_DEBUG
4097                                             snprintf(dbgstr, 1024,
4098                                                       "RDR_ProcessReleaseFileExtentsResult dirty flag set but extent has not changed! old %s kernel %s new %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4099                                                       md5dbg, md5dbg2, md5dbg3,
4100                                                       Fid.volume, Fid.vnode, Fid.unique,
4101                                                       pExtent->FileOffset.HighPart,
4102                                                       pExtent->FileOffset.LowPart,
4103                                                       pExtent->CacheOffset.HighPart,
4104                                                       pExtent->CacheOffset.LowPart);
4105                                             OutputDebugStringA( dbgstr);
4106 #endif
4107                                             osi_Log4(afsd_logp,
4108                                                       "RDR_ProcessReleaseFileExtentsResult dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
4109                                                       Fid.volume, Fid.vnode,
4110                                                       pExtent->FileOffset.HighPart,
4111                                                       pExtent->FileOffset.LowPart);
4112                                             osi_Log2(afsd_logp,
4113                                                       "... coffset 0x%x:%x",
4114                                                       pExtent->CacheOffset.HighPart,
4115                                                       pExtent->CacheOffset.LowPart);
4116                                         }
4117                                     }
4118                                 }
4119 #else /* !VALIDATE_CHECK_SUM */
4120                                 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4121                                 dirty++;
4122 #ifdef ODS_DEBUG
4123                                 snprintf(dbgstr, 1024,
4124                                           "RDR_ProcessReleaseFileExtentsResult dirty! vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4125                                           Fid.volume, Fid.vnode, Fid.unique,
4126                                           pExtent->FileOffset.HighPart,
4127                                           pExtent->FileOffset.LowPart,
4128                                           pExtent->CacheOffset.HighPart,
4129                                           pExtent->CacheOffset.LowPart);
4130                                 OutputDebugStringA( dbgstr);
4131 #endif
4132 #endif /* VALIDATE_CHECK_SUM */
4133                             }
4134 #ifdef VALIDATE_CHECK_SUM
4135                             else {
4136 #ifdef ODS_DEBUG
4137                                 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
4138 #endif
4139                                 if ( !buf_ValidateCheckSum(bufp) ) {
4140                                     buf_ComputeCheckSum(bufp);
4141 #ifdef ODS_DEBUG
4142                                     HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
4143                                     snprintf(dbgstr, 1024,
4144                                              "RDR_ProcessReleaseFileExtentsResult dirty flag not set but dirty! old %s new %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4145                                              md5dbg, md5dbg3,
4146                                              Fid.volume, Fid.vnode, Fid.unique,
4147                                              pExtent->FileOffset.HighPart,
4148                                              pExtent->FileOffset.LowPart,
4149                                              pExtent->CacheOffset.HighPart,
4150                                              pExtent->CacheOffset.LowPart);
4151                                     OutputDebugStringA( dbgstr);
4152 #endif
4153                                     osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult dirty flag NOT set but extent has changed! vol 0x%x vno 0x%x foffset 0x%x:%x",
4154                                              Fid.volume, Fid.vnode,
4155                                              pExtent->FileOffset.HighPart,
4156                                              pExtent->FileOffset.LowPart);
4157                                     osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4158                                              pExtent->CacheOffset.HighPart,
4159                                              pExtent->CacheOffset.LowPart);
4160 #ifdef DEBUG
4161                                     DebugBreak();
4162 #endif
4163                                     buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4164                                     dirty++;
4165                                 } else {
4166                                     buf_ComputeCheckSum(bufp);
4167 #ifdef ODS_DEBUG
4168                                     HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
4169                                     snprintf(dbgstr, 1024,
4170                                              "RDR_ProcessReleaseFileExtentsResult dirty flag not set and not dirty! old %s new %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4171                                              md5dbg, md5dbg3,
4172                                              Fid.volume, Fid.vnode, Fid.unique,
4173                                              pExtent->FileOffset.HighPart,
4174                                              pExtent->FileOffset.LowPart,
4175                                              pExtent->CacheOffset.HighPart,
4176                                              pExtent->CacheOffset.LowPart);
4177                                     OutputDebugStringA( dbgstr);
4178 #endif
4179                                 }
4180                             }
4181 #endif /* VALIDATE_CHECK_SUM */
4182                             lock_ReleaseMutex(&bufp->mx);
4183                         }
4184                     }
4185                 } else {
4186                     /* CacheOffset doesn't match bufp->datap */
4187                     char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
4188                     cm_buf_t *wbp;
4189
4190                     for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
4191                         if (wbp->datap == datap)
4192                             break;
4193                     }
4194
4195 #ifdef ODS_DEBUG
4196                     snprintf(dbgstr, 1024,
4197                              "RDR_ProcessReleaseFileExtentsResult non-matching extent vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x flags 0x%x\n",
4198                              Fid.volume, Fid.vnode, Fid.unique,
4199                              pExtent->FileOffset.HighPart,
4200                              pExtent->FileOffset.LowPart,
4201                              pExtent->CacheOffset.HighPart,
4202                              pExtent->CacheOffset.LowPart,
4203                              pExtent->Flags);
4204                     OutputDebugStringA( dbgstr);
4205 #endif
4206                     osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult non-matching extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4207                              Fid.volume, Fid.vnode,
4208                              pExtent->FileOffset.HighPart,
4209                              pExtent->FileOffset.LowPart);
4210                     osi_Log3(afsd_logp, "... coffset 0x%x:%x flags 0x%x",
4211                              pExtent->CacheOffset.HighPart,
4212                              pExtent->CacheOffset.LowPart,
4213                              pExtent->Flags);
4214                     if (wbp)
4215                         osi_Log5(afsd_logp, "... coffset belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
4216                                  wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
4217                     else
4218                         osi_Log0(afsd_logp, "... coffset cannot be found");
4219 #ifdef DEBUG
4220                     DebugBreak();
4221 #endif
4222                 }
4223                 buf_Release(bufp);
4224             } else {
4225                 if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
4226                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4227                              Fid.volume, Fid.vnode, pExtent->FileOffset.HighPart,
4228                              pExtent->FileOffset.LowPart);
4229                     osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; cm_buf not found -- recycled?",
4230                              pExtent->CacheOffset.HighPart,
4231                              pExtent->CacheOffset.LowPart);
4232
4233                     continue;
4234                 }
4235
4236 #ifdef ODS_DEBUG
4237                 snprintf(dbgstr, 1024,
4238                          "RDR_ProcessReleaseFileExtentsResult buf not found vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4239                          Fid.volume, Fid.vnode, Fid.unique,
4240                          pExtent->FileOffset.HighPart,
4241                          pExtent->FileOffset.LowPart,
4242                          pExtent->CacheOffset.HighPart,
4243                          pExtent->CacheOffset.LowPart);
4244                 OutputDebugStringA( dbgstr);
4245 #endif
4246                 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult buf not found vol 0x%x vno 0x%x foffset 0x%x:%x",
4247                          Fid.volume, Fid.vnode,
4248                          pExtent->FileOffset.HighPart,
4249                          pExtent->FileOffset.LowPart);
4250                 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4251                          pExtent->CacheOffset.HighPart,
4252                          pExtent->CacheOffset.LowPart);
4253             }
4254         }
4255
4256         if (scp && dirty) {
4257             osi_hyper_t offset = {0,0};
4258             afs_uint32  length = 0;
4259
4260             /*
4261              * there is at least one dirty extent on this file.  queue up background store
4262              * requests for contiguous blocks
4263              */
4264             for ( extentno = 0; extentno < pFileCB->ExtentCount; extentno++ ) {
4265                 AFSFileExtentCB *pExtent = &pFileCB->FileExtents[extentno];
4266                 if (pExtent->FileOffset.QuadPart == offset.QuadPart + length &&
4267                      length < cm_chunkSize) {
4268                     length += cm_data.buf_blockSize;
4269                 } else {
4270                     if (!(offset.QuadPart == 0 && length == 0))
4271                         cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
4272                                             length, 0, userp, &req);
4273                     offset.QuadPart = pExtent->FileOffset.QuadPart;
4274                     length = cm_data.buf_blockSize;
4275                 }
4276             }
4277             cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
4278                                 length, 0, userp, &req);
4279         }
4280
4281         osi_Log5(afsd_logp, "RDR_ProcessReleaseFileExtentsResult File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x Released %d",
4282                   Fid.cell, Fid.volume, Fid.vnode, Fid.unique, released);
4283
4284       cleanup_file:
4285         if (userp)
4286             cm_ReleaseUser(userp);
4287         if (scp)
4288             cm_ReleaseSCache(scp);
4289
4290         p = (char *)pFileCB;
4291         p += sizeof(AFSReleaseFileExtentsResultFileCB);
4292         p += sizeof(AFSFileExtentCB) * (pFileCB->ExtentCount - 1);
4293         pNextFileCB = (AFSReleaseFileExtentsResultFileCB *)p;
4294     }
4295
4296     if (total_extents == 0) {
4297         osi_Log0(afsd_logp, "RDR_ProcessReleaseFileExtentsResult is empty");
4298         code = CM_ERROR_RETRY;
4299     }
4300
4301     if (code)
4302         osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult FAILURE code=0x%x", code);
4303     else
4304         osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult DONE code=0x%x", code);
4305
4306     return code;
4307 }
4308
4309 DWORD
4310 RDR_ReleaseFailedSetFileExtents( IN cm_user_t *userp,
4311                                  IN AFSSetFileExtentsCB *SetFileExtentsResultCB,
4312                                  IN DWORD ResultBufferLength)
4313 {
4314     afs_uint32  code = 0;
4315     cm_req_t    req;
4316     unsigned int extentno;
4317     cm_fid_t         Fid;
4318     cm_scache_t *    scp = NULL;
4319     int              dirty = 0;
4320
4321     RDR_InitReq(&req);
4322
4323     osi_Log4(afsd_logp, "RDR_ReleaseFailedSetFileExtents %d.%d.%d.%d",
4324               SetFileExtentsResultCB->FileId.Cell, SetFileExtentsResultCB->FileId.Volume,
4325               SetFileExtentsResultCB->FileId.Vnode, SetFileExtentsResultCB->FileId.Unique);
4326
4327     /* Process the release */
4328     Fid.cell = SetFileExtentsResultCB->FileId.Cell;
4329     Fid.volume = SetFileExtentsResultCB->FileId.Volume;
4330     Fid.vnode = SetFileExtentsResultCB->FileId.Vnode;
4331     Fid.unique = SetFileExtentsResultCB->FileId.Unique;
4332     Fid.hash = SetFileExtentsResultCB->FileId.Hash;
4333
4334     if (Fid.cell == 0) {
4335         osi_Log4(afsd_logp, "RDR_ReleaseFailedSetFile Invalid FID %d.%d.%d.%d",
4336                   Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
4337         code = CM_ERROR_INVAL;
4338         goto cleanup_file;
4339     }
4340
4341     code = cm_GetSCache(&Fid, &scp, userp, &req);
4342     if (code) {
4343         osi_Log1(afsd_logp, "RDR_ReleaseFailedSetFileExtents cm_GetSCache FID failure code=0x%x",
4344                   code);
4345         /* Failure to find the cm_scache object cannot block return of the extents */
4346     }
4347
4348     for ( extentno = 0; extentno < SetFileExtentsResultCB->ExtentCount; extentno++ ) {
4349         osi_hyper_t thyper;
4350         cm_buf_t    *bufp;
4351         AFSFileExtentCB *pExtent = &SetFileExtentsResultCB->FileExtents[extentno];
4352
4353         thyper.QuadPart = pExtent->FileOffset.QuadPart;
4354
4355         bufp = buf_Find(&Fid, &thyper);
4356         if (bufp) {
4357             osi_Log5(afsd_logp, "RDR_ReleaseFailedSetFileExtents bufp 0x%p foffset 0x%x:%x coffset 0x%x:%x",
4358                       bufp, pExtent->FileOffset.HighPart, pExtent->FileOffset.LowPart,
4359                       pExtent->CacheOffset.HighPart, pExtent->CacheOffset.LowPart);
4360
4361             lock_ObtainMutex(&bufp->mx);
4362             if (bufp->qFlags & CM_BUF_QREDIR) {
4363                 lock_ObtainWrite(&buf_globalLock);
4364                 if (bufp->qFlags & CM_BUF_QREDIR) {
4365                     buf_RemoveFromRedirQueue(scp, bufp);
4366                     buf_ReleaseLocked(bufp, TRUE);
4367                 }
4368                 lock_ReleaseWrite(&buf_globalLock);
4369             }
4370             lock_ReleaseMutex(&bufp->mx);
4371             buf_Release(bufp);
4372         }
4373     }
4374
4375   cleanup_file:
4376     if (userp)
4377         cm_ReleaseUser(userp);
4378     if (scp)
4379         cm_ReleaseSCache(scp);
4380
4381     osi_Log1(afsd_logp, "RDR_ReleaseFailedSetFileExtents DONE code=0x%x", code);
4382     return code;
4383 }
4384
4385 void
4386 RDR_PioctlOpen( IN cm_user_t *userp,
4387                 IN AFSFileID  ParentId,
4388                 IN AFSPIOCtlOpenCloseRequestCB *pPioctlCB,
4389                 IN BOOL bWow64,
4390                 IN DWORD ResultBufferLength,
4391                 IN OUT AFSCommResult **ResultCB)
4392 {
4393     cm_fid_t    ParentFid;
4394     cm_fid_t    RootFid;
4395
4396     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
4397     if (!(*ResultCB))
4398         return;
4399
4400     memset( *ResultCB,
4401             '\0',
4402             sizeof( AFSCommResult));
4403
4404     /* Get the active directory */
4405     ParentFid.cell = ParentId.Cell;
4406     ParentFid.volume = ParentId.Volume;
4407     ParentFid.vnode = ParentId.Vnode;
4408     ParentFid.unique = ParentId.Unique;
4409     ParentFid.hash = ParentId.Hash;
4410
4411     /* Get the root directory */
4412     RootFid.cell = pPioctlCB->RootId.Cell;
4413     RootFid.volume = pPioctlCB->RootId.Volume;
4414     RootFid.vnode = pPioctlCB->RootId.Vnode;
4415     RootFid.unique = pPioctlCB->RootId.Unique;
4416     RootFid.hash = pPioctlCB->RootId.Hash;
4417
4418     /* Create the pioctl index */
4419     RDR_SetupIoctl(pPioctlCB->RequestId, &ParentFid, &RootFid, userp);
4420
4421     return;
4422 }
4423
4424
4425 void
4426 RDR_PioctlClose( IN cm_user_t *userp,
4427                  IN AFSFileID  ParentId,
4428                  IN AFSPIOCtlOpenCloseRequestCB *pPioctlCB,
4429                  IN BOOL bWow64,
4430                  IN DWORD ResultBufferLength,
4431                  IN OUT AFSCommResult **ResultCB)
4432 {
4433     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
4434     if (!(*ResultCB))
4435         return;
4436
4437     memset( *ResultCB,
4438             '\0',
4439             sizeof( AFSCommResult));
4440
4441     /* Cleanup the pioctl index */
4442     RDR_CleanupIoctl(pPioctlCB->RequestId);
4443
4444     return;
4445 }
4446
4447
4448 void
4449 RDR_PioctlWrite( IN cm_user_t *userp,
4450                  IN AFSFileID  ParentId,
4451                  IN AFSPIOCtlIORequestCB *pPioctlCB,
4452                  IN BOOL bWow64,
4453                  IN DWORD ResultBufferLength,
4454                  IN OUT AFSCommResult **ResultCB)
4455 {
4456     AFSPIOCtlIOResultCB *pResultCB;
4457     cm_scache_t *dscp = NULL;
4458     afs_uint32  code;
4459     cm_req_t    req;
4460     DWORD       status;
4461
4462     RDR_InitReq(&req);
4463     if ( bWow64 )
4464         req.flags |= CM_REQ_WOW64;
4465
4466     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4467     if (!(*ResultCB))
4468         return;
4469
4470     memset( *ResultCB,
4471             '\0',
4472             sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4473
4474     pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
4475
4476     code = RDR_IoctlWrite(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer, &req);
4477     if (code) {
4478         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4479         (*ResultCB)->ResultStatus = status;
4480         return;
4481     }
4482
4483     pResultCB->BytesProcessed = pPioctlCB->BufferLength;
4484     (*ResultCB)->ResultBufferLength = sizeof( AFSPIOCtlIOResultCB);
4485 }
4486
4487 void
4488 RDR_PioctlRead( IN cm_user_t *userp,
4489                 IN AFSFileID  ParentId,
4490                 IN AFSPIOCtlIORequestCB *pPioctlCB,
4491                 IN BOOL bWow64,
4492                 IN BOOL bIsLocalSystem,
4493                 IN DWORD ResultBufferLength,
4494                 IN OUT AFSCommResult **ResultCB)
4495 {
4496     AFSPIOCtlIOResultCB *pResultCB;
4497     cm_scache_t *dscp = NULL;
4498     afs_uint32  code;
4499     cm_req_t    req;
4500     DWORD       status;
4501     afs_uint32  pflags = (bIsLocalSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
4502
4503     RDR_InitReq(&req);
4504     if ( bWow64 )
4505         req.flags |= CM_REQ_WOW64;
4506
4507     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4508     if (!(*ResultCB))
4509         return;
4510
4511     memset( *ResultCB,
4512             '\0',
4513             sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4514
4515     pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
4516
4517     code = RDR_IoctlRead(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer,
4518                          &pResultCB->BytesProcessed, &req, pflags);
4519     if (code) {
4520         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4521         (*ResultCB)->ResultStatus = status;
4522         return;
4523     }
4524
4525     (*ResultCB)->ResultBufferLength = sizeof( AFSPIOCtlIOResultCB);
4526 }
4527
4528 void
4529 RDR_ByteRangeLockSync( IN cm_user_t     *userp,
4530                        IN AFSFileID     FileId,
4531                        IN AFSByteRangeLockRequestCB *pBRLRequestCB,
4532                        IN BOOL bWow64,
4533                        IN DWORD ResultBufferLength,
4534                        IN OUT AFSCommResult **ResultCB)
4535 {
4536     AFSByteRangeLockResultCB *pResultCB = NULL;
4537     LARGE_INTEGER ProcessId;
4538     DWORD       Length;
4539     cm_scache_t *scp = NULL;
4540     cm_fid_t    Fid;
4541     afs_uint32  code;
4542     cm_req_t    req;
4543     cm_key_t    key;
4544     DWORD       i;
4545     DWORD       status;
4546
4547     ProcessId.QuadPart = pBRLRequestCB->ProcessId;
4548
4549     RDR_InitReq(&req);
4550     if ( bWow64 )
4551         req.flags |= CM_REQ_WOW64;
4552
4553     osi_Log4(afsd_logp, "RDR_ByteRangeLockSync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4554               FileId.Cell, FileId.Volume,
4555               FileId.Vnode, FileId.Unique);
4556     osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
4557              ProcessId.HighPart, ProcessId.LowPart);
4558
4559     Length = sizeof( AFSByteRangeLockResultCB) + ((pBRLRequestCB->Count - 1) * sizeof(AFSByteRangeLockResult));
4560     if (Length > ResultBufferLength) {
4561         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult));
4562         if (!(*ResultCB))
4563             return;
4564         memset( *ResultCB, 0, sizeof(AFSCommResult));
4565         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
4566         return;
4567     }
4568
4569     *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
4570     if (!(*ResultCB))
4571         return;
4572     memset( *ResultCB, '\0', Length + sizeof( AFSCommResult) );
4573     (*ResultCB)->ResultBufferLength = Length;
4574
4575     pResultCB = (AFSByteRangeLockResultCB *)(*ResultCB)->ResultData;
4576     pResultCB->FileId = FileId;
4577     pResultCB->Count = pBRLRequestCB->Count;
4578
4579     /* Allocate the extents from the buffer package */
4580     Fid.cell = FileId.Cell;
4581     Fid.volume = FileId.Volume;
4582     Fid.vnode = FileId.Vnode;
4583     Fid.unique = FileId.Unique;
4584     Fid.hash = FileId.Hash;
4585
4586     code = cm_GetSCache(&Fid, &scp, userp, &req);
4587     if (code) {
4588         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4589         (*ResultCB)->ResultStatus = status;
4590         (*ResultCB)->ResultBufferLength = 0;
4591         osi_Log2(afsd_logp, "RDR_ByteRangeLockSync cm_GetSCache FID failure code=0x%x status=0x%x",
4592                   code, status);
4593         return;
4594     }
4595
4596     lock_ObtainWrite(&scp->rw);
4597
4598     /* start by looking up the file's end */
4599     code = cm_SyncOp(scp, NULL, userp, &req, 0,
4600                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4601     if (code) {
4602         lock_ReleaseWrite(&scp->rw);
4603         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4604         (*ResultCB)->ResultStatus = status;
4605         (*ResultCB)->ResultBufferLength = 0;
4606         osi_Log3(afsd_logp, "RDR_ByteRangeLockSync cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
4607                  scp, code, status);
4608         return;
4609     }
4610
4611     /* the scp is now locked and current */
4612     key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
4613
4614     for ( i=0; i<pBRLRequestCB->Count; i++ ) {
4615         pResultCB->Result[i].LockType = pBRLRequestCB->Request[i].LockType;
4616         pResultCB->Result[i].Offset = pBRLRequestCB->Request[i].Offset;
4617         pResultCB->Result[i].Length = pBRLRequestCB->Request[i].Length;
4618
4619         code = cm_Lock(scp,
4620                        pBRLRequestCB->Request[i].LockType == AFS_BYTE_RANGE_LOCK_TYPE_SHARED,
4621                        pBRLRequestCB->Request[i].Offset,
4622                        pBRLRequestCB->Request[i].Length,
4623                        key, 0, userp, &req, NULL);
4624
4625         if (code) {
4626             osi_Log4(afsd_logp, "RDR_ByteRangeLockSync FAILURE code 0x%x type 0x%u offset 0x%x:%x",
4627                      code,
4628                      pBRLRequestCB->Request[i].LockType,
4629                      pBRLRequestCB->Request[i].Offset.HighPart,
4630                      pBRLRequestCB->Request[i].Offset.LowPart);
4631             osi_Log2(afsd_logp, "... length 0x%x:%x",
4632                      pBRLRequestCB->Request[i].Length.HighPart,
4633                      pBRLRequestCB->Request[i].Length.LowPart);
4634         }
4635
4636         switch (code) {
4637         case 0:
4638             pResultCB->Result[i].Status = 0;
4639             break;
4640         case CM_ERROR_WOULDBLOCK:
4641             pResultCB->Result[i].Status = STATUS_FILE_LOCK_CONFLICT;
4642             break;
4643         default:
4644             pResultCB->Result[i].Status = STATUS_LOCK_NOT_GRANTED;
4645         }
4646     }
4647
4648     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4649     lock_ReleaseWrite(&scp->rw);
4650     cm_ReleaseSCache(scp);
4651
4652     (*ResultCB)->ResultStatus = 0;
4653     osi_Log0(afsd_logp, "RDR_ByteRangeLockSync SUCCESS");
4654     return;
4655 }
4656
4657 void
4658 RDR_ByteRangeUnlock( IN cm_user_t     *userp,
4659                      IN AFSFileID     FileId,
4660                      IN AFSByteRangeUnlockRequestCB *pBRURequestCB,
4661                      IN BOOL bWow64,
4662                      IN DWORD ResultBufferLength,
4663                      IN OUT AFSCommResult **ResultCB)
4664 {
4665     AFSByteRangeUnlockResultCB *pResultCB = NULL;
4666     LARGE_INTEGER ProcessId;
4667     DWORD       Length;
4668     cm_scache_t *scp = NULL;
4669     cm_fid_t    Fid;
4670     afs_uint32  code;
4671     cm_req_t    req;
4672     cm_key_t    key;
4673     DWORD       i;
4674     DWORD       status;
4675
4676     ProcessId.QuadPart = pBRURequestCB->ProcessId;
4677
4678     RDR_InitReq(&req);
4679     if ( bWow64 )
4680         req.flags |= CM_REQ_WOW64;
4681
4682     osi_Log4(afsd_logp, "RDR_ByteRangeUnlock File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4683               FileId.Cell, FileId.Volume,
4684               FileId.Vnode, FileId.Unique);
4685     osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
4686              ProcessId.HighPart, ProcessId.LowPart);
4687
4688     Length = sizeof( AFSByteRangeUnlockResultCB) + ((pBRURequestCB->Count - 1) * sizeof(AFSByteRangeLockResult));
4689     if (Length > ResultBufferLength) {
4690         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult));
4691         if (!(*ResultCB))
4692             return;
4693         memset( *ResultCB, 0, sizeof(AFSCommResult));
4694         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
4695         return;
4696     }
4697
4698     *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
4699     if (!(*ResultCB))
4700         return;
4701     memset( *ResultCB, '\0', Length + sizeof( AFSCommResult) );
4702     (*ResultCB)->ResultBufferLength = Length;
4703
4704     pResultCB = (AFSByteRangeUnlockResultCB *)(*ResultCB)->ResultData;
4705     pResultCB->Count = pBRURequestCB->Count;
4706
4707     /* Allocate the extents from the buffer package */
4708     Fid.cell = FileId.Cell;
4709     Fid.volume = FileId.Volume;
4710     Fid.vnode = FileId.Vnode;
4711     Fid.unique = FileId.Unique;
4712     Fid.hash = FileId.Hash;
4713
4714     code = cm_GetSCache(&Fid, &scp, userp, &req);
4715     if (code) {
4716         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4717         (*ResultCB)->ResultStatus = status;
4718         (*ResultCB)->ResultBufferLength = 0;
4719         osi_Log2(afsd_logp, "RDR_ByteRangeUnlock cm_GetSCache FID failure code=0x%x status=0x%x",
4720                   code, status);
4721         return;
4722     }
4723
4724     lock_ObtainWrite(&scp->rw);
4725
4726     /* start by looking up the file's end */
4727     code = cm_SyncOp(scp, NULL, userp, &req, 0,
4728                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4729     if (code) {
4730         lock_ReleaseWrite(&scp->rw);
4731         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4732         (*ResultCB)->ResultStatus = status;
4733         (*ResultCB)->ResultBufferLength = 0;
4734         osi_Log3(afsd_logp, "RDR_ByteRangeUnlock cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
4735                  scp, code, status);
4736         return;
4737     }
4738
4739     /* the scp is now locked and current */
4740     key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
4741
4742     for ( i=0; i<pBRURequestCB->Count; i++ ) {
4743         pResultCB->Result[i].LockType = pBRURequestCB->Request[i].LockType;
4744         pResultCB->Result[i].Offset = pBRURequestCB->Request[i].Offset;
4745         pResultCB->Result[i].Length = pBRURequestCB->Request[i].Length;
4746
4747         code = cm_Unlock(scp,
4748                          pBRURequestCB->Request[i].LockType == AFS_BYTE_RANGE_LOCK_TYPE_SHARED,
4749                          pBRURequestCB->Request[i].Offset,
4750                          pBRURequestCB->Request[i].Length,
4751                          key, CM_UNLOCK_FLAG_MATCH_RANGE, userp, &req);
4752
4753         if (code) {
4754             osi_Log4(afsd_logp, "RDR_ByteRangeUnlock FAILURE code 0x%x type 0x%u offset 0x%x:%x",
4755                      code, pBRURequestCB->Request[i].LockType,
4756                      pBRURequestCB->Request[i].Offset.HighPart,
4757                      pBRURequestCB->Request[i].Offset.LowPart);
4758             osi_Log2(afsd_logp, "... length 0x%x:%x",
4759                      pBRURequestCB->Request[i].Length.HighPart,
4760                      pBRURequestCB->Request[i].Length.LowPart);
4761         }
4762         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4763         pResultCB->Result[i].Status = status;
4764     }
4765
4766     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4767     lock_ReleaseWrite(&scp->rw);
4768     cm_ReleaseSCache(scp);
4769
4770     (*ResultCB)->ResultStatus = 0;
4771     osi_Log0(afsd_logp, "RDR_ByteRangeUnlock SUCCESS");
4772     return;
4773 }
4774
4775 void
4776 RDR_ByteRangeUnlockAll( IN cm_user_t     *userp,
4777                         IN AFSFileID     FileId,
4778                         IN AFSByteRangeUnlockRequestCB *pBRURequestCB,
4779                         IN BOOL bWow64,
4780                         IN DWORD ResultBufferLength,
4781                         IN OUT AFSCommResult **ResultCB)
4782 {
4783     AFSByteRangeUnlockResultCB *pResultCB = NULL;
4784     LARGE_INTEGER ProcessId;
4785     cm_scache_t *scp = NULL;
4786     cm_fid_t    Fid;
4787     afs_uint32  code;
4788     cm_req_t    req;
4789     cm_key_t    key;
4790     DWORD       status;
4791
4792     ProcessId.QuadPart = pBRURequestCB->ProcessId;
4793
4794     RDR_InitReq(&req);
4795     if ( bWow64 )
4796         req.flags |= CM_REQ_WOW64;
4797
4798     osi_Log4(afsd_logp, "RDR_ByteRangeUnlockAll File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4799               FileId.Cell, FileId.Volume,
4800               FileId.Vnode, FileId.Unique);
4801     osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
4802              ProcessId.HighPart, ProcessId.LowPart);
4803
4804     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
4805     if (!(*ResultCB))
4806         return;
4807     memset( *ResultCB, '\0', sizeof( AFSCommResult));
4808     (*ResultCB)->ResultBufferLength = 0;
4809
4810     /* Allocate the extents from the buffer package */
4811     Fid.cell = FileId.Cell;
4812     Fid.volume = FileId.Volume;
4813     Fid.vnode = FileId.Vnode;
4814     Fid.unique = FileId.Unique;
4815     Fid.hash = FileId.Hash;
4816
4817     code = cm_GetSCache(&Fid, &scp, userp, &req);
4818     if (code) {
4819         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4820         (*ResultCB)->ResultStatus = status;
4821         (*ResultCB)->ResultBufferLength = 0;
4822         osi_Log2(afsd_logp, "RDR_ByteRangeUnlockAll cm_GetSCache FID failure code=0x%x status=0x%x",
4823                   code, status);
4824         return;
4825     }
4826
4827     lock_ObtainWrite(&scp->rw);
4828
4829     /* start by looking up the file's end */
4830     code = cm_SyncOp(scp, NULL, userp, &req, 0,
4831                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4832     if (code) {
4833         lock_ReleaseWrite(&scp->rw);
4834         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4835         (*ResultCB)->ResultStatus = status;
4836         (*ResultCB)->ResultBufferLength = 0;
4837         osi_Log3(afsd_logp, "RDR_ByteRangeUnlockAll cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
4838                  scp, code, status);
4839         return;
4840     }
4841
4842     /* the scp is now locked and current */
4843     key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
4844
4845     code = cm_UnlockByKey(scp, key, 0, userp, &req);
4846
4847     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4848     lock_ReleaseWrite(&scp->rw);
4849     cm_ReleaseSCache(scp);
4850
4851     smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4852     (*ResultCB)->ResultStatus = status;
4853
4854     if (code)
4855         osi_Log1(afsd_logp, "RDR_ByteRangeUnlockAll FAILURE code 0x%x", code);
4856     else
4857         osi_Log0(afsd_logp, "RDR_ByteRangeUnlockAll SUCCESS");
4858     return;
4859
4860 }
4861
4862 void
4863 RDR_GetVolumeInfo( IN cm_user_t     *userp,
4864                    IN AFSFileID     FileId,
4865                    IN BOOL bWow64,
4866                    IN DWORD ResultBufferLength,
4867                    IN OUT AFSCommResult **ResultCB)
4868 {
4869     AFSVolumeInfoCB *pResultCB = NULL;
4870     DWORD       Length;
4871     cm_scache_t *scp = NULL;
4872     cm_volume_t *volp = NULL;
4873     cm_vol_state_t *volstatep = NULL;
4874     afs_uint32   volType;
4875     cm_cell_t   *cellp = NULL;
4876     cm_fid_t    Fid;
4877     afs_uint32  code;
4878     cm_req_t    req;
4879     DWORD       status;
4880     FILETIME ft = {0x832cf000, 0x01abfcc4}; /* October 1, 1982 00:00:00 +0600 */
4881
4882     char volName[32]="(unknown)";
4883     char offLineMsg[256]="server temporarily inaccessible";
4884     char motd[256]="server temporarily inaccessible";
4885     cm_conn_t *connp;
4886     AFSFetchVolumeStatus volStat;
4887     char *Name;
4888     char *OfflineMsg;
4889     char *MOTD;
4890     struct rx_connection * rxconnp;
4891
4892     RDR_InitReq(&req);
4893     if ( bWow64 )
4894         req.flags |= CM_REQ_WOW64;
4895
4896     osi_Log4(afsd_logp, "RDR_GetVolumeInfo File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4897              FileId.Cell, FileId.Volume,
4898              FileId.Vnode, FileId.Unique);
4899
4900     Length = sizeof( AFSCommResult) + sizeof(AFSVolumeInfoCB);
4901     if (sizeof(AFSVolumeInfoCB) > ResultBufferLength) {
4902         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
4903         if (!(*ResultCB))
4904             return;
4905         memset( *ResultCB, 0, sizeof(AFSCommResult));
4906         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
4907         return;
4908     }
4909
4910     *ResultCB = (AFSCommResult *)malloc( Length );
4911     if (!(*ResultCB))
4912         return;
4913     memset( *ResultCB, '\0', Length );
4914     (*ResultCB)->ResultBufferLength = sizeof(AFSVolumeInfoCB);
4915     pResultCB = (AFSVolumeInfoCB *)(*ResultCB)->ResultData;
4916
4917     /* Allocate the extents from the buffer package */
4918     if (FileId.Cell != 0) {
4919         Fid.cell = FileId.Cell;
4920         Fid.volume = FileId.Volume;
4921         Fid.vnode = FileId.Vnode;
4922         Fid.unique = FileId.Unique;
4923         Fid.hash = FileId.Hash;
4924
4925         code = cm_GetSCache(&Fid, &scp, userp, &req);
4926         if (code) {
4927             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4928             (*ResultCB)->ResultStatus = status;
4929             (*ResultCB)->ResultBufferLength = 0;
4930             osi_Log2(afsd_logp, "RDR_GetVolumeInfo cm_GetSCache FID failure code=0x%x status=0x%x",
4931                       code, status);
4932             return;
4933         }
4934     } else {
4935         (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
4936         osi_Log0(afsd_logp, "RDR_GetVolumeInfo Object Name Invalid - Cell = 0");
4937         return;
4938     }
4939     lock_ObtainWrite(&scp->rw);
4940
4941     /* start by looking up the file's end */
4942     code = cm_SyncOp(scp, NULL, userp, &req, 0,
4943                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
4944     if (code) {
4945         lock_ReleaseWrite(&scp->rw);
4946         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4947         (*ResultCB)->ResultStatus = status;
4948         (*ResultCB)->ResultBufferLength = 0;
4949         osi_Log3(afsd_logp, "RDR_GetVolumeInfo cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
4950                  scp, code, status);
4951         return;
4952     }
4953
4954     /* Fake for now */
4955     pResultCB->SectorsPerAllocationUnit = 1;
4956     pResultCB->BytesPerSector = 1024;
4957
4958     pResultCB->CellID = scp->fid.cell;
4959     pResultCB->VolumeID = scp->fid.volume;
4960     pResultCB->Characteristics = FILE_REMOTE_DEVICE;
4961     pResultCB->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK |
4962         FILE_SUPPORTS_REPARSE_POINTS;
4963
4964     if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
4965          scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
4966     {
4967         pResultCB->TotalAllocationUnits.QuadPart = 100;
4968         memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
4969
4970         pResultCB->AvailableAllocationUnits.QuadPart = 0;
4971         pResultCB->Characteristics |= FILE_READ_ONLY_DEVICE;
4972
4973         pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( "Freelance.Local.Root", -1, pResultCB->VolumeLabel,
4974                                                        (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
4975         if ( pResultCB->VolumeLabelLength )
4976             pResultCB->VolumeLabelLength--;
4977     } else {
4978         memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
4979
4980         volp = cm_GetVolumeByFID(&scp->fid);
4981         if (!volp) {
4982             code = CM_ERROR_NOSUCHVOLUME;
4983             goto _done;
4984         }
4985         volstatep = cm_VolumeStateByID(volp, scp->fid.volume);
4986         volType = cm_VolumeType(volp, scp->fid.volume);
4987
4988         pResultCB->Characteristics |= ((volType == ROVOL || volType == BACKVOL) ? FILE_READ_ONLY_DEVICE : 0);
4989
4990         Name = volName;
4991         OfflineMsg = offLineMsg;
4992         MOTD = motd;
4993         lock_ReleaseWrite(&scp->rw);
4994         do {
4995             code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
4996             if (code) continue;
4997
4998             rxconnp = cm_GetRxConn(connp);
4999             code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
5000                                          &volStat, &Name, &OfflineMsg, &MOTD);
5001             rx_PutConnection(rxconnp);
5002
5003         } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
5004         code = cm_MapRPCError(code, &req);
5005         if (code == 0) {
5006             pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
5007             pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
5008
5009             pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( Name, -1, pResultCB->VolumeLabel,
5010                                                            (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
5011         } else {
5012             pResultCB->TotalAllocationUnits.QuadPart = 0x7FFFFFFF;
5013             pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
5014
5015             pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( volp->namep, -1, pResultCB->VolumeLabel,
5016                                                            (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
5017             code = 0;
5018         }
5019         if ( pResultCB->VolumeLabelLength )
5020             pResultCB->VolumeLabelLength--;
5021
5022         lock_ObtainWrite(&scp->rw);
5023     }
5024     pResultCB->VolumeLabelLength *= sizeof(WCHAR);  /* convert to bytes from chars */
5025
5026     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
5027
5028   _done:
5029     lock_ReleaseWrite(&scp->rw);
5030     if (volp)
5031        cm_PutVolume(volp);
5032     cm_ReleaseSCache(scp);
5033
5034     smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5035     (*ResultCB)->ResultStatus = status;
5036     osi_Log0(afsd_logp, "RDR_GetVolumeInfo SUCCESS");
5037     return;
5038 }
5039
5040 void
5041 RDR_HoldFid( IN cm_user_t     *userp,
5042              IN AFSHoldFidRequestCB * pHoldFidCB,
5043              IN BOOL bFast,
5044              IN DWORD ResultBufferLength,
5045              IN OUT AFSCommResult **ResultCB)
5046 {
5047     AFSHoldFidResultCB *pResultCB = NULL;
5048     DWORD       index;
5049     DWORD       Length;
5050     cm_req_t    req;
5051
5052     RDR_InitReq(&req);
5053
5054     osi_Log1(afsd_logp, "RDR_HoldFid Count=%u", pHoldFidCB->Count);
5055
5056     Length = sizeof(AFSHoldFidResultCB) + (pHoldFidCB->Count-1) * sizeof(AFSFidResult);
5057     if (Length > ResultBufferLength) {
5058         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
5059         if (!(*ResultCB))
5060             return;
5061         memset( *ResultCB, 0, sizeof(AFSCommResult));
5062         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5063         return;
5064     }
5065     *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
5066     if (!(*ResultCB))
5067         return;
5068     memset( *ResultCB, '\0', Length );
5069     (*ResultCB)->ResultBufferLength = Length;
5070     pResultCB = (AFSHoldFidResultCB *)(*ResultCB)->ResultData;
5071
5072     for ( index = 0; index < pHoldFidCB->Count; index++ )
5073     {
5074         cm_scache_t *scp = NULL;
5075         cm_fid_t    Fid;
5076
5077         Fid.cell   = pResultCB->Result[index].FileID.Cell   = pHoldFidCB->FileID[index].Cell;
5078         Fid.volume = pResultCB->Result[index].FileID.Volume = pHoldFidCB->FileID[index].Volume;
5079         Fid.vnode  = pResultCB->Result[index].FileID.Vnode  = pHoldFidCB->FileID[index].Vnode;
5080         Fid.unique = pResultCB->Result[index].FileID.Unique = pHoldFidCB->FileID[index].Unique;
5081         Fid.hash   = pResultCB->Result[index].FileID.Hash   = pHoldFidCB->FileID[index].Hash;
5082
5083         osi_Log4( afsd_logp,
5084                   "RDR_HoldFid File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5085                   Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
5086
5087         scp = cm_FindSCache(&Fid);
5088         if (scp) {
5089             RDR_FlagScpInUse( scp, FALSE );
5090             cm_ReleaseSCache(scp);
5091         }
5092         pResultCB->Result[index].Status = 0;
5093     }
5094
5095     (*ResultCB)->ResultStatus = 0;
5096     osi_Log0(afsd_logp, "RDR_HoldFid SUCCESS");
5097     return;
5098 }
5099
5100 void
5101 RDR_ReleaseFid( IN cm_user_t     *userp,
5102                 IN AFSReleaseFidRequestCB * pReleaseFidCB,
5103                 IN BOOL bFast,
5104                 IN DWORD ResultBufferLength,
5105                 IN OUT AFSCommResult **ResultCB)
5106 {
5107     AFSReleaseFidResultCB *pResultCB = NULL;
5108     DWORD       index;
5109     DWORD       Length;
5110     cm_req_t    req;
5111
5112     RDR_InitReq(&req);
5113
5114     osi_Log1(afsd_logp, "RDR_ReleaseFid Count=%u", pReleaseFidCB->Count);
5115
5116     Length = sizeof(AFSReleaseFidResultCB) + (pReleaseFidCB->Count ? pReleaseFidCB->Count-1 : 0) * sizeof(AFSFidResult);
5117     if (Length > ResultBufferLength) {
5118         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
5119         if (!(*ResultCB))
5120             return;
5121         memset( *ResultCB, 0, sizeof(AFSCommResult));
5122         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5123         return;
5124     }
5125     *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
5126     if (!(*ResultCB))
5127         return;
5128     memset( *ResultCB, '\0', Length );
5129     (*ResultCB)->ResultBufferLength = Length;
5130     pResultCB = (AFSReleaseFidResultCB *)(*ResultCB)->ResultData;
5131
5132     for ( index = 0; index < pReleaseFidCB->Count; index++ )
5133     {
5134         cm_scache_t *scp = NULL;
5135         cm_fid_t    Fid;
5136
5137         Fid.cell   = pResultCB->Result[index].FileID.Cell   = pReleaseFidCB->FileID[index].Cell;
5138         Fid.volume = pResultCB->Result[index].FileID.Volume = pReleaseFidCB->FileID[index].Volume;
5139         Fid.vnode  = pResultCB->Result[index].FileID.Vnode  = pReleaseFidCB->FileID[index].Vnode;
5140         Fid.unique = pResultCB->Result[index].FileID.Unique = pReleaseFidCB->FileID[index].Unique;
5141         Fid.hash   = pResultCB->Result[index].FileID.Hash   = pReleaseFidCB->FileID[index].Hash;
5142
5143         osi_Log4( afsd_logp,
5144                   "RDR_ReleaseFid File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5145                   Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
5146
5147         scp = cm_FindSCache(&Fid);
5148         if (scp) {
5149             lock_ObtainWrite(&scp->rw);
5150             scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
5151             lock_ReleaseWrite(&scp->rw);
5152
5153             cm_ReleaseSCache(scp);
5154         }
5155         pResultCB->Result[index].Status = 0;
5156     }
5157     pResultCB->Count = pReleaseFidCB->Count;
5158
5159     (*ResultCB)->ResultStatus = 0;
5160     osi_Log0(afsd_logp, "RDR_ReleaseFid SUCCESS");
5161     return;
5162 }
5163
5164 /*
5165  * The redirector makes several assumptions regarding the
5166  * SRVSVC and WKSSVC pipes transactions.  First, the interface
5167  * versions are those indicated below.  Secondly, the encoding
5168  * will be performed using NDR version 2.  These assumptions
5169  * may not hold in the future and end-to-end MSRPC Bind
5170  * negotiations may need to be supported.  Of course, these
5171  * are the only interface versions that are supported by the
5172  * service.
5173  */
5174 #define MSRPC_PIPE_PREFIX L".\\"
5175
5176 static const UUID MSRPC_SRVSVC_UUID = {0x4B324FC8, 0x1670, 0x01D3,
5177                                        {0x12, 0x78, 0x5A, 0x47, 0xBF, 0x6E, 0xE1, 0x88}};
5178 #define MSRPC_SRVSVC_NAME L"PIPE\\SRVSVC"
5179 #define MSRPC_SRVSVC_VERS 3
5180
5181 static const UUID MSRPC_WKSSVC_UUID = {0x6BFFD098, 0xA112, 0x3610,
5182                                        {0x98, 0x33, 0x46, 0xC3, 0xF8, 0x7E, 0x34, 0x5A}};
5183 #define MSRPC_WKSSVC_NAME L"PIPE\\WKSSVC"
5184 #define MSRPC_WKSSVC_VERS 1
5185
5186 static const UUID MSRPC_NDR_UUID = {0x8A885D04, 0x1CEB, 0x11C9,
5187                                     {0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60}};
5188 #define MSRPC_NDR_NAME    L"NDR"
5189 #define MSRPC_NDR_VERS    2
5190
5191 extern RPC_IF_HANDLE srvsvc_v3_0_s_ifspec;
5192 extern RPC_IF_HANDLE wkssvc_v1_0_s_ifspec;
5193
5194 void
5195 RDR_PipeOpen( IN cm_user_t *userp,
5196               IN AFSFileID  ParentId,
5197               IN WCHAR     *Name,
5198               IN DWORD      NameLength,
5199               IN AFSPipeOpenCloseRequestCB *pPipe_CB,
5200               IN BOOL bWow64,
5201               IN DWORD ResultBufferLength,
5202               IN OUT AFSCommResult **ResultCB)
5203 {
5204     cm_fid_t    ParentFid;
5205     cm_fid_t    RootFid;
5206
5207     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5208     if (!(*ResultCB))
5209         return;
5210
5211     memset( *ResultCB,
5212             '\0',
5213             sizeof( AFSCommResult));
5214
5215     /* Get the active directory */
5216     ParentFid.cell = ParentId.Cell;
5217     ParentFid.volume = ParentId.Volume;
5218     ParentFid.vnode = ParentId.Vnode;
5219     ParentFid.unique = ParentId.Unique;
5220     ParentFid.hash = ParentId.Hash;
5221
5222     /* Get the root directory */
5223     RootFid.cell = pPipe_CB->RootId.Cell;
5224     RootFid.volume = pPipe_CB->RootId.Volume;
5225     RootFid.vnode = pPipe_CB->RootId.Vnode;
5226     RootFid.unique = pPipe_CB->RootId.Unique;
5227     RootFid.hash = pPipe_CB->RootId.Hash;
5228
5229     /* Create the pipe index */
5230     (*ResultCB)->ResultStatus =
5231       RDR_SetupPipe( pPipe_CB->RequestId, &ParentFid, &RootFid,
5232                      Name, NameLength, userp);
5233     return;
5234 }
5235
5236
5237 void
5238 RDR_PipeClose( IN cm_user_t *userp,
5239                IN AFSFileID  ParentId,
5240                IN AFSPipeOpenCloseRequestCB *pPipe_CB,
5241                IN BOOL bWow64,
5242                IN DWORD ResultBufferLength,
5243                IN OUT AFSCommResult **ResultCB)
5244 {
5245     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5246     if (!(*ResultCB))
5247         return;
5248
5249     memset( *ResultCB,
5250             '\0',
5251             sizeof( AFSCommResult));
5252
5253     /* Cleanup the pipe index */
5254     RDR_CleanupPipe(pPipe_CB->RequestId);
5255
5256     return;
5257 }
5258
5259
5260 void
5261 RDR_PipeWrite( IN cm_user_t *userp,
5262                IN AFSFileID  ParentId,
5263                IN AFSPipeIORequestCB *pPipe_CB,
5264                IN BYTE *pPipe_Data,
5265                IN BOOL bWow64,
5266                IN DWORD ResultBufferLength,
5267                IN OUT AFSCommResult **ResultCB)
5268 {
5269     AFSPipeIOResultCB *pResultCB;
5270     cm_scache_t *dscp = NULL;
5271     afs_uint32  code;
5272     cm_req_t    req;
5273     DWORD       status;
5274
5275     RDR_InitReq(&req);
5276     if ( bWow64 )
5277         req.flags |= CM_REQ_WOW64;
5278
5279     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5280     if (!(*ResultCB))
5281         return;
5282
5283     memset( *ResultCB,
5284             '\0',
5285             sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5286
5287     pResultCB = (AFSPipeIOResultCB *)(*ResultCB)->ResultData;
5288
5289     code = RDR_Pipe_Write( pPipe_CB->RequestId, pPipe_CB->BufferLength, pPipe_Data, &req, userp);
5290     if (code) {
5291         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5292         (*ResultCB)->ResultStatus = status;
5293         return;
5294     }
5295
5296     pResultCB->BytesProcessed = pPipe_CB->BufferLength;
5297     (*ResultCB)->ResultBufferLength = sizeof( AFSPipeIOResultCB);
5298 }
5299
5300
5301 void
5302 RDR_PipeRead( IN cm_user_t *userp,
5303               IN AFSFileID  ParentId,
5304               IN AFSPipeIORequestCB *pPipe_CB,
5305               IN BOOL bWow64,
5306               IN DWORD ResultBufferLength,
5307               IN OUT AFSCommResult **ResultCB)
5308 {
5309     BYTE *pPipe_Data;
5310     cm_scache_t *dscp = NULL;
5311     afs_uint32  code;
5312     cm_req_t    req;
5313     DWORD       status;
5314
5315     RDR_InitReq(&req);
5316     if ( bWow64 )
5317         req.flags |= CM_REQ_WOW64;
5318
5319     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
5320     if (!(*ResultCB))
5321         return;
5322
5323     memset( *ResultCB,
5324             '\0',
5325             sizeof( AFSCommResult));
5326
5327     pPipe_Data = (BYTE *)(*ResultCB)->ResultData;
5328
5329     code = RDR_Pipe_Read( pPipe_CB->RequestId, ResultBufferLength, pPipe_Data,
5330                           &(*ResultCB)->ResultBufferLength, &req, userp);
5331     if (code) {
5332         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5333         (*ResultCB)->ResultStatus = status;
5334         return;
5335     }
5336 }
5337
5338
5339 void
5340 RDR_PipeSetInfo( IN cm_user_t *userp,
5341                  IN AFSFileID  ParentId,
5342                  IN AFSPipeInfoRequestCB *pPipeInfo_CB,
5343                  IN BYTE *pPipe_Data,
5344                  IN BOOL bWow64,
5345                  IN DWORD ResultBufferLength,
5346                  IN OUT AFSCommResult **ResultCB)
5347 {
5348     cm_scache_t *dscp = NULL;
5349     cm_req_t    req;
5350     DWORD       status;
5351
5352     RDR_InitReq(&req);
5353     if ( bWow64 )
5354         req.flags |= CM_REQ_WOW64;
5355
5356     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5357     if (!(*ResultCB))
5358         return;
5359
5360     memset( *ResultCB,
5361             '\0',
5362             sizeof( AFSCommResult));
5363
5364     status = RDR_Pipe_SetInfo( pPipeInfo_CB->RequestId, pPipeInfo_CB->InformationClass,
5365                                pPipeInfo_CB->BufferLength, pPipe_Data, &req, userp);
5366
5367     (*ResultCB)->ResultStatus = status;
5368 }
5369
5370
5371 void
5372 RDR_PipeQueryInfo( IN cm_user_t *userp,
5373                    IN AFSFileID  ParentId,
5374                    IN AFSPipeInfoRequestCB *pPipeInfo_CB,
5375                    IN BOOL bWow64,
5376                    IN DWORD ResultBufferLength,
5377                    IN OUT AFSCommResult **ResultCB)
5378 {
5379     BYTE *pPipe_Data;
5380     cm_scache_t *dscp = NULL;
5381     cm_req_t    req;
5382     DWORD       status;
5383
5384     RDR_InitReq(&req);
5385     if ( bWow64 )
5386         req.flags |= CM_REQ_WOW64;
5387
5388     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
5389     if (!(*ResultCB))
5390         return;
5391
5392     memset( *ResultCB,
5393             '\0',
5394             sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5395
5396     pPipe_Data = (BYTE *)(*ResultCB)->ResultData;
5397
5398     status = RDR_Pipe_QueryInfo( pPipeInfo_CB->RequestId, pPipeInfo_CB->InformationClass,
5399                                  ResultBufferLength, pPipe_Data,
5400                                  &(*ResultCB)->ResultBufferLength, &req, userp);
5401
5402     (*ResultCB)->ResultStatus = status;
5403 }
5404
5405 void
5406 RDR_PipeTransceive( IN cm_user_t     *userp,
5407                     IN AFSFileID  ParentId,
5408                     IN AFSPipeIORequestCB *pPipe_CB,
5409                     IN BYTE *pPipe_InData,
5410                     IN BOOL bWow64,
5411                     IN DWORD ResultBufferLength,
5412                     IN OUT AFSCommResult **ResultCB)
5413 {
5414     /*
5415      * This function processes a Pipe Service request
5416      * that would normally be sent to a LAN Manager server
5417      * across an authenticated SMB-PIPE/MSRPC/SVC request
5418      * stack.  The request is being sent here because the
5419      * application (e.g., Explorer Shell or Common Control File
5420      * dialog) believes that because the UNC path it is
5421      * processing has specified a server name that is not
5422      * "." and that the Server is remote and that the Share
5423      * list cannot be obtained using the Network Provider
5424      * interface.
5425      *
5426      * The file system driver is faking the Bind-Ack response
5427      * to the MSRPC Bind request but cannot decode the NDR
5428      * encoded Pipe Service requests.  For that we will use
5429      * the service's MSRPC module.  However, unlike the SMB
5430      * server usage we must fake the MSRPC Bind exchange and
5431      * map the PipeName to an interface instead of using the
5432      * GUID specified in the MSRPC Bind request.
5433      *
5434      * None of the requests that are being processed by the
5435      * service require authentication.  As a result the userp
5436      * parameter will be ignored.
5437      *
5438      * Although there are dozens of Pipe Services, the only
5439      * ones that we are implementing are WKSSVC and SRVSVC.
5440      * These support NetShareEnum, NetShareGetInfo,
5441      * NetServerGetInfo, and NetWorkstaGetInfo which are
5442      * commonly queried by NET VIEW, the Explorer Shell,
5443      * and the Common Control File dialog.
5444      */
5445     BYTE *pPipe_OutData;
5446     cm_scache_t *dscp = NULL;
5447     afs_uint32  code;
5448     cm_req_t    req;
5449     DWORD       status;
5450     DWORD Length = ResultBufferLength + sizeof( AFSCommResult);
5451
5452     RDR_InitReq(&req);
5453     if ( bWow64 )
5454         req.flags |= CM_REQ_WOW64;
5455
5456     *ResultCB = (AFSCommResult *)malloc( Length);
5457     if (!(*ResultCB))
5458         return;
5459     memset( *ResultCB, '\0', Length );
5460
5461     code = RDR_Pipe_Write( pPipe_CB->RequestId, pPipe_CB->BufferLength, pPipe_InData, &req, userp);
5462     if (code) {
5463         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5464         osi_Log2( afsd_logp, "RDR_Pipe_Transceive Write FAILURE code=0x%x status=0x%x",
5465                   code, status);
5466         (*ResultCB)->ResultStatus = status;
5467         return;
5468     }
5469
5470     pPipe_OutData = (BYTE *)(*ResultCB)->ResultData;
5471     code = RDR_Pipe_Read( pPipe_CB->RequestId, ResultBufferLength, pPipe_OutData,
5472                           &(*ResultCB)->ResultBufferLength, &req, userp);
5473     if (code) {
5474         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5475         osi_Log2( afsd_logp, "RDR_Pipe_Transceive Read FAILURE code=0x%x status=0x%x",
5476                   code, status);
5477         (*ResultCB)->ResultStatus = status;
5478         return;
5479     }
5480
5481     (*ResultCB)->ResultStatus = 0;
5482     osi_Log0(afsd_logp, "RDR_Pipe_Transceive SUCCESS");
5483 }