Windows: Use AuthGroups for extent request error reporting
[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             continue;
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->flags & CM_BUF_DIRTY)
2976                 cm_BufWrite(scp, &bufp->offset, cm_chunkSize, CM_BUF_WRITE_SCP_LOCKED, userp, reqp);
2977
2978             if (!(bufp->qFlags & CM_BUF_QREDIR)) {
2979 #ifdef VALIDATE_CHECK_SUM
2980 #ifdef ODS_DEBUG
2981                 char md5dbg[33];
2982                 char dbgstr[1024];
2983 #endif
2984 #endif
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             }
3067         }
3068
3069         if (bBufRelease)
3070             buf_Release(bufp);
3071     }
3072
3073     if (!rwheld) {
3074         lock_ObtainWrite(&scp->rw);
3075         rwheld = 1;
3076     }
3077
3078     /* wakeup anyone who is waiting */
3079     if (scp->flags & CM_SCACHEFLAG_WAITING) {
3080         osi_Log1(afsd_logp, "RDR Bkg Fetch Waking scp 0x%p", scp);
3081         osi_Wakeup((LONG_PTR) &scp->flags);
3082     }
3083     lock_ReleaseWrite(&scp->rw);
3084
3085     if (count > 0) {
3086         pResultCB->ExtentCount = count;
3087         RDR_SetFileExtents( pResultCB, dwResultBufferLength);
3088     }
3089     free(pResultCB);
3090
3091     if (reportErrorToRedir) {
3092         smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
3093         RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
3094     }
3095
3096     osi_Log4(afsd_logp, "Ending BKG Fetch scp 0x%p code 0x%x fetched 0x%x:%x",
3097              scp, code, fetched.HighPart, fetched.LowPart);
3098
3099     return force_retry ? CM_ERROR_RETRY : code;
3100 }
3101
3102
3103 BOOL
3104 RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
3105                              IN AFSFileID FileId,
3106                              IN AFSRequestExtentsCB *RequestExtentsCB,
3107                              IN BOOL bWow64,
3108                              IN OUT DWORD * ResultBufferLength,
3109                              IN OUT AFSSetFileExtentsCB **ResultCB)
3110 {
3111     AFSSetFileExtentsCB *pResultCB = NULL;
3112     DWORD Length;
3113     DWORD count;
3114     DWORD status;
3115     cm_scache_t *scp = NULL;
3116     cm_fid_t    Fid;
3117     cm_buf_t    *bufp;
3118     afs_uint32  code = 0;
3119     osi_hyper_t thyper;
3120     LARGE_INTEGER ByteOffset, BeginOffset, EndOffset, QueueOffset;
3121     afs_uint32  QueueLength;
3122     cm_req_t    req;
3123     BOOLEAN     bBufRelease = TRUE;
3124
3125     RDR_InitReq(&req);
3126     if ( bWow64 )
3127         req.flags |= CM_REQ_WOW64;
3128     req.flags |= CM_REQ_NORETRY;
3129
3130     osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3131               FileId.Cell, FileId.Volume,
3132               FileId.Vnode, FileId.Unique);
3133     osi_Log4(afsd_logp, "... Flags 0x%x ByteOffset 0x%x:%x Length 0x%x",
3134              RequestExtentsCB->Flags,
3135              RequestExtentsCB->ByteOffset.HighPart, RequestExtentsCB->ByteOffset.LowPart,
3136              RequestExtentsCB->Length);
3137     Length = sizeof( AFSSetFileExtentsCB) + sizeof( AFSFileExtentCB) * (RequestExtentsCB->Length / cm_data.blockSize + 1);
3138
3139     pResultCB = *ResultCB = (AFSSetFileExtentsCB *)malloc( Length );
3140     if (*ResultCB == NULL) {
3141         *ResultBufferLength = 0;
3142         return FALSE;
3143     }
3144     *ResultBufferLength = Length;
3145
3146     memset( pResultCB, '\0', Length );
3147     pResultCB->FileId = FileId;
3148
3149     Fid.cell = FileId.Cell;
3150     Fid.volume = FileId.Volume;
3151     Fid.vnode = FileId.Vnode;
3152     Fid.unique = FileId.Unique;
3153     Fid.hash = FileId.Hash;
3154
3155     code = cm_GetSCache(&Fid, &scp, userp, &req);
3156     if (code) {
3157         osi_Log1(afsd_logp, "RDR_RequestFileExtentsAsync cm_GetSCache FID failure code=0x%x",
3158                   code);
3159         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3160         return FALSE;
3161     }
3162
3163     /*
3164      * Make sure we have a callback.
3165      * This is necessary so that we can return access denied
3166      * if a callback cannot be granted.
3167      */
3168     lock_ObtainWrite(&scp->rw);
3169     code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
3170                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3171     lock_ReleaseWrite(&scp->rw);
3172     if (code) {
3173         cm_ReleaseSCache(scp);
3174         osi_Log2(afsd_logp, "RDR_RequestFileExtentsAsync cm_SyncOp failure scp=0x%p code=0x%x",
3175                  scp, code);
3176         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3177         RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
3178         return FALSE;
3179     }
3180
3181     /* Allocate the extents from the buffer package */
3182     for ( count = 0,
3183           ByteOffset = BeginOffset = RequestExtentsCB->ByteOffset,
3184           EndOffset.QuadPart = ByteOffset.QuadPart + RequestExtentsCB->Length;
3185           code == 0 && ByteOffset.QuadPart < EndOffset.QuadPart;
3186           ByteOffset.QuadPart += cm_data.blockSize)
3187     {
3188         BOOL bHaveBuffer = FALSE;
3189
3190         QueueLength = 0;
3191         thyper.QuadPart = ByteOffset.QuadPart;
3192
3193         code = buf_Get(scp, &thyper, &req, &bufp);
3194         if (code == 0) {
3195             lock_ObtainMutex(&bufp->mx);
3196             bBufRelease = TRUE;
3197
3198             if (bufp->qFlags & CM_BUF_QREDIR) {
3199                 bHaveBuffer = TRUE;
3200             } else if (bufp->flags & CM_BUF_DIRTY) {
3201                 bHaveBuffer = FALSE;
3202 #if 0
3203                 code = buf_CleanAsyncLocked(scp, bufp, &req, 0, NULL);
3204                 switch (code) {
3205                 case 0:
3206                     bHaveBuffer = TRUE;
3207                     break;
3208                 case CM_ERROR_RETRY:
3209                     /* Couldn't flush it, obtain it asynchronously so we don't block the thread. */
3210                     bHaveBuffer = FALSE;
3211                     code = 0;
3212                     break;
3213                 default:
3214                     smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3215                     RDR_SetFileStatus(&FileId, &userp->authgroup, status);
3216                     bHaveBuffer = FALSE;
3217                     code = 0;
3218                 }
3219 #endif
3220             } else {
3221                 osi_hyper_t minLength;  /* effective end of file */
3222
3223                 lock_ObtainRead(&scp->rw);
3224                 bHaveBuffer = cm_HaveBuffer(scp, bufp, TRUE);
3225
3226                 if (LargeIntegerGreaterThan(scp->length, scp->serverLength))
3227                     minLength = scp->serverLength;
3228                 else
3229                     minLength = scp->length;
3230
3231                 if (!bHaveBuffer &&
3232                     LargeIntegerGreaterThanOrEqualTo(bufp->offset, minLength)) {
3233                     memset(bufp->datap, 0, cm_data.buf_blockSize);
3234                     bufp->dataVersion = scp->dataVersion;
3235                     bHaveBuffer = TRUE;
3236                 }
3237                 else if ((RequestExtentsCB->Flags & AFS_EXTENT_FLAG_CLEAN) &&
3238                          ByteOffset.QuadPart <= bufp->offset.QuadPart &&
3239                          EndOffset.QuadPart >= bufp->offset.QuadPart + cm_data.blockSize)
3240                 {
3241                     memset(bufp->datap, 0, cm_data.blockSize);
3242                     bufp->dataVersion = scp->dataVersion;
3243                     buf_SetDirty(bufp, &req, 0, cm_data.blockSize, userp);
3244                     bHaveBuffer = TRUE;
3245                 }
3246                 lock_ReleaseRead(&scp->rw);
3247             }
3248
3249             /*
3250              * if this buffer is already up to date, skip it.
3251              */
3252             if (bHaveBuffer) {
3253                 if (ByteOffset.QuadPart == BeginOffset.QuadPart) {
3254                     BeginOffset.QuadPart += cm_data.blockSize;
3255                 } else {
3256                     QueueLength = (afs_uint32)(ByteOffset.QuadPart - BeginOffset.QuadPart);
3257                     QueueOffset = BeginOffset;
3258                     BeginOffset = ByteOffset;
3259                 }
3260
3261                 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3262 #ifdef VALIDATE_CHECK_SUM
3263 #ifdef ODS_DEBUG
3264                     char md5dbg[33];
3265                     char dbgstr[1024];
3266 #endif
3267 #endif
3268                     lock_ObtainWrite(&buf_globalLock);
3269                     if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3270                         buf_InsertToRedirQueue(scp, bufp);
3271                         lock_ReleaseWrite(&buf_globalLock);
3272
3273 #ifdef VALIDATE_CHECK_SUM
3274                         buf_ComputeCheckSum(bufp);
3275 #endif
3276                         /* we already have the buffer, return it now */
3277                         pResultCB->FileExtents[count].Flags = 0;
3278                         pResultCB->FileExtents[count].FileOffset = ByteOffset;
3279                         pResultCB->FileExtents[count].CacheOffset.QuadPart = bufp->datap - RDR_extentBaseAddress;
3280                         pResultCB->FileExtents[count].Length = cm_data.blockSize;
3281                         count++;
3282
3283                         bBufRelease = FALSE;
3284
3285 #ifdef VALIDATE_CHECK_SUM
3286 #ifdef ODS_DEBUG
3287                         HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3288                         snprintf( dbgstr, 1024,
3289                                   "RDR_RequestFileExtentsAsync md5 %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3290                                   md5dbg,
3291                                   scp->fid.volume, scp->fid.vnode, scp->fid.unique,
3292                                   pResultCB->FileExtents[count].FileOffset.HighPart,
3293                                   pResultCB->FileExtents[count].FileOffset.LowPart,
3294                                   pResultCB->FileExtents[count].CacheOffset.HighPart,
3295                                   pResultCB->FileExtents[count].CacheOffset.LowPart);
3296                         OutputDebugStringA( dbgstr);
3297 #endif
3298 #endif
3299                         osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync Extent2FS bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3300                                  bufp, ByteOffset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3301                     } else {
3302                         lock_ReleaseWrite(&buf_globalLock);
3303                     }
3304                 } else {
3305                     if (bBufRelease) {
3306                         /*
3307                          * The service is not handing off the extent to the redirector in this pass.
3308                          * However, we know the buffer is in recent use so move the buffer to the
3309                          * front of the queue
3310                          */
3311                         lock_ObtainWrite(&buf_globalLock);
3312                         buf_MoveToHeadOfRedirQueue(scp, bufp);
3313                         lock_ReleaseWrite(&buf_globalLock);
3314
3315                         osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync Extent2FS Already held by Redirector bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3316                                  bufp, ByteOffset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3317                     }
3318                 }
3319             }
3320             lock_ReleaseMutex(&bufp->mx);
3321             if (bBufRelease)
3322                 buf_Release(bufp);
3323
3324             if (QueueLength) {
3325                 cm_QueueBKGRequest(scp, RDR_BkgFetch, QueueOffset.LowPart, QueueOffset.HighPart,
3326                                    QueueLength, 0, userp, &req);
3327                 osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
3328                          QueueOffset.HighPart, QueueOffset.LowPart, QueueLength);
3329             }
3330         } else {
3331             /* No error from buf_Get() can be fatal */
3332             osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync buf_Get FAILURE offset 0x%x:%x code 0x%x",
3333                      BeginOffset.HighPart, BeginOffset.LowPart, code);
3334         }
3335     }
3336
3337     if (BeginOffset.QuadPart != EndOffset.QuadPart) {
3338         afs_uint32 length = (afs_uint32)(EndOffset.QuadPart - BeginOffset.QuadPart);
3339
3340         cm_QueueBKGRequest(scp, RDR_BkgFetch, BeginOffset.LowPart, BeginOffset.HighPart,
3341                            length, 0, userp, &req);
3342         osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
3343                   BeginOffset.HighPart, BeginOffset.LowPart, length);
3344     }
3345     cm_ReleaseSCache(scp);
3346
3347     (*ResultCB)->ExtentCount = count;
3348     osi_Log1(afsd_logp, "RDR_RequestFileExtentsAsync replying with 0x%x extent records", count);
3349     return FALSE;
3350 }
3351
3352 /*
3353  * When processing an extent release the extents must be accepted back by
3354  * the service even if there is an error condition returned to the redirector.
3355  * For example, there may no longer be a callback present or the file may
3356  * have been deleted on the file server.  Regardless, the extents must be
3357  * put back into the pool.
3358  */
3359 void
3360 RDR_ReleaseFileExtents( IN cm_user_t *userp,
3361                         IN AFSFileID FileId,
3362                         IN AFSReleaseExtentsCB *ReleaseExtentsCB,
3363                         IN BOOL bWow64,
3364                         IN DWORD ResultBufferLength,
3365                         IN OUT AFSCommResult **ResultCB)
3366 {
3367     DWORD count;
3368     cm_scache_t *scp = NULL;
3369     cm_fid_t    Fid;
3370     cm_buf_t    *bufp;
3371     afs_uint32  code;
3372     osi_hyper_t thyper;
3373     cm_req_t    req;
3374     int         dirty = 0;
3375     int         released = 0;
3376     DWORD       status;
3377 #ifdef ODS_DEBUG
3378 #ifdef VALIDATE_CHECK_SUM
3379     char md5dbg[33], md5dbg2[33], md5dbg3[33];
3380 #endif
3381     char dbgstr[1024];
3382 #endif
3383
3384     RDR_InitReq(&req);
3385     if ( bWow64 )
3386         req.flags |= CM_REQ_WOW64;
3387
3388     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3389               FileId.Cell, FileId.Volume,
3390               FileId.Vnode, FileId.Unique);
3391
3392     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
3393     if (!(*ResultCB))
3394         return;
3395
3396     memset( *ResultCB,
3397             '\0',
3398             sizeof( AFSCommResult));
3399
3400     /* Process the release */
3401     Fid.cell = FileId.Cell;
3402     Fid.volume = FileId.Volume;
3403     Fid.vnode = FileId.Vnode;
3404     Fid.unique = FileId.Unique;
3405     Fid.hash = FileId.Hash;
3406
3407     code = cm_GetSCache(&Fid, &scp, userp, &req);
3408     if (code) {
3409         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3410         (*ResultCB)->ResultStatus = status;
3411         osi_Log2(afsd_logp, "RDR_ReleaseFileExtents cm_GetSCache FID failure code=0x%x status=0x%x",
3412                   code, status);
3413     }
3414
3415     /*
3416      * We do not stop processing as a result of being unable to find the cm_scache object.
3417      * If this occurs something really bad has happened since the cm_scache object must have
3418      * been recycled while extents were held by the redirector.  However, we will be resilient
3419      * and carry on without it.
3420      */
3421     if (scp && ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart) {
3422         cm_attr_t setAttr;
3423
3424         memset(&setAttr, 0, sizeof(cm_attr_t));
3425         lock_ObtainWrite(&scp->rw);
3426         if (ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart) {
3427
3428             osi_Log4(afsd_logp, "RDR_ReleaseFileExtents new length fid vol 0x%x vno 0x%x length 0x%x:%x",
3429                       scp->fid.volume, scp->fid.vnode,
3430                       ReleaseExtentsCB->AllocationSize.HighPart,
3431                       ReleaseExtentsCB->AllocationSize.LowPart);
3432
3433             setAttr.mask |= CM_ATTRMASK_LENGTH;
3434             setAttr.length.LowPart = ReleaseExtentsCB->AllocationSize.LowPart;
3435             setAttr.length.HighPart = ReleaseExtentsCB->AllocationSize.HighPart;
3436         }
3437         lock_ReleaseWrite(&scp->rw);
3438         if (setAttr.mask)
3439             code = cm_SetAttr(scp, &setAttr, userp, &req);
3440     }
3441
3442     for ( count = 0; count < ReleaseExtentsCB->ExtentCount; count++) {
3443         AFSFileExtentCB * pExtent = &ReleaseExtentsCB->FileExtents[count];
3444
3445         thyper.QuadPart = pExtent->FileOffset.QuadPart;
3446
3447         bufp = buf_Find(&Fid, &thyper);
3448         if (bufp) {
3449             if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
3450                 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3451                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3452                               Fid.volume, Fid.vnode,
3453                               pExtent->FileOffset.HighPart,
3454                               pExtent->FileOffset.LowPart);
3455                     osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; previously released",
3456                               pExtent->CacheOffset.HighPart,
3457                               pExtent->CacheOffset.LowPart);
3458                 } else {
3459                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3460                               Fid.volume, Fid.vnode,
3461                               pExtent->FileOffset.HighPart,
3462                               pExtent->FileOffset.LowPart);
3463                     osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; owned by redirector",
3464                               pExtent->CacheOffset.HighPart,
3465                               pExtent->CacheOffset.LowPart);
3466                 }
3467                 buf_Release(bufp);
3468                 continue;
3469             }
3470
3471             if (pExtent->Flags & AFS_EXTENT_FLAG_IN_USE) {
3472                 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3473                           Fid.volume, Fid.vnode,
3474                           pExtent->FileOffset.HighPart,
3475                           pExtent->FileOffset.LowPart);
3476                 osi_Log2(afsd_logp, "... coffset 0x%x:%x IN_USE by file system",
3477                           pExtent->CacheOffset.HighPart,
3478                           pExtent->CacheOffset.LowPart);
3479
3480                 /* Move the buffer to the front of the queue */
3481                 lock_ObtainWrite(&buf_globalLock);
3482                 buf_MoveToHeadOfRedirQueue(scp, bufp);
3483                 lock_ReleaseWrite(&buf_globalLock);
3484                 buf_Release(bufp);
3485                 continue;
3486             }
3487
3488             if (bufp->datap - RDR_extentBaseAddress == pExtent->CacheOffset.QuadPart) {
3489                 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3490                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x not held by file system",
3491                              Fid.volume, Fid.vnode, pExtent->FileOffset.HighPart,
3492                              pExtent->FileOffset.LowPart);
3493                     osi_Log2(afsd_logp, "... coffset 0x%x:%x",
3494                              pExtent->CacheOffset.HighPart,
3495                              pExtent->CacheOffset.LowPart);
3496                 } else {
3497                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtents bufp 0x%p vno 0x%x foffset 0x%x:%x",
3498                               bufp, bufp->fid.vnode, pExtent->FileOffset.HighPart,
3499                               pExtent->FileOffset.LowPart);
3500                     osi_Log2(afsd_logp, "... coffset 0x%x:%x",
3501                              pExtent->CacheOffset.HighPart,
3502                              pExtent->CacheOffset.LowPart);
3503
3504                     if (pExtent->Flags || ReleaseExtentsCB->Flags) {
3505                         lock_ObtainMutex(&bufp->mx);
3506                         if ( (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_RELEASE) ||
3507                              (pExtent->Flags & AFS_EXTENT_FLAG_RELEASE) )
3508                         {
3509                             if (bufp->qFlags & CM_BUF_QREDIR) {
3510                                 lock_ObtainWrite(&buf_globalLock);
3511                                 if (bufp->qFlags & CM_BUF_QREDIR) {
3512                                     buf_RemoveFromRedirQueue(scp, bufp);
3513                                     buf_ReleaseLocked(bufp, TRUE);
3514                                 }
3515                                 lock_ReleaseWrite(&buf_globalLock);
3516                             }
3517 #ifdef ODS_DEBUG
3518                             snprintf( dbgstr, 1024,
3519                                       "RDR_ReleaseFileExtents releasing: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3520                                       Fid.volume, Fid.vnode, Fid.unique,
3521                                       pExtent->FileOffset.HighPart,
3522                                       pExtent->FileOffset.LowPart,
3523                                       pExtent->CacheOffset.HighPart,
3524                                       pExtent->CacheOffset.LowPart);
3525                             OutputDebugStringA( dbgstr);
3526 #endif
3527                             released++;
3528                         } else {
3529 #ifdef ODS_DEBUG
3530                             snprintf( dbgstr, 1024,
3531                                       "RDR_ReleaseFileExtents not releasing: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3532                                       Fid.volume, Fid.vnode, Fid.unique,
3533                                       pExtent->FileOffset.HighPart,
3534                                       pExtent->FileOffset.LowPart,
3535                                       pExtent->CacheOffset.HighPart,
3536                                       pExtent->CacheOffset.LowPart);
3537                             OutputDebugStringA( dbgstr);
3538 #endif
3539                             osi_Log4( afsd_logp, "RDR_ReleaseFileExtents not releasing vol 0x%x vno 0x%x foffset 0x%x:%x",
3540                                       Fid.volume, Fid.vnode,
3541                                       pExtent->FileOffset.HighPart,
3542                                       pExtent->FileOffset.LowPart);
3543                             osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3544                                       pExtent->CacheOffset.HighPart,
3545                                       pExtent->CacheOffset.LowPart);
3546                         }
3547
3548                         if ( (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
3549                              (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY) )
3550                         {
3551 #ifdef VALIDATE_CHECK_SUM
3552 #ifdef ODS_DEBUG
3553                             HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3554 #endif
3555
3556                             /*
3557                              * if the saved checksum matches the checksum of the current state of the buffer
3558                              * then the buffer is the same as what was given to the kernel.
3559                              */
3560                             if ( buf_ValidateCheckSum(bufp) ) {
3561                                 buf_ComputeCheckSum(bufp);
3562
3563                                 if (pExtent->Flags & AFS_EXTENT_FLAG_MD5_SET)
3564                                 {
3565 #ifdef ODS_DEBUG
3566                                     HexCheckSum(md5dbg2, sizeof(md5dbg2), pExtent->MD5);
3567                                     HexCheckSum(md5dbg3, sizeof(md5dbg3), bufp->md5cksum);
3568 #endif
3569                                     if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
3570                                     {
3571 #ifdef ODS_DEBUG
3572                                         snprintf( dbgstr, 1024,
3573                                                   "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",
3574                                                   md5dbg, md5dbg2,md5dbg3,
3575                                                   Fid.volume, Fid.vnode, Fid.unique,
3576                                                   pExtent->FileOffset.HighPart,
3577                                                   pExtent->FileOffset.LowPart,
3578                                                   pExtent->CacheOffset.HighPart,
3579                                                   pExtent->CacheOffset.LowPart);
3580                                         OutputDebugStringA( dbgstr);
3581 #endif
3582                                         osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set and checksums do not match! vol 0x%x vno 0x%x foffset 0x%x:%x",
3583                                                   Fid.volume, Fid.vnode,
3584                                                   pExtent->FileOffset.HighPart,
3585                                                   pExtent->FileOffset.LowPart);
3586                                         osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3587                                                   pExtent->CacheOffset.HighPart,
3588                                                   pExtent->CacheOffset.LowPart);
3589                                         buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
3590                                         dirty++;
3591                                     } else {
3592 #ifdef ODS_DEBUG
3593                                         snprintf( dbgstr, 1024,
3594                                                   "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",
3595                                                   md5dbg, md5dbg2, md5dbg3,
3596                                                   Fid.volume, Fid.vnode, Fid.unique,
3597                                                   pExtent->FileOffset.HighPart,
3598                                                   pExtent->FileOffset.LowPart,
3599                                                   pExtent->CacheOffset.HighPart,
3600                                                   pExtent->CacheOffset.LowPart);
3601                                         OutputDebugStringA( dbgstr);
3602 #endif
3603                                         osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
3604                                                   Fid.volume, Fid.vnode,
3605                                                   pExtent->FileOffset.HighPart,
3606                                                   pExtent->FileOffset.LowPart);
3607                                         osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3608                                                   pExtent->CacheOffset.HighPart,
3609                                                   pExtent->CacheOffset.LowPart);
3610                                     }
3611                                 } else {
3612 #ifdef ODS_DEBUG
3613                                         snprintf( dbgstr, 1024,
3614                                                   "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",
3615                                                   Fid.volume, Fid.vnode, Fid.unique,
3616                                                   pExtent->FileOffset.HighPart,
3617                                                   pExtent->FileOffset.LowPart,
3618                                                   pExtent->CacheOffset.HighPart,
3619                                                   pExtent->CacheOffset.LowPart);
3620                                         OutputDebugStringA( dbgstr);
3621 #endif
3622                                         osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
3623                                                   Fid.volume, Fid.vnode,
3624                                                   pExtent->FileOffset.HighPart,
3625                                                   pExtent->FileOffset.LowPart);
3626                                         osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3627                                                   pExtent->CacheOffset.HighPart,
3628                                                   pExtent->CacheOffset.LowPart);
3629                                 }
3630                             } else {
3631                                 buf_ComputeCheckSum(bufp);
3632 #ifdef ODS_DEBUG
3633                                 if (pExtent->Flags & AFS_EXTENT_FLAG_MD5_SET)
3634                                 {
3635                                     HexCheckSum(md5dbg3, sizeof(md5dbg3), bufp->md5cksum);
3636                                     if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
3637                                     {
3638                                         snprintf( dbgstr, 1024,
3639                                                   "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",
3640                                                   md5dbg, md5dbg2,md5dbg3,
3641                                                   Fid.volume, Fid.vnode, Fid.unique,
3642                                                   pExtent->FileOffset.HighPart,
3643                                                   pExtent->FileOffset.LowPart,
3644                                                   pExtent->CacheOffset.HighPart,
3645                                                   pExtent->CacheOffset.LowPart);
3646                                         OutputDebugStringA( dbgstr);
3647                                     } else {
3648                                         snprintf( dbgstr, 1024,
3649                                                   "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",
3650                                                   md5dbg, md5dbg2,md5dbg3,
3651                                                   Fid.volume, Fid.vnode, Fid.unique,
3652                                                   pExtent->FileOffset.HighPart,
3653                                                   pExtent->FileOffset.LowPart,
3654                                                   pExtent->CacheOffset.HighPart,
3655                                                   pExtent->CacheOffset.LowPart);
3656                                         OutputDebugStringA( dbgstr);
3657                                     }
3658                                 } else {
3659                                     snprintf( dbgstr, 1024,
3660                                               "RDR_ReleaseFileExtents dirty flag set: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3661                                               Fid.volume, Fid.vnode, Fid.unique,
3662                                               pExtent->FileOffset.HighPart,
3663                                               pExtent->FileOffset.LowPart,
3664                                               pExtent->CacheOffset.HighPart,
3665                                               pExtent->CacheOffset.LowPart);
3666                                     OutputDebugStringA( dbgstr);
3667                                 }
3668 #endif
3669                                 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
3670                                 dirty++;
3671                             }
3672 #else /* !VALIDATE_CHECK_SUM */
3673                             buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
3674                             dirty++;
3675 #endif /* VALIDATE_CHECK_SUM */
3676                         }
3677 #ifdef VALIDATE_CHECK_SUM
3678                         else {
3679 #ifdef ODS_DEBUG
3680                             HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3681 #endif
3682                             if ( !buf_ValidateCheckSum(bufp) ) {
3683                                 buf_ComputeCheckSum(bufp);
3684 #ifdef ODS_DEBUG
3685                                 HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
3686                                 snprintf( dbgstr, 1024,
3687                                           "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",
3688                                           md5dbg, md5dbg3,
3689                                           Fid.volume, Fid.vnode, Fid.unique,
3690                                           pExtent->FileOffset.HighPart,
3691                                           pExtent->FileOffset.LowPart,
3692                                           pExtent->CacheOffset.HighPart,
3693                                           pExtent->CacheOffset.LowPart);
3694                                 OutputDebugStringA( dbgstr);
3695 #endif
3696                                 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag not set but extent has changed vol 0x%x vno 0x%x foffset 0x%x:%x",
3697                                           Fid.volume, Fid.vnode,
3698                                           pExtent->FileOffset.HighPart,
3699                                           pExtent->FileOffset.LowPart);
3700                                 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3701                                           pExtent->CacheOffset.HighPart,
3702                                           pExtent->CacheOffset.LowPart);
3703                                 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
3704                                 dirty++;
3705                             } else {
3706                                 buf_ComputeCheckSum(bufp);
3707 #ifdef ODS_DEBUG
3708                                 HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
3709                                 snprintf( dbgstr, 1024,
3710                                           "RDR_ReleaseFileExtents dirty flag not set: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3711                                           Fid.volume, Fid.vnode, Fid.unique,
3712                                           pExtent->FileOffset.HighPart,
3713                                           pExtent->FileOffset.LowPart,
3714                                           pExtent->CacheOffset.HighPart,
3715                                           pExtent->CacheOffset.LowPart);
3716                                 OutputDebugStringA( dbgstr);
3717 #endif
3718                                 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag not set: vol 0x%x vno 0x%x foffset 0x%x:%x",
3719                                           Fid.volume, Fid.vnode,
3720                                           pExtent->FileOffset.HighPart,
3721                                           pExtent->FileOffset.LowPart);
3722                                 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3723                                           pExtent->CacheOffset.HighPart,
3724                                           pExtent->CacheOffset.LowPart);
3725                             }
3726                         }
3727 #endif /* VALIDATE_CHECK_SUM */
3728                         lock_ReleaseMutex(&bufp->mx);
3729                     }
3730                 }
3731             }
3732             else {
3733                 char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
3734                 cm_buf_t *wbp;
3735
3736                 for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
3737                     if (wbp->datap == datap)
3738                         break;
3739                 }
3740
3741 #ifdef ODS_DEBUG
3742                 snprintf( dbgstr, 1024,
3743                           "RDR_ReleaseFileExtents non-matching extent vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3744                           Fid.volume, Fid.vnode, Fid.unique,
3745                           pExtent->FileOffset.HighPart,
3746                           pExtent->FileOffset.LowPart,
3747                           pExtent->CacheOffset.HighPart,
3748                           pExtent->CacheOffset.LowPart);
3749                 OutputDebugStringA( dbgstr);
3750 #endif
3751                 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents non-matching extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3752                           Fid.volume, Fid.vnode,
3753                           pExtent->FileOffset.HighPart,
3754                           pExtent->FileOffset.LowPart);
3755                 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3756                           pExtent->CacheOffset.HighPart,
3757                           pExtent->CacheOffset.LowPart);
3758                 osi_Log5( afsd_logp, "... belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
3759                           wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
3760 #ifdef DEBUG
3761                 DebugBreak();
3762 #endif
3763             }
3764             buf_Release(bufp);
3765         }
3766         else {
3767             char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
3768             cm_buf_t *wbp;
3769
3770             for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
3771                 if (wbp->datap == datap)
3772                     break;
3773             }
3774
3775 #ifdef ODS_DEBUG
3776             snprintf( dbgstr, 1024,
3777                       "RDR_ReleaseFileExtents unknown extent vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3778                       Fid.volume, Fid.vnode, Fid.unique,
3779                       pExtent->FileOffset.HighPart,
3780                       pExtent->FileOffset.LowPart,
3781                       pExtent->CacheOffset.HighPart,
3782                       pExtent->CacheOffset.LowPart);
3783             OutputDebugStringA( dbgstr);
3784 #endif
3785             osi_Log4( afsd_logp, "RDR_ReleaseFileExtents unknown extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3786                       Fid.volume, Fid.vnode,
3787                       pExtent->FileOffset.HighPart,
3788                       pExtent->FileOffset.LowPart);
3789             osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3790                       pExtent->CacheOffset.HighPart,
3791                       pExtent->CacheOffset.LowPart);
3792             osi_Log5( afsd_logp, "... belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
3793                       wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
3794         }
3795     }
3796
3797     if (scp) {
3798         if (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_FLUSH) {
3799             lock_ObtainWrite(&scp->rw);
3800             code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
3801                              CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3802             lock_ReleaseWrite(&scp->rw);
3803             if (code == 0)
3804                 code = cm_FSync(scp, userp, &req, FALSE);
3805         }
3806         else if (dirty) {
3807             osi_hyper_t offset = {0,0};
3808             afs_uint32  length = 0;
3809             afs_uint32  rights = 0;
3810
3811             lock_ObtainWrite(&scp->rw);
3812             code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
3813                              CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3814             lock_ReleaseWrite(&scp->rw);
3815             if (code == 0) {
3816                 /*
3817                  * there is at least one dirty extent on this file.  queue up background store
3818                  * requests for contiguous blocks
3819                  */
3820                 for ( count = 0; count < ReleaseExtentsCB->ExtentCount; count++) {
3821                     if (ReleaseExtentsCB->FileExtents[count].FileOffset.QuadPart == offset.QuadPart + length &&
3822                          length + cm_data.buf_blockSize <= cm_chunkSize)
3823                     {
3824                         length += cm_data.buf_blockSize;
3825                     } else {
3826                         if (!(offset.QuadPart == 0 && length == 0))
3827                             cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
3828                                                 length, 0, userp, &req);
3829                         offset.QuadPart = ReleaseExtentsCB->FileExtents[count].FileOffset.QuadPart;
3830                         length = cm_data.buf_blockSize;
3831                     }
3832                 }
3833                 cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
3834                                    length, 0, userp, &req);
3835             }
3836         }
3837         cm_ReleaseSCache(scp);
3838     }
3839
3840     osi_Log5(afsd_logp, "RDR_ReleaseFileExtents File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x Released %d",
3841               FileId.Cell, FileId.Volume,
3842               FileId.Vnode, FileId.Unique, released);
3843     if (code && code != CM_ERROR_WOULDBLOCK) {
3844         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3845         (*ResultCB)->ResultStatus = status;
3846         osi_Log2(afsd_logp, "RDR_ReleaseFileExtents FAILURE code=0x%x status=0x%x",
3847                   code, status);
3848     } else {
3849         (*ResultCB)->ResultStatus = 0;
3850         osi_Log0(afsd_logp, "RDR_ReleaseFileExtents SUCCESS");
3851     }
3852     (*ResultCB)->ResultBufferLength = 0;
3853
3854     return;
3855 }
3856
3857 DWORD
3858 RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFileExtentsResultCB,
3859                                      IN DWORD ResultBufferLength)
3860 {
3861     afs_uint32  code = 0;
3862     cm_req_t    req;
3863     osi_hyper_t thyper;
3864     cm_buf_t    *bufp;
3865     unsigned int fileno, extentno, total_extents = 0;
3866     AFSReleaseFileExtentsResultFileCB *pNextFileCB;
3867 #ifdef ODS_DEBUG
3868 #ifdef VALIDATE_CHECK_SUM
3869     char md5dbg[33], md5dbg2[33], md5dbg3[33];
3870 #endif
3871     char dbgstr[1024];
3872 #endif
3873     RDR_InitReq(&req);
3874
3875     for ( fileno = 0, pNextFileCB = &ReleaseFileExtentsResultCB->Files[0];
3876           fileno < ReleaseFileExtentsResultCB->FileCount;
3877           fileno++ ) {
3878         AFSReleaseFileExtentsResultFileCB *pFileCB = pNextFileCB;
3879         cm_user_t       *userp = NULL;
3880         cm_fid_t         Fid;
3881         cm_scache_t *    scp = NULL;
3882         int              dirty = 0;
3883         int              released = 0;
3884         char * p;
3885
3886         userp = RDR_UserFromAuthGroup( &pFileCB->AuthGroup);
3887
3888         osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult %d.%d.%d.%d",
3889                   pFileCB->FileId.Cell, pFileCB->FileId.Volume,
3890                   pFileCB->FileId.Vnode, pFileCB->FileId.Unique);
3891
3892         /* Process the release */
3893         Fid.cell = pFileCB->FileId.Cell;
3894         Fid.volume = pFileCB->FileId.Volume;
3895         Fid.vnode = pFileCB->FileId.Vnode;
3896         Fid.unique = pFileCB->FileId.Unique;
3897         Fid.hash = pFileCB->FileId.Hash;
3898
3899         if (Fid.cell == 0) {
3900             osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult Invalid FID %d.%d.%d.%d",
3901                      Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
3902             code = CM_ERROR_INVAL;
3903             goto cleanup_file;
3904         }
3905
3906         code = cm_GetSCache(&Fid, &scp, userp, &req);
3907         if (code) {
3908             osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult cm_GetSCache FID failure code=0x%x",
3909                      code);
3910             /*
3911              * A failure to find the cm_scache object cannot prevent the service
3912              * from accepting the extents back from the redirector.
3913              */
3914         }
3915
3916         /* if the scp was not found, do not perform the length check */
3917         if (scp && (pFileCB->AllocationSize.QuadPart != scp->length.QuadPart)) {
3918             cm_attr_t setAttr;
3919
3920             memset(&setAttr, 0, sizeof(cm_attr_t));
3921             lock_ObtainWrite(&scp->rw);
3922             if (pFileCB->AllocationSize.QuadPart != scp->length.QuadPart) {
3923                 osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult length change vol 0x%x vno 0x%x length 0x%x:%x",
3924                           scp->fid.volume, scp->fid.vnode,
3925                           pFileCB->AllocationSize.HighPart,
3926                           pFileCB->AllocationSize.LowPart);
3927                 setAttr.mask |= CM_ATTRMASK_LENGTH;
3928                 setAttr.length.LowPart = pFileCB->AllocationSize.LowPart;
3929                 setAttr.length.HighPart = pFileCB->AllocationSize.HighPart;
3930             }
3931             lock_ReleaseWrite(&scp->rw);
3932             if (setAttr.mask)
3933                 code = cm_SetAttr(scp, &setAttr, userp, &req);
3934         }
3935
3936         for ( extentno = 0; extentno < pFileCB->ExtentCount; total_extents++, extentno++ ) {
3937             AFSFileExtentCB *pExtent = &pFileCB->FileExtents[extentno];
3938
3939             thyper.QuadPart = pExtent->FileOffset.QuadPart;
3940
3941             bufp = buf_Find(&Fid, &thyper);
3942             if (bufp) {
3943                 if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
3944                     if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3945                         osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3946                                  Fid.volume, Fid.vnode,
3947                                  pExtent->FileOffset.HighPart,
3948                                  pExtent->FileOffset.LowPart);
3949                         osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; previously released",
3950                                  pExtent->CacheOffset.HighPart,
3951                                  pExtent->CacheOffset.LowPart);
3952                     } else {
3953                         osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3954                                  Fid.volume, Fid.vnode,
3955                                  pExtent->FileOffset.HighPart,
3956                                  pExtent->FileOffset.LowPart);
3957                         osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; owned by redirector",
3958                                  pExtent->CacheOffset.HighPart,
3959                                  pExtent->CacheOffset.LowPart);
3960                     }
3961                     buf_Release(bufp);
3962                     continue;
3963                 }
3964
3965                 if (pExtent->Flags & AFS_EXTENT_FLAG_IN_USE) {
3966                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3967                               Fid.volume, Fid.vnode,
3968                               pExtent->FileOffset.HighPart,
3969                               pExtent->FileOffset.LowPart);
3970                     osi_Log2(afsd_logp, "... coffset 0x%x:%x IN_USE by file system",
3971                               pExtent->CacheOffset.HighPart,
3972                               pExtent->CacheOffset.LowPart);
3973
3974                     /* Move the buffer to the front of the queue */
3975                     lock_ObtainWrite(&buf_globalLock);
3976                     buf_MoveToHeadOfRedirQueue(scp, bufp);
3977                     lock_ReleaseWrite(&buf_globalLock);
3978                     buf_Release(bufp);
3979                     continue;
3980                 }
3981
3982                 if (bufp->datap - RDR_extentBaseAddress == pExtent->CacheOffset.QuadPart) {
3983                     if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3984                         osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3985                                  Fid.volume, Fid.vnode,
3986                                  pExtent->FileOffset.HighPart,
3987                                  pExtent->FileOffset.LowPart);
3988                         osi_Log2(afsd_logp, "... coffset 0x%x:%x not held by file system",
3989                                  pExtent->CacheOffset.HighPart,
3990                                  pExtent->CacheOffset.LowPart);
3991 #ifdef ODS_DEBUG
3992                         snprintf(dbgstr, 1024,
3993                                   "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",
3994                                   ReleaseFileExtentsResultCB->Flags, pExtent->Flags,
3995                                   Fid.volume, Fid.vnode, Fid.unique,
3996                                   pExtent->FileOffset.HighPart,
3997                                   pExtent->FileOffset.LowPart,
3998                                   pExtent->CacheOffset.HighPart,
3999                                   pExtent->CacheOffset.LowPart);
4000                         OutputDebugStringA( dbgstr);
4001 #endif
4002                     } else {
4003                         osi_Log5(afsd_logp, "RDR_ProcessReleaseFileExtentsResult bufp 0x%p foffset 0x%x:%x coffset 0x%x:%x",
4004                                  bufp, pExtent->FileOffset.HighPart, pExtent->FileOffset.LowPart,
4005                                  pExtent->CacheOffset.HighPart, pExtent->CacheOffset.LowPart);
4006
4007                         if (pExtent->Flags || ReleaseFileExtentsResultCB->Flags) {
4008                             lock_ObtainMutex(&bufp->mx);
4009                             if ( (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_RELEASE) ||
4010                                  (pExtent->Flags & AFS_EXTENT_FLAG_RELEASE) )
4011                             {
4012                                 if (bufp->qFlags & CM_BUF_QREDIR) {
4013                                     lock_ObtainWrite(&buf_globalLock);
4014                                     if (bufp->qFlags & CM_BUF_QREDIR) {
4015                                         buf_RemoveFromRedirQueue(scp, bufp);
4016                                         buf_ReleaseLocked(bufp, TRUE);
4017                                     }
4018                                     lock_ReleaseWrite(&buf_globalLock);
4019                                 }
4020
4021 #ifdef ODS_DEBUG
4022                                 snprintf(dbgstr, 1024,
4023                                           "RDR_ProcessReleaseFileExtentsResult extent released: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4024                                           Fid.volume, Fid.vnode, Fid.unique,
4025                                           pExtent->FileOffset.HighPart,
4026                                           pExtent->FileOffset.LowPart,
4027                                           pExtent->CacheOffset.HighPart,
4028                                           pExtent->CacheOffset.LowPart);
4029                                 OutputDebugStringA( dbgstr);
4030 #endif
4031
4032                                 released++;
4033                             } else {
4034                                 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult not releasing vol 0x%x vno 0x%x foffset 0x%x:%x",
4035                                          Fid.volume, Fid.vnode,
4036                                          pExtent->FileOffset.HighPart,
4037                                          pExtent->FileOffset.LowPart);
4038                                 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4039                                          pExtent->CacheOffset.HighPart,
4040                                          pExtent->CacheOffset.LowPart);
4041 #ifdef ODS_DEBUG
4042                                 snprintf(dbgstr, 1024,
4043                                           "RDR_ProcessReleaseFileExtentsResult not released! vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4044                                           Fid.volume, Fid.vnode, Fid.unique,
4045                                           pExtent->FileOffset.HighPart,
4046                                           pExtent->FileOffset.LowPart,
4047                                           pExtent->CacheOffset.HighPart,
4048                                           pExtent->CacheOffset.LowPart);
4049                                 OutputDebugStringA( dbgstr);
4050 #endif
4051                             }
4052
4053                             if ( (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
4054                                  (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY) )
4055                             {
4056 #ifdef VALIDATE_CHECK_SUM
4057                                 if ( buf_ValidateCheckSum(bufp) ) {
4058 #ifdef ODS_DEBUG
4059                                     HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
4060                                     if (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_MD5_SET)
4061                                         HexCheckSum(md5dbg2, sizeof(md5dbg2), pExtent->MD5);
4062 #endif
4063                                     buf_ComputeCheckSum(bufp);
4064 #ifdef ODS_DEBUG
4065                                     HexCheckSum(md5dbg3, sizeof(md5dbg), bufp->md5cksum);
4066 #endif
4067                                     if (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_MD5_SET)
4068                                     {
4069                                         if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
4070                                         {
4071 #ifdef ODS_DEBUG
4072                                             snprintf(dbgstr, 1024,
4073                                                       "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",
4074                                                       md5dbg3, md5dbg2,
4075                                                       Fid.volume, Fid.vnode, Fid.unique,
4076                                                       pExtent->FileOffset.HighPart,
4077                                                       pExtent->FileOffset.LowPart,
4078                                                       pExtent->CacheOffset.HighPart,
4079                                                       pExtent->CacheOffset.LowPart);
4080                                             OutputDebugStringA( dbgstr);
4081 #endif
4082                                             osi_Log4(afsd_logp,
4083                                                       "RDR_ProcessReleaseFileExtentsResult dirty flag set and checksums do not match! vol 0x%x vno 0x%x foffset 0x%x:%x",
4084                                                       Fid.volume, Fid.vnode,
4085                                                       pExtent->FileOffset.HighPart,
4086                                                       pExtent->FileOffset.LowPart);
4087                                             osi_Log2(afsd_logp,
4088                                                       "... coffset 0x%x:%x",
4089                                                       pExtent->CacheOffset.HighPart,
4090                                                       pExtent->CacheOffset.LowPart);
4091
4092                                             buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4093                                             dirty++;
4094                                         } else {
4095 #ifdef ODS_DEBUG
4096                                             snprintf(dbgstr, 1024,
4097                                                       "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",
4098                                                       md5dbg, md5dbg2, md5dbg3,
4099                                                       Fid.volume, Fid.vnode, Fid.unique,
4100                                                       pExtent->FileOffset.HighPart,
4101                                                       pExtent->FileOffset.LowPart,
4102                                                       pExtent->CacheOffset.HighPart,
4103                                                       pExtent->CacheOffset.LowPart);
4104                                             OutputDebugStringA( dbgstr);
4105 #endif
4106                                             osi_Log4(afsd_logp,
4107                                                       "RDR_ProcessReleaseFileExtentsResult dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
4108                                                       Fid.volume, Fid.vnode,
4109                                                       pExtent->FileOffset.HighPart,
4110                                                       pExtent->FileOffset.LowPart);
4111                                             osi_Log2(afsd_logp,
4112                                                       "... coffset 0x%x:%x",
4113                                                       pExtent->CacheOffset.HighPart,
4114                                                       pExtent->CacheOffset.LowPart);
4115                                         }
4116                                     }
4117                                 }
4118 #else /* !VALIDATE_CHECK_SUM */
4119                                 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4120                                 dirty++;
4121 #ifdef ODS_DEBUG
4122                                 snprintf(dbgstr, 1024,
4123                                           "RDR_ProcessReleaseFileExtentsResult dirty! vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4124                                           Fid.volume, Fid.vnode, Fid.unique,
4125                                           pExtent->FileOffset.HighPart,
4126                                           pExtent->FileOffset.LowPart,
4127                                           pExtent->CacheOffset.HighPart,
4128                                           pExtent->CacheOffset.LowPart);
4129                                 OutputDebugStringA( dbgstr);
4130 #endif
4131 #endif /* VALIDATE_CHECK_SUM */
4132                             }
4133 #ifdef VALIDATE_CHECK_SUM
4134                             else {
4135 #ifdef ODS_DEBUG
4136                                 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
4137 #endif
4138                                 if ( !buf_ValidateCheckSum(bufp) ) {
4139                                     buf_ComputeCheckSum(bufp);
4140 #ifdef ODS_DEBUG
4141                                     HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
4142                                     snprintf(dbgstr, 1024,
4143                                              "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",
4144                                              md5dbg, md5dbg3,
4145                                              Fid.volume, Fid.vnode, Fid.unique,
4146                                              pExtent->FileOffset.HighPart,
4147                                              pExtent->FileOffset.LowPart,
4148                                              pExtent->CacheOffset.HighPart,
4149                                              pExtent->CacheOffset.LowPart);
4150                                     OutputDebugStringA( dbgstr);
4151 #endif
4152                                     osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult dirty flag NOT set but extent has changed! vol 0x%x vno 0x%x foffset 0x%x:%x",
4153                                              Fid.volume, Fid.vnode,
4154                                              pExtent->FileOffset.HighPart,
4155                                              pExtent->FileOffset.LowPart);
4156                                     osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4157                                              pExtent->CacheOffset.HighPart,
4158                                              pExtent->CacheOffset.LowPart);
4159 #ifdef DEBUG
4160                                     DebugBreak();
4161 #endif
4162                                     buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4163                                     dirty++;
4164                                 } else {
4165                                     buf_ComputeCheckSum(bufp);
4166 #ifdef ODS_DEBUG
4167                                     HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
4168                                     snprintf(dbgstr, 1024,
4169                                              "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",
4170                                              md5dbg, md5dbg3,
4171                                              Fid.volume, Fid.vnode, Fid.unique,
4172                                              pExtent->FileOffset.HighPart,
4173                                              pExtent->FileOffset.LowPart,
4174                                              pExtent->CacheOffset.HighPart,
4175                                              pExtent->CacheOffset.LowPart);
4176                                     OutputDebugStringA( dbgstr);
4177 #endif
4178                                 }
4179                             }
4180 #endif /* VALIDATE_CHECK_SUM */
4181                             lock_ReleaseMutex(&bufp->mx);
4182                         }
4183                     }
4184                 } else {
4185                     /* CacheOffset doesn't match bufp->datap */
4186                     char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
4187                     cm_buf_t *wbp;
4188
4189                     for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
4190                         if (wbp->datap == datap)
4191                             break;
4192                     }
4193
4194 #ifdef ODS_DEBUG
4195                     snprintf(dbgstr, 1024,
4196                              "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",
4197                              Fid.volume, Fid.vnode, Fid.unique,
4198                              pExtent->FileOffset.HighPart,
4199                              pExtent->FileOffset.LowPart,
4200                              pExtent->CacheOffset.HighPart,
4201                              pExtent->CacheOffset.LowPart,
4202                              pExtent->Flags);
4203                     OutputDebugStringA( dbgstr);
4204 #endif
4205                     osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult non-matching extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4206                              Fid.volume, Fid.vnode,
4207                              pExtent->FileOffset.HighPart,
4208                              pExtent->FileOffset.LowPart);
4209                     osi_Log3(afsd_logp, "... coffset 0x%x:%x flags 0x%x",
4210                              pExtent->CacheOffset.HighPart,
4211                              pExtent->CacheOffset.LowPart,
4212                              pExtent->Flags);
4213                     if (wbp)
4214                         osi_Log5(afsd_logp, "... coffset belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
4215                                  wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
4216                     else
4217                         osi_Log0(afsd_logp, "... coffset cannot be found");
4218 #ifdef DEBUG
4219                     DebugBreak();
4220 #endif
4221                 }
4222                 buf_Release(bufp);
4223             } else {
4224                 if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
4225                     osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4226                              Fid.volume, Fid.vnode, pExtent->FileOffset.HighPart,
4227                              pExtent->FileOffset.LowPart);
4228                     osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; cm_buf not found -- recycled?",
4229                              pExtent->CacheOffset.HighPart,
4230                              pExtent->CacheOffset.LowPart);
4231
4232                     continue;
4233                 }
4234
4235 #ifdef ODS_DEBUG
4236                 snprintf(dbgstr, 1024,
4237                          "RDR_ProcessReleaseFileExtentsResult buf not found vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4238                          Fid.volume, Fid.vnode, Fid.unique,
4239                          pExtent->FileOffset.HighPart,
4240                          pExtent->FileOffset.LowPart,
4241                          pExtent->CacheOffset.HighPart,
4242                          pExtent->CacheOffset.LowPart);
4243                 OutputDebugStringA( dbgstr);
4244 #endif
4245                 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult buf not found vol 0x%x vno 0x%x foffset 0x%x:%x",
4246                          Fid.volume, Fid.vnode,
4247                          pExtent->FileOffset.HighPart,
4248                          pExtent->FileOffset.LowPart);
4249                 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4250                          pExtent->CacheOffset.HighPart,
4251                          pExtent->CacheOffset.LowPart);
4252             }
4253         }
4254
4255         if (scp && dirty) {
4256             osi_hyper_t offset = {0,0};
4257             afs_uint32  length = 0;
4258
4259             /*
4260              * there is at least one dirty extent on this file.  queue up background store
4261              * requests for contiguous blocks
4262              */
4263             for ( extentno = 0; extentno < pFileCB->ExtentCount; extentno++ ) {
4264                 AFSFileExtentCB *pExtent = &pFileCB->FileExtents[extentno];
4265                 if (pExtent->FileOffset.QuadPart == offset.QuadPart + length &&
4266                      length < cm_chunkSize) {
4267                     length += cm_data.buf_blockSize;
4268                 } else {
4269                     if (!(offset.QuadPart == 0 && length == 0))
4270                         cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
4271                                             length, 0, userp, &req);
4272                     offset.QuadPart = pExtent->FileOffset.QuadPart;
4273                     length = cm_data.buf_blockSize;
4274                 }
4275             }
4276             cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
4277                                 length, 0, userp, &req);
4278         }
4279
4280         osi_Log5(afsd_logp, "RDR_ProcessReleaseFileExtentsResult File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x Released %d",
4281                   Fid.cell, Fid.volume, Fid.vnode, Fid.unique, released);
4282
4283       cleanup_file:
4284         if (userp)
4285             cm_ReleaseUser(userp);
4286         if (scp)
4287             cm_ReleaseSCache(scp);
4288
4289         p = (char *)pFileCB;
4290         p += sizeof(AFSReleaseFileExtentsResultFileCB);
4291         p += sizeof(AFSFileExtentCB) * (pFileCB->ExtentCount - 1);
4292         pNextFileCB = (AFSReleaseFileExtentsResultFileCB *)p;
4293     }
4294
4295     if (total_extents == 0) {
4296         osi_Log0(afsd_logp, "RDR_ProcessReleaseFileExtentsResult is empty");
4297         code = CM_ERROR_RETRY;
4298     }
4299
4300     if (code)
4301         osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult FAILURE code=0x%x", code);
4302     else
4303         osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult DONE code=0x%x", code);
4304
4305     return code;
4306 }
4307
4308 DWORD
4309 RDR_ReleaseFailedSetFileExtents( IN cm_user_t *userp,
4310                                  IN AFSSetFileExtentsCB *SetFileExtentsResultCB,
4311                                  IN DWORD ResultBufferLength)
4312 {
4313     afs_uint32  code = 0;
4314     cm_req_t    req;
4315     unsigned int extentno;
4316     cm_fid_t         Fid;
4317     cm_scache_t *    scp = NULL;
4318     int              dirty = 0;
4319
4320     RDR_InitReq(&req);
4321
4322     osi_Log4(afsd_logp, "RDR_ReleaseFailedSetFileExtents %d.%d.%d.%d",
4323               SetFileExtentsResultCB->FileId.Cell, SetFileExtentsResultCB->FileId.Volume,
4324               SetFileExtentsResultCB->FileId.Vnode, SetFileExtentsResultCB->FileId.Unique);
4325
4326     /* Process the release */
4327     Fid.cell = SetFileExtentsResultCB->FileId.Cell;
4328     Fid.volume = SetFileExtentsResultCB->FileId.Volume;
4329     Fid.vnode = SetFileExtentsResultCB->FileId.Vnode;
4330     Fid.unique = SetFileExtentsResultCB->FileId.Unique;
4331     Fid.hash = SetFileExtentsResultCB->FileId.Hash;
4332
4333     if (Fid.cell == 0) {
4334         osi_Log4(afsd_logp, "RDR_ReleaseFailedSetFile Invalid FID %d.%d.%d.%d",
4335                   Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
4336         code = CM_ERROR_INVAL;
4337         goto cleanup_file;
4338     }
4339
4340     code = cm_GetSCache(&Fid, &scp, userp, &req);
4341     if (code) {
4342         osi_Log1(afsd_logp, "RDR_ReleaseFailedSetFileExtents cm_GetSCache FID failure code=0x%x",
4343                   code);
4344         /* Failure to find the cm_scache object cannot block return of the extents */
4345     }
4346
4347     for ( extentno = 0; extentno < SetFileExtentsResultCB->ExtentCount; extentno++ ) {
4348         osi_hyper_t thyper;
4349         cm_buf_t    *bufp;
4350         AFSFileExtentCB *pExtent = &SetFileExtentsResultCB->FileExtents[extentno];
4351
4352         thyper.QuadPart = pExtent->FileOffset.QuadPart;
4353
4354         bufp = buf_Find(&Fid, &thyper);
4355         if (bufp) {
4356             osi_Log5(afsd_logp, "RDR_ReleaseFailedSetFileExtents bufp 0x%p foffset 0x%x:%x coffset 0x%x:%x",
4357                       bufp, pExtent->FileOffset.HighPart, pExtent->FileOffset.LowPart,
4358                       pExtent->CacheOffset.HighPart, pExtent->CacheOffset.LowPart);
4359
4360             lock_ObtainMutex(&bufp->mx);
4361             if (bufp->qFlags & CM_BUF_QREDIR) {
4362                 lock_ObtainWrite(&buf_globalLock);
4363                 if (bufp->qFlags & CM_BUF_QREDIR) {
4364                     buf_RemoveFromRedirQueue(scp, bufp);
4365                     buf_ReleaseLocked(bufp, TRUE);
4366                 }
4367                 lock_ReleaseWrite(&buf_globalLock);
4368             }
4369             lock_ReleaseMutex(&bufp->mx);
4370             buf_Release(bufp);
4371         }
4372     }
4373
4374   cleanup_file:
4375     if (userp)
4376         cm_ReleaseUser(userp);
4377     if (scp)
4378         cm_ReleaseSCache(scp);
4379
4380     osi_Log1(afsd_logp, "RDR_ReleaseFailedSetFileExtents DONE code=0x%x", code);
4381     return code;
4382 }
4383
4384 void
4385 RDR_PioctlOpen( IN cm_user_t *userp,
4386                 IN AFSFileID  ParentId,
4387                 IN AFSPIOCtlOpenCloseRequestCB *pPioctlCB,
4388                 IN BOOL bWow64,
4389                 IN DWORD ResultBufferLength,
4390                 IN OUT AFSCommResult **ResultCB)
4391 {
4392     cm_fid_t    ParentFid;
4393     cm_fid_t    RootFid;
4394
4395     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
4396     if (!(*ResultCB))
4397         return;
4398
4399     memset( *ResultCB,
4400             '\0',
4401             sizeof( AFSCommResult));
4402
4403     /* Get the active directory */
4404     ParentFid.cell = ParentId.Cell;
4405     ParentFid.volume = ParentId.Volume;
4406     ParentFid.vnode = ParentId.Vnode;
4407     ParentFid.unique = ParentId.Unique;
4408     ParentFid.hash = ParentId.Hash;
4409
4410     /* Get the root directory */
4411     RootFid.cell = pPioctlCB->RootId.Cell;
4412     RootFid.volume = pPioctlCB->RootId.Volume;
4413     RootFid.vnode = pPioctlCB->RootId.Vnode;
4414     RootFid.unique = pPioctlCB->RootId.Unique;
4415     RootFid.hash = pPioctlCB->RootId.Hash;
4416
4417     /* Create the pioctl index */
4418     RDR_SetupIoctl(pPioctlCB->RequestId, &ParentFid, &RootFid, userp);
4419
4420     return;
4421 }
4422
4423
4424 void
4425 RDR_PioctlClose( IN cm_user_t *userp,
4426                  IN AFSFileID  ParentId,
4427                  IN AFSPIOCtlOpenCloseRequestCB *pPioctlCB,
4428                  IN BOOL bWow64,
4429                  IN DWORD ResultBufferLength,
4430                  IN OUT AFSCommResult **ResultCB)
4431 {
4432     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
4433     if (!(*ResultCB))
4434         return;
4435
4436     memset( *ResultCB,
4437             '\0',
4438             sizeof( AFSCommResult));
4439
4440     /* Cleanup the pioctl index */
4441     RDR_CleanupIoctl(pPioctlCB->RequestId);
4442
4443     return;
4444 }
4445
4446
4447 void
4448 RDR_PioctlWrite( IN cm_user_t *userp,
4449                  IN AFSFileID  ParentId,
4450                  IN AFSPIOCtlIORequestCB *pPioctlCB,
4451                  IN BOOL bWow64,
4452                  IN DWORD ResultBufferLength,
4453                  IN OUT AFSCommResult **ResultCB)
4454 {
4455     AFSPIOCtlIOResultCB *pResultCB;
4456     cm_scache_t *dscp = NULL;
4457     afs_uint32  code;
4458     cm_req_t    req;
4459     DWORD       status;
4460
4461     RDR_InitReq(&req);
4462     if ( bWow64 )
4463         req.flags |= CM_REQ_WOW64;
4464
4465     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4466     if (!(*ResultCB))
4467         return;
4468
4469     memset( *ResultCB,
4470             '\0',
4471             sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4472
4473     pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
4474
4475     code = RDR_IoctlWrite(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer, &req);
4476     if (code) {
4477         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4478         (*ResultCB)->ResultStatus = status;
4479         return;
4480     }
4481
4482     pResultCB->BytesProcessed = pPioctlCB->BufferLength;
4483     (*ResultCB)->ResultBufferLength = sizeof( AFSPIOCtlIOResultCB);
4484 }
4485
4486 void
4487 RDR_PioctlRead( IN cm_user_t *userp,
4488                 IN AFSFileID  ParentId,
4489                 IN AFSPIOCtlIORequestCB *pPioctlCB,
4490                 IN BOOL bWow64,
4491                 IN BOOL bIsLocalSystem,
4492                 IN DWORD ResultBufferLength,
4493                 IN OUT AFSCommResult **ResultCB)
4494 {
4495     AFSPIOCtlIOResultCB *pResultCB;
4496     cm_scache_t *dscp = NULL;
4497     afs_uint32  code;
4498     cm_req_t    req;
4499     DWORD       status;
4500     afs_uint32  pflags = (bIsLocalSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
4501
4502     RDR_InitReq(&req);
4503     if ( bWow64 )
4504         req.flags |= CM_REQ_WOW64;
4505
4506     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4507     if (!(*ResultCB))
4508         return;
4509
4510     memset( *ResultCB,
4511             '\0',
4512             sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4513
4514     pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
4515
4516     code = RDR_IoctlRead(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer,
4517                          &pResultCB->BytesProcessed, &req, pflags);
4518     if (code) {
4519         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4520         (*ResultCB)->ResultStatus = status;
4521         return;
4522     }
4523
4524     (*ResultCB)->ResultBufferLength = sizeof( AFSPIOCtlIOResultCB);
4525 }
4526
4527 void
4528 RDR_ByteRangeLockSync( IN cm_user_t     *userp,
4529                        IN AFSFileID     FileId,
4530                        IN AFSByteRangeLockRequestCB *pBRLRequestCB,
4531                        IN BOOL bWow64,
4532                        IN DWORD ResultBufferLength,
4533                        IN OUT AFSCommResult **ResultCB)
4534 {
4535     AFSByteRangeLockResultCB *pResultCB = NULL;
4536     LARGE_INTEGER ProcessId;
4537     DWORD       Length;
4538     cm_scache_t *scp = NULL;
4539     cm_fid_t    Fid;
4540     afs_uint32  code;
4541     cm_req_t    req;
4542     cm_key_t    key;
4543     DWORD       i;
4544     DWORD       status;
4545
4546     ProcessId.QuadPart = pBRLRequestCB->ProcessId;
4547
4548     RDR_InitReq(&req);
4549     if ( bWow64 )
4550         req.flags |= CM_REQ_WOW64;
4551
4552     osi_Log4(afsd_logp, "RDR_ByteRangeLockSync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4553               FileId.Cell, FileId.Volume,
4554               FileId.Vnode, FileId.Unique);
4555     osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
4556              ProcessId.HighPart, ProcessId.LowPart);
4557
4558     Length = sizeof( AFSByteRangeLockResultCB) + ((pBRLRequestCB->Count - 1) * sizeof(AFSByteRangeLockResult));
4559     if (Length > ResultBufferLength) {
4560         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult));
4561         if (!(*ResultCB))
4562             return;
4563         memset( *ResultCB, 0, sizeof(AFSCommResult));
4564         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
4565         return;
4566     }
4567
4568     *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
4569     if (!(*ResultCB))
4570         return;
4571     memset( *ResultCB, '\0', Length + sizeof( AFSCommResult) );
4572     (*ResultCB)->ResultBufferLength = Length;
4573
4574     pResultCB = (AFSByteRangeLockResultCB *)(*ResultCB)->ResultData;
4575     pResultCB->FileId = FileId;
4576     pResultCB->Count = pBRLRequestCB->Count;
4577
4578     /* Allocate the extents from the buffer package */
4579     Fid.cell = FileId.Cell;
4580     Fid.volume = FileId.Volume;
4581     Fid.vnode = FileId.Vnode;
4582     Fid.unique = FileId.Unique;
4583     Fid.hash = FileId.Hash;
4584
4585     code = cm_GetSCache(&Fid, &scp, userp, &req);
4586     if (code) {
4587         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4588         (*ResultCB)->ResultStatus = status;
4589         (*ResultCB)->ResultBufferLength = 0;
4590         osi_Log2(afsd_logp, "RDR_ByteRangeLockSync cm_GetSCache FID failure code=0x%x status=0x%x",
4591                   code, status);
4592         return;
4593     }
4594
4595     lock_ObtainWrite(&scp->rw);
4596
4597     /* start by looking up the file's end */
4598     code = cm_SyncOp(scp, NULL, userp, &req, 0,
4599                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4600     if (code) {
4601         lock_ReleaseWrite(&scp->rw);
4602         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4603         (*ResultCB)->ResultStatus = status;
4604         (*ResultCB)->ResultBufferLength = 0;
4605         osi_Log3(afsd_logp, "RDR_ByteRangeLockSync cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
4606                  scp, code, status);
4607         return;
4608     }
4609
4610     /* the scp is now locked and current */
4611     key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
4612
4613     for ( i=0; i<pBRLRequestCB->Count; i++ ) {
4614         pResultCB->Result[i].LockType = pBRLRequestCB->Request[i].LockType;
4615         pResultCB->Result[i].Offset = pBRLRequestCB->Request[i].Offset;
4616         pResultCB->Result[i].Length = pBRLRequestCB->Request[i].Length;
4617
4618         code = cm_Lock(scp,
4619                        pBRLRequestCB->Request[i].LockType == AFS_BYTE_RANGE_LOCK_TYPE_SHARED,
4620                        pBRLRequestCB->Request[i].Offset,
4621                        pBRLRequestCB->Request[i].Length,
4622                        key, 0, userp, &req, NULL);
4623
4624         if (code) {
4625             osi_Log4(afsd_logp, "RDR_ByteRangeLockSync FAILURE code 0x%x type 0x%u offset 0x%x:%x",
4626                      code,
4627                      pBRLRequestCB->Request[i].LockType,
4628                      pBRLRequestCB->Request[i].Offset.HighPart,
4629                      pBRLRequestCB->Request[i].Offset.LowPart);
4630             osi_Log2(afsd_logp, "... length 0x%x:%x",
4631                      pBRLRequestCB->Request[i].Length.HighPart,
4632                      pBRLRequestCB->Request[i].Length.LowPart);
4633         }
4634
4635         switch (code) {
4636         case 0:
4637             pResultCB->Result[i].Status = 0;
4638             break;
4639         case CM_ERROR_WOULDBLOCK:
4640             pResultCB->Result[i].Status = STATUS_FILE_LOCK_CONFLICT;
4641             break;
4642         default:
4643             pResultCB->Result[i].Status = STATUS_LOCK_NOT_GRANTED;
4644         }
4645     }
4646
4647     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4648     lock_ReleaseWrite(&scp->rw);
4649     cm_ReleaseSCache(scp);
4650
4651     (*ResultCB)->ResultStatus = 0;
4652     osi_Log0(afsd_logp, "RDR_ByteRangeLockSync SUCCESS");
4653     return;
4654 }
4655
4656 void
4657 RDR_ByteRangeUnlock( IN cm_user_t     *userp,
4658                      IN AFSFileID     FileId,
4659                      IN AFSByteRangeUnlockRequestCB *pBRURequestCB,
4660                      IN BOOL bWow64,
4661                      IN DWORD ResultBufferLength,
4662                      IN OUT AFSCommResult **ResultCB)
4663 {
4664     AFSByteRangeUnlockResultCB *pResultCB = NULL;
4665     LARGE_INTEGER ProcessId;
4666     DWORD       Length;
4667     cm_scache_t *scp = NULL;
4668     cm_fid_t    Fid;
4669     afs_uint32  code;
4670     cm_req_t    req;
4671     cm_key_t    key;
4672     DWORD       i;
4673     DWORD       status;
4674
4675     ProcessId.QuadPart = pBRURequestCB->ProcessId;
4676
4677     RDR_InitReq(&req);
4678     if ( bWow64 )
4679         req.flags |= CM_REQ_WOW64;
4680
4681     osi_Log4(afsd_logp, "RDR_ByteRangeUnlock File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4682               FileId.Cell, FileId.Volume,
4683               FileId.Vnode, FileId.Unique);
4684     osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
4685              ProcessId.HighPart, ProcessId.LowPart);
4686
4687     Length = sizeof( AFSByteRangeUnlockResultCB) + ((pBRURequestCB->Count - 1) * sizeof(AFSByteRangeLockResult));
4688     if (Length > ResultBufferLength) {
4689         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult));
4690         if (!(*ResultCB))
4691             return;
4692         memset( *ResultCB, 0, sizeof(AFSCommResult));
4693         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
4694         return;
4695     }
4696
4697     *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
4698     if (!(*ResultCB))
4699         return;
4700     memset( *ResultCB, '\0', Length + sizeof( AFSCommResult) );
4701     (*ResultCB)->ResultBufferLength = Length;
4702
4703     pResultCB = (AFSByteRangeUnlockResultCB *)(*ResultCB)->ResultData;
4704     pResultCB->Count = pBRURequestCB->Count;
4705
4706     /* Allocate the extents from the buffer package */
4707     Fid.cell = FileId.Cell;
4708     Fid.volume = FileId.Volume;
4709     Fid.vnode = FileId.Vnode;
4710     Fid.unique = FileId.Unique;
4711     Fid.hash = FileId.Hash;
4712
4713     code = cm_GetSCache(&Fid, &scp, userp, &req);
4714     if (code) {
4715         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4716         (*ResultCB)->ResultStatus = status;
4717         (*ResultCB)->ResultBufferLength = 0;
4718         osi_Log2(afsd_logp, "RDR_ByteRangeUnlock cm_GetSCache FID failure code=0x%x status=0x%x",
4719                   code, status);
4720         return;
4721     }
4722
4723     lock_ObtainWrite(&scp->rw);
4724
4725     /* start by looking up the file's end */
4726     code = cm_SyncOp(scp, NULL, userp, &req, 0,
4727                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4728     if (code) {
4729         lock_ReleaseWrite(&scp->rw);
4730         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4731         (*ResultCB)->ResultStatus = status;
4732         (*ResultCB)->ResultBufferLength = 0;
4733         osi_Log3(afsd_logp, "RDR_ByteRangeUnlock cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
4734                  scp, code, status);
4735         return;
4736     }
4737
4738     /* the scp is now locked and current */
4739     key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
4740
4741     for ( i=0; i<pBRURequestCB->Count; i++ ) {
4742         pResultCB->Result[i].LockType = pBRURequestCB->Request[i].LockType;
4743         pResultCB->Result[i].Offset = pBRURequestCB->Request[i].Offset;
4744         pResultCB->Result[i].Length = pBRURequestCB->Request[i].Length;
4745
4746         code = cm_Unlock(scp,
4747                          pBRURequestCB->Request[i].LockType == AFS_BYTE_RANGE_LOCK_TYPE_SHARED,
4748                          pBRURequestCB->Request[i].Offset,
4749                          pBRURequestCB->Request[i].Length,
4750                          key, CM_UNLOCK_FLAG_MATCH_RANGE, userp, &req);
4751
4752         if (code) {
4753             osi_Log4(afsd_logp, "RDR_ByteRangeUnlock FAILURE code 0x%x type 0x%u offset 0x%x:%x",
4754                      code, pBRURequestCB->Request[i].LockType,
4755                      pBRURequestCB->Request[i].Offset.HighPart,
4756                      pBRURequestCB->Request[i].Offset.LowPart);
4757             osi_Log2(afsd_logp, "... length 0x%x:%x",
4758                      pBRURequestCB->Request[i].Length.HighPart,
4759                      pBRURequestCB->Request[i].Length.LowPart);
4760         }
4761         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4762         pResultCB->Result[i].Status = status;
4763     }
4764
4765     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4766     lock_ReleaseWrite(&scp->rw);
4767     cm_ReleaseSCache(scp);
4768
4769     (*ResultCB)->ResultStatus = 0;
4770     osi_Log0(afsd_logp, "RDR_ByteRangeUnlock SUCCESS");
4771     return;
4772 }
4773
4774 void
4775 RDR_ByteRangeUnlockAll( IN cm_user_t     *userp,
4776                         IN AFSFileID     FileId,
4777                         IN AFSByteRangeUnlockRequestCB *pBRURequestCB,
4778                         IN BOOL bWow64,
4779                         IN DWORD ResultBufferLength,
4780                         IN OUT AFSCommResult **ResultCB)
4781 {
4782     AFSByteRangeUnlockResultCB *pResultCB = NULL;
4783     LARGE_INTEGER ProcessId;
4784     cm_scache_t *scp = NULL;
4785     cm_fid_t    Fid;
4786     afs_uint32  code;
4787     cm_req_t    req;
4788     cm_key_t    key;
4789     DWORD       status;
4790
4791     ProcessId.QuadPart = pBRURequestCB->ProcessId;
4792
4793     RDR_InitReq(&req);
4794     if ( bWow64 )
4795         req.flags |= CM_REQ_WOW64;
4796
4797     osi_Log4(afsd_logp, "RDR_ByteRangeUnlockAll File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4798               FileId.Cell, FileId.Volume,
4799               FileId.Vnode, FileId.Unique);
4800     osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
4801              ProcessId.HighPart, ProcessId.LowPart);
4802
4803     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
4804     if (!(*ResultCB))
4805         return;
4806     memset( *ResultCB, '\0', sizeof( AFSCommResult));
4807     (*ResultCB)->ResultBufferLength = 0;
4808
4809     /* Allocate the extents from the buffer package */
4810     Fid.cell = FileId.Cell;
4811     Fid.volume = FileId.Volume;
4812     Fid.vnode = FileId.Vnode;
4813     Fid.unique = FileId.Unique;
4814     Fid.hash = FileId.Hash;
4815
4816     code = cm_GetSCache(&Fid, &scp, userp, &req);
4817     if (code) {
4818         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4819         (*ResultCB)->ResultStatus = status;
4820         (*ResultCB)->ResultBufferLength = 0;
4821         osi_Log2(afsd_logp, "RDR_ByteRangeUnlockAll cm_GetSCache FID failure code=0x%x status=0x%x",
4822                   code, status);
4823         return;
4824     }
4825
4826     lock_ObtainWrite(&scp->rw);
4827
4828     /* start by looking up the file's end */
4829     code = cm_SyncOp(scp, NULL, userp, &req, 0,
4830                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4831     if (code) {
4832         lock_ReleaseWrite(&scp->rw);
4833         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4834         (*ResultCB)->ResultStatus = status;
4835         (*ResultCB)->ResultBufferLength = 0;
4836         osi_Log3(afsd_logp, "RDR_ByteRangeUnlockAll cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
4837                  scp, code, status);
4838         return;
4839     }
4840
4841     /* the scp is now locked and current */
4842     key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
4843
4844     code = cm_UnlockByKey(scp, key, 0, userp, &req);
4845
4846     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
4847     lock_ReleaseWrite(&scp->rw);
4848     cm_ReleaseSCache(scp);
4849
4850     smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4851     (*ResultCB)->ResultStatus = status;
4852
4853     if (code)
4854         osi_Log1(afsd_logp, "RDR_ByteRangeUnlockAll FAILURE code 0x%x", code);
4855     else
4856         osi_Log0(afsd_logp, "RDR_ByteRangeUnlockAll SUCCESS");
4857     return;
4858
4859 }
4860
4861 void
4862 RDR_GetVolumeInfo( IN cm_user_t     *userp,
4863                    IN AFSFileID     FileId,
4864                    IN BOOL bWow64,
4865                    IN DWORD ResultBufferLength,
4866                    IN OUT AFSCommResult **ResultCB)
4867 {
4868     AFSVolumeInfoCB *pResultCB = NULL;
4869     DWORD       Length;
4870     cm_scache_t *scp = NULL;
4871     cm_volume_t *volp = NULL;
4872     cm_vol_state_t *volstatep = NULL;
4873     afs_uint32   volType;
4874     cm_cell_t   *cellp = NULL;
4875     cm_fid_t    Fid;
4876     afs_uint32  code;
4877     cm_req_t    req;
4878     DWORD       status;
4879     FILETIME ft = {0x832cf000, 0x01abfcc4}; /* October 1, 1982 00:00:00 +0600 */
4880
4881     char volName[32]="(unknown)";
4882     char offLineMsg[256]="server temporarily inaccessible";
4883     char motd[256]="server temporarily inaccessible";
4884     cm_conn_t *connp;
4885     AFSFetchVolumeStatus volStat;
4886     char *Name;
4887     char *OfflineMsg;
4888     char *MOTD;
4889     struct rx_connection * rxconnp;
4890
4891     RDR_InitReq(&req);
4892     if ( bWow64 )
4893         req.flags |= CM_REQ_WOW64;
4894
4895     osi_Log4(afsd_logp, "RDR_GetVolumeInfo File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4896              FileId.Cell, FileId.Volume,
4897              FileId.Vnode, FileId.Unique);
4898
4899     Length = sizeof( AFSCommResult) + sizeof(AFSVolumeInfoCB);
4900     if (sizeof(AFSVolumeInfoCB) > ResultBufferLength) {
4901         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
4902         if (!(*ResultCB))
4903             return;
4904         memset( *ResultCB, 0, sizeof(AFSCommResult));
4905         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
4906         return;
4907     }
4908
4909     *ResultCB = (AFSCommResult *)malloc( Length );
4910     if (!(*ResultCB))
4911         return;
4912     memset( *ResultCB, '\0', Length );
4913     (*ResultCB)->ResultBufferLength = sizeof(AFSVolumeInfoCB);
4914     pResultCB = (AFSVolumeInfoCB *)(*ResultCB)->ResultData;
4915
4916     /* Allocate the extents from the buffer package */
4917     if (FileId.Cell != 0) {
4918         Fid.cell = FileId.Cell;
4919         Fid.volume = FileId.Volume;
4920         Fid.vnode = FileId.Vnode;
4921         Fid.unique = FileId.Unique;
4922         Fid.hash = FileId.Hash;
4923
4924         code = cm_GetSCache(&Fid, &scp, userp, &req);
4925         if (code) {
4926             smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4927             (*ResultCB)->ResultStatus = status;
4928             (*ResultCB)->ResultBufferLength = 0;
4929             osi_Log2(afsd_logp, "RDR_GetVolumeInfo cm_GetSCache FID failure code=0x%x status=0x%x",
4930                       code, status);
4931             return;
4932         }
4933     } else {
4934         (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
4935         osi_Log0(afsd_logp, "RDR_GetVolumeInfo Object Name Invalid - Cell = 0");
4936         return;
4937     }
4938     lock_ObtainWrite(&scp->rw);
4939
4940     /* start by looking up the file's end */
4941     code = cm_SyncOp(scp, NULL, userp, &req, 0,
4942                       CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
4943     if (code) {
4944         lock_ReleaseWrite(&scp->rw);
4945         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4946         (*ResultCB)->ResultStatus = status;
4947         (*ResultCB)->ResultBufferLength = 0;
4948         osi_Log3(afsd_logp, "RDR_GetVolumeInfo cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
4949                  scp, code, status);
4950         return;
4951     }
4952
4953     /* Fake for now */
4954     pResultCB->SectorsPerAllocationUnit = 1;
4955     pResultCB->BytesPerSector = 1024;
4956
4957     pResultCB->CellID = scp->fid.cell;
4958     pResultCB->VolumeID = scp->fid.volume;
4959     pResultCB->Characteristics = FILE_REMOTE_DEVICE;
4960     pResultCB->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK |
4961         FILE_SUPPORTS_REPARSE_POINTS;
4962
4963     if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
4964          scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
4965     {
4966         pResultCB->TotalAllocationUnits.QuadPart = 100;
4967         memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
4968
4969         pResultCB->AvailableAllocationUnits.QuadPart = 0;
4970         pResultCB->Characteristics |= FILE_READ_ONLY_DEVICE;
4971
4972         pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( "Freelance.Local.Root", -1, pResultCB->VolumeLabel,
4973                                                        (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
4974         if ( pResultCB->VolumeLabelLength )
4975             pResultCB->VolumeLabelLength--;
4976     } else {
4977         memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
4978
4979         volp = cm_GetVolumeByFID(&scp->fid);
4980         if (!volp) {
4981             code = CM_ERROR_NOSUCHVOLUME;
4982             goto _done;
4983         }
4984         volstatep = cm_VolumeStateByID(volp, scp->fid.volume);
4985         volType = cm_VolumeType(volp, scp->fid.volume);
4986
4987         pResultCB->Characteristics |= ((volType == ROVOL || volType == BACKVOL) ? FILE_READ_ONLY_DEVICE : 0);
4988
4989         Name = volName;
4990         OfflineMsg = offLineMsg;
4991         MOTD = motd;
4992         lock_ReleaseWrite(&scp->rw);
4993         do {
4994             code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
4995             if (code) continue;
4996
4997             rxconnp = cm_GetRxConn(connp);
4998             code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
4999                                          &volStat, &Name, &OfflineMsg, &MOTD);
5000             rx_PutConnection(rxconnp);
5001
5002         } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
5003         code = cm_MapRPCError(code, &req);
5004         if (code == 0) {
5005             pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
5006             pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
5007
5008             pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( Name, -1, pResultCB->VolumeLabel,
5009                                                            (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
5010         } else {
5011             pResultCB->TotalAllocationUnits.QuadPart = 0x7FFFFFFF;
5012             pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
5013
5014             pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( volp->namep, -1, pResultCB->VolumeLabel,
5015                                                            (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
5016             code = 0;
5017         }
5018         if ( pResultCB->VolumeLabelLength )
5019             pResultCB->VolumeLabelLength--;
5020
5021         lock_ObtainWrite(&scp->rw);
5022     }
5023     pResultCB->VolumeLabelLength *= sizeof(WCHAR);  /* convert to bytes from chars */
5024
5025     cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
5026
5027   _done:
5028     lock_ReleaseWrite(&scp->rw);
5029     if (volp)
5030        cm_PutVolume(volp);
5031     cm_ReleaseSCache(scp);
5032
5033     smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5034     (*ResultCB)->ResultStatus = status;
5035     osi_Log0(afsd_logp, "RDR_GetVolumeInfo SUCCESS");
5036     return;
5037 }
5038
5039 void
5040 RDR_HoldFid( IN cm_user_t     *userp,
5041              IN AFSHoldFidRequestCB * pHoldFidCB,
5042              IN BOOL bFast,
5043              IN DWORD ResultBufferLength,
5044              IN OUT AFSCommResult **ResultCB)
5045 {
5046     AFSHoldFidResultCB *pResultCB = NULL;
5047     DWORD       index;
5048     DWORD       Length;
5049     cm_req_t    req;
5050
5051     RDR_InitReq(&req);
5052
5053     osi_Log1(afsd_logp, "RDR_HoldFid Count=%u", pHoldFidCB->Count);
5054
5055     Length = sizeof(AFSHoldFidResultCB) + (pHoldFidCB->Count-1) * sizeof(AFSFidResult);
5056     if (Length > ResultBufferLength) {
5057         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
5058         if (!(*ResultCB))
5059             return;
5060         memset( *ResultCB, 0, sizeof(AFSCommResult));
5061         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5062         return;
5063     }
5064     *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
5065     if (!(*ResultCB))
5066         return;
5067     memset( *ResultCB, '\0', Length );
5068     (*ResultCB)->ResultBufferLength = Length;
5069     pResultCB = (AFSHoldFidResultCB *)(*ResultCB)->ResultData;
5070
5071     for ( index = 0; index < pHoldFidCB->Count; index++ )
5072     {
5073         cm_scache_t *scp = NULL;
5074         cm_fid_t    Fid;
5075
5076         Fid.cell   = pResultCB->Result[index].FileID.Cell   = pHoldFidCB->FileID[index].Cell;
5077         Fid.volume = pResultCB->Result[index].FileID.Volume = pHoldFidCB->FileID[index].Volume;
5078         Fid.vnode  = pResultCB->Result[index].FileID.Vnode  = pHoldFidCB->FileID[index].Vnode;
5079         Fid.unique = pResultCB->Result[index].FileID.Unique = pHoldFidCB->FileID[index].Unique;
5080         Fid.hash   = pResultCB->Result[index].FileID.Hash   = pHoldFidCB->FileID[index].Hash;
5081
5082         osi_Log4( afsd_logp,
5083                   "RDR_HoldFid File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5084                   Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
5085
5086         scp = cm_FindSCache(&Fid);
5087         if (scp) {
5088             RDR_FlagScpInUse( scp, FALSE );
5089             cm_ReleaseSCache(scp);
5090         }
5091         pResultCB->Result[index].Status = 0;
5092     }
5093
5094     (*ResultCB)->ResultStatus = 0;
5095     osi_Log0(afsd_logp, "RDR_HoldFid SUCCESS");
5096     return;
5097 }
5098
5099 void
5100 RDR_ReleaseFid( IN cm_user_t     *userp,
5101                 IN AFSReleaseFidRequestCB * pReleaseFidCB,
5102                 IN BOOL bFast,
5103                 IN DWORD ResultBufferLength,
5104                 IN OUT AFSCommResult **ResultCB)
5105 {
5106     AFSReleaseFidResultCB *pResultCB = NULL;
5107     DWORD       index;
5108     DWORD       Length;
5109     cm_req_t    req;
5110
5111     RDR_InitReq(&req);
5112
5113     osi_Log1(afsd_logp, "RDR_ReleaseFid Count=%u", pReleaseFidCB->Count);
5114
5115     Length = sizeof(AFSReleaseFidResultCB) + (pReleaseFidCB->Count ? pReleaseFidCB->Count-1 : 0) * sizeof(AFSFidResult);
5116     if (Length > ResultBufferLength) {
5117         *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
5118         if (!(*ResultCB))
5119             return;
5120         memset( *ResultCB, 0, sizeof(AFSCommResult));
5121         (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5122         return;
5123     }
5124     *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
5125     if (!(*ResultCB))
5126         return;
5127     memset( *ResultCB, '\0', Length );
5128     (*ResultCB)->ResultBufferLength = Length;
5129     pResultCB = (AFSReleaseFidResultCB *)(*ResultCB)->ResultData;
5130
5131     for ( index = 0; index < pReleaseFidCB->Count; index++ )
5132     {
5133         cm_scache_t *scp = NULL;
5134         cm_fid_t    Fid;
5135
5136         Fid.cell   = pResultCB->Result[index].FileID.Cell   = pReleaseFidCB->FileID[index].Cell;
5137         Fid.volume = pResultCB->Result[index].FileID.Volume = pReleaseFidCB->FileID[index].Volume;
5138         Fid.vnode  = pResultCB->Result[index].FileID.Vnode  = pReleaseFidCB->FileID[index].Vnode;
5139         Fid.unique = pResultCB->Result[index].FileID.Unique = pReleaseFidCB->FileID[index].Unique;
5140         Fid.hash   = pResultCB->Result[index].FileID.Hash   = pReleaseFidCB->FileID[index].Hash;
5141
5142         osi_Log4( afsd_logp,
5143                   "RDR_ReleaseFid File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5144                   Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
5145
5146         scp = cm_FindSCache(&Fid);
5147         if (scp) {
5148             lock_ObtainWrite(&scp->rw);
5149             scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
5150             lock_ReleaseWrite(&scp->rw);
5151
5152             cm_ReleaseSCache(scp);
5153         }
5154         pResultCB->Result[index].Status = 0;
5155     }
5156     pResultCB->Count = pReleaseFidCB->Count;
5157
5158     (*ResultCB)->ResultStatus = 0;
5159     osi_Log0(afsd_logp, "RDR_ReleaseFid SUCCESS");
5160     return;
5161 }
5162
5163 /*
5164  * The redirector makes several assumptions regarding the
5165  * SRVSVC and WKSSVC pipes transactions.  First, the interface
5166  * versions are those indicated below.  Secondly, the encoding
5167  * will be performed using NDR version 2.  These assumptions
5168  * may not hold in the future and end-to-end MSRPC Bind
5169  * negotiations may need to be supported.  Of course, these
5170  * are the only interface versions that are supported by the
5171  * service.
5172  */
5173 #define MSRPC_PIPE_PREFIX L".\\"
5174
5175 static const UUID MSRPC_SRVSVC_UUID = {0x4B324FC8, 0x1670, 0x01D3,
5176                                        {0x12, 0x78, 0x5A, 0x47, 0xBF, 0x6E, 0xE1, 0x88}};
5177 #define MSRPC_SRVSVC_NAME L"PIPE\\SRVSVC"
5178 #define MSRPC_SRVSVC_VERS 3
5179
5180 static const UUID MSRPC_WKSSVC_UUID = {0x6BFFD098, 0xA112, 0x3610,
5181                                        {0x98, 0x33, 0x46, 0xC3, 0xF8, 0x7E, 0x34, 0x5A}};
5182 #define MSRPC_WKSSVC_NAME L"PIPE\\WKSSVC"
5183 #define MSRPC_WKSSVC_VERS 1
5184
5185 static const UUID MSRPC_NDR_UUID = {0x8A885D04, 0x1CEB, 0x11C9,
5186                                     {0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60}};
5187 #define MSRPC_NDR_NAME    L"NDR"
5188 #define MSRPC_NDR_VERS    2
5189
5190 extern RPC_IF_HANDLE srvsvc_v3_0_s_ifspec;
5191 extern RPC_IF_HANDLE wkssvc_v1_0_s_ifspec;
5192
5193 void
5194 RDR_PipeOpen( IN cm_user_t *userp,
5195               IN AFSFileID  ParentId,
5196               IN WCHAR     *Name,
5197               IN DWORD      NameLength,
5198               IN AFSPipeOpenCloseRequestCB *pPipe_CB,
5199               IN BOOL bWow64,
5200               IN DWORD ResultBufferLength,
5201               IN OUT AFSCommResult **ResultCB)
5202 {
5203     cm_fid_t    ParentFid;
5204     cm_fid_t    RootFid;
5205
5206     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5207     if (!(*ResultCB))
5208         return;
5209
5210     memset( *ResultCB,
5211             '\0',
5212             sizeof( AFSCommResult));
5213
5214     /* Get the active directory */
5215     ParentFid.cell = ParentId.Cell;
5216     ParentFid.volume = ParentId.Volume;
5217     ParentFid.vnode = ParentId.Vnode;
5218     ParentFid.unique = ParentId.Unique;
5219     ParentFid.hash = ParentId.Hash;
5220
5221     /* Get the root directory */
5222     RootFid.cell = pPipe_CB->RootId.Cell;
5223     RootFid.volume = pPipe_CB->RootId.Volume;
5224     RootFid.vnode = pPipe_CB->RootId.Vnode;
5225     RootFid.unique = pPipe_CB->RootId.Unique;
5226     RootFid.hash = pPipe_CB->RootId.Hash;
5227
5228     /* Create the pipe index */
5229     (*ResultCB)->ResultStatus =
5230       RDR_SetupPipe( pPipe_CB->RequestId, &ParentFid, &RootFid,
5231                      Name, NameLength, userp);
5232     return;
5233 }
5234
5235
5236 void
5237 RDR_PipeClose( IN cm_user_t *userp,
5238                IN AFSFileID  ParentId,
5239                IN AFSPipeOpenCloseRequestCB *pPipe_CB,
5240                IN BOOL bWow64,
5241                IN DWORD ResultBufferLength,
5242                IN OUT AFSCommResult **ResultCB)
5243 {
5244     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5245     if (!(*ResultCB))
5246         return;
5247
5248     memset( *ResultCB,
5249             '\0',
5250             sizeof( AFSCommResult));
5251
5252     /* Cleanup the pipe index */
5253     RDR_CleanupPipe(pPipe_CB->RequestId);
5254
5255     return;
5256 }
5257
5258
5259 void
5260 RDR_PipeWrite( IN cm_user_t *userp,
5261                IN AFSFileID  ParentId,
5262                IN AFSPipeIORequestCB *pPipe_CB,
5263                IN BYTE *pPipe_Data,
5264                IN BOOL bWow64,
5265                IN DWORD ResultBufferLength,
5266                IN OUT AFSCommResult **ResultCB)
5267 {
5268     AFSPipeIOResultCB *pResultCB;
5269     cm_scache_t *dscp = NULL;
5270     afs_uint32  code;
5271     cm_req_t    req;
5272     DWORD       status;
5273
5274     RDR_InitReq(&req);
5275     if ( bWow64 )
5276         req.flags |= CM_REQ_WOW64;
5277
5278     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5279     if (!(*ResultCB))
5280         return;
5281
5282     memset( *ResultCB,
5283             '\0',
5284             sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5285
5286     pResultCB = (AFSPipeIOResultCB *)(*ResultCB)->ResultData;
5287
5288     code = RDR_Pipe_Write( pPipe_CB->RequestId, pPipe_CB->BufferLength, pPipe_Data, &req, userp);
5289     if (code) {
5290         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5291         (*ResultCB)->ResultStatus = status;
5292         return;
5293     }
5294
5295     pResultCB->BytesProcessed = pPipe_CB->BufferLength;
5296     (*ResultCB)->ResultBufferLength = sizeof( AFSPipeIOResultCB);
5297 }
5298
5299
5300 void
5301 RDR_PipeRead( IN cm_user_t *userp,
5302               IN AFSFileID  ParentId,
5303               IN AFSPipeIORequestCB *pPipe_CB,
5304               IN BOOL bWow64,
5305               IN DWORD ResultBufferLength,
5306               IN OUT AFSCommResult **ResultCB)
5307 {
5308     BYTE *pPipe_Data;
5309     cm_scache_t *dscp = NULL;
5310     afs_uint32  code;
5311     cm_req_t    req;
5312     DWORD       status;
5313
5314     RDR_InitReq(&req);
5315     if ( bWow64 )
5316         req.flags |= CM_REQ_WOW64;
5317
5318     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
5319     if (!(*ResultCB))
5320         return;
5321
5322     memset( *ResultCB,
5323             '\0',
5324             sizeof( AFSCommResult));
5325
5326     pPipe_Data = (BYTE *)(*ResultCB)->ResultData;
5327
5328     code = RDR_Pipe_Read( pPipe_CB->RequestId, ResultBufferLength, pPipe_Data,
5329                           &(*ResultCB)->ResultBufferLength, &req, userp);
5330     if (code) {
5331         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5332         (*ResultCB)->ResultStatus = status;
5333         return;
5334     }
5335 }
5336
5337
5338 void
5339 RDR_PipeSetInfo( IN cm_user_t *userp,
5340                  IN AFSFileID  ParentId,
5341                  IN AFSPipeInfoRequestCB *pPipeInfo_CB,
5342                  IN BYTE *pPipe_Data,
5343                  IN BOOL bWow64,
5344                  IN DWORD ResultBufferLength,
5345                  IN OUT AFSCommResult **ResultCB)
5346 {
5347     cm_scache_t *dscp = NULL;
5348     cm_req_t    req;
5349     DWORD       status;
5350
5351     RDR_InitReq(&req);
5352     if ( bWow64 )
5353         req.flags |= CM_REQ_WOW64;
5354
5355     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5356     if (!(*ResultCB))
5357         return;
5358
5359     memset( *ResultCB,
5360             '\0',
5361             sizeof( AFSCommResult));
5362
5363     status = RDR_Pipe_SetInfo( pPipeInfo_CB->RequestId, pPipeInfo_CB->InformationClass,
5364                                pPipeInfo_CB->BufferLength, pPipe_Data, &req, userp);
5365
5366     (*ResultCB)->ResultStatus = status;
5367 }
5368
5369
5370 void
5371 RDR_PipeQueryInfo( IN cm_user_t *userp,
5372                    IN AFSFileID  ParentId,
5373                    IN AFSPipeInfoRequestCB *pPipeInfo_CB,
5374                    IN BOOL bWow64,
5375                    IN DWORD ResultBufferLength,
5376                    IN OUT AFSCommResult **ResultCB)
5377 {
5378     BYTE *pPipe_Data;
5379     cm_scache_t *dscp = NULL;
5380     cm_req_t    req;
5381     DWORD       status;
5382
5383     RDR_InitReq(&req);
5384     if ( bWow64 )
5385         req.flags |= CM_REQ_WOW64;
5386
5387     *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
5388     if (!(*ResultCB))
5389         return;
5390
5391     memset( *ResultCB,
5392             '\0',
5393             sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5394
5395     pPipe_Data = (BYTE *)(*ResultCB)->ResultData;
5396
5397     status = RDR_Pipe_QueryInfo( pPipeInfo_CB->RequestId, pPipeInfo_CB->InformationClass,
5398                                  ResultBufferLength, pPipe_Data,
5399                                  &(*ResultCB)->ResultBufferLength, &req, userp);
5400
5401     (*ResultCB)->ResultStatus = status;
5402 }
5403
5404 void
5405 RDR_PipeTransceive( IN cm_user_t     *userp,
5406                     IN AFSFileID  ParentId,
5407                     IN AFSPipeIORequestCB *pPipe_CB,
5408                     IN BYTE *pPipe_InData,
5409                     IN BOOL bWow64,
5410                     IN DWORD ResultBufferLength,
5411                     IN OUT AFSCommResult **ResultCB)
5412 {
5413     /*
5414      * This function processes a Pipe Service request
5415      * that would normally be sent to a LAN Manager server
5416      * across an authenticated SMB-PIPE/MSRPC/SVC request
5417      * stack.  The request is being sent here because the
5418      * application (e.g., Explorer Shell or Common Control File
5419      * dialog) believes that because the UNC path it is
5420      * processing has specified a server name that is not
5421      * "." and that the Server is remote and that the Share
5422      * list cannot be obtained using the Network Provider
5423      * interface.
5424      *
5425      * The file system driver is faking the Bind-Ack response
5426      * to the MSRPC Bind request but cannot decode the NDR
5427      * encoded Pipe Service requests.  For that we will use
5428      * the service's MSRPC module.  However, unlike the SMB
5429      * server usage we must fake the MSRPC Bind exchange and
5430      * map the PipeName to an interface instead of using the
5431      * GUID specified in the MSRPC Bind request.
5432      *
5433      * None of the requests that are being processed by the
5434      * service require authentication.  As a result the userp
5435      * parameter will be ignored.
5436      *
5437      * Although there are dozens of Pipe Services, the only
5438      * ones that we are implementing are WKSSVC and SRVSVC.
5439      * These support NetShareEnum, NetShareGetInfo,
5440      * NetServerGetInfo, and NetWorkstaGetInfo which are
5441      * commonly queried by NET VIEW, the Explorer Shell,
5442      * and the Common Control File dialog.
5443      */
5444     BYTE *pPipe_OutData;
5445     cm_scache_t *dscp = NULL;
5446     afs_uint32  code;
5447     cm_req_t    req;
5448     DWORD       status;
5449     DWORD Length = ResultBufferLength + sizeof( AFSCommResult);
5450
5451     RDR_InitReq(&req);
5452     if ( bWow64 )
5453         req.flags |= CM_REQ_WOW64;
5454
5455     *ResultCB = (AFSCommResult *)malloc( Length);
5456     if (!(*ResultCB))
5457         return;
5458     memset( *ResultCB, '\0', Length );
5459
5460     code = RDR_Pipe_Write( pPipe_CB->RequestId, pPipe_CB->BufferLength, pPipe_InData, &req, userp);
5461     if (code) {
5462         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5463         osi_Log2( afsd_logp, "RDR_Pipe_Transceive Write FAILURE code=0x%x status=0x%x",
5464                   code, status);
5465         (*ResultCB)->ResultStatus = status;
5466         return;
5467     }
5468
5469     pPipe_OutData = (BYTE *)(*ResultCB)->ResultData;
5470     code = RDR_Pipe_Read( pPipe_CB->RequestId, ResultBufferLength, pPipe_OutData,
5471                           &(*ResultCB)->ResultBufferLength, &req, userp);
5472     if (code) {
5473         smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5474         osi_Log2( afsd_logp, "RDR_Pipe_Transceive Read FAILURE code=0x%x status=0x%x",
5475                   code, status);
5476         (*ResultCB)->ResultStatus = status;
5477         return;
5478     }
5479
5480     (*ResultCB)->ResultStatus = 0;
5481     osi_Log0(afsd_logp, "RDR_Pipe_Transceive SUCCESS");
5482 }