2 * Copyright (c) 2008 Secure Endpoints, Inc.
3 * Copyright (c) 2009-2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
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.
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.
32 #include <afsconfig.h>
33 #include <afs/param.h>
36 #define _WIN32_WINNT 0x0500
38 #define _CRT_SECURE_NO_DEPRECATE
39 #define _CRT_NON_CONFORMING_SWPRINTFS
40 #define INITGUID /* define AFS_AUTH_GUID_NO_PAG */
43 #define WIN32_NO_STATUS
53 #pragma warning(disable: 4005)
57 #include "..\\Common\\AFSUserDefines.h"
58 #include "..\\Common\\AFSUserStructs.h"
76 #include <RDRPrototypes.h>
80 static CHAR * RDR_extentBaseAddress = NULL;
83 RDR_InitReq(cm_req_t *reqp, BOOL bWow64)
86 reqp->flags |= CM_REQ_SOURCE_REDIR;
88 reqp->flags |= CM_REQ_WOW64;
92 RDR_fid2FID( cm_fid_t *fid, AFSFileID *FileId)
94 FileId->Cell = fid->cell;
95 FileId->Volume = fid->volume;
96 FileId->Vnode = fid->vnode;
97 FileId->Unique = fid->unique;
98 FileId->Hash = fid->hash;
102 RDR_FID2fid( AFSFileID *FileId, cm_fid_t *fid)
104 fid->cell = FileId->Cell;
105 fid->volume = FileId->Volume;
106 fid->vnode = FileId->Vnode;
107 fid->unique = FileId->Unique;
108 fid->hash = FileId->Hash;
112 RDR_SetInitParams( OUT AFSRedirectorInitInfo **ppRedirInitInfo, OUT DWORD * pRedirInitInfoLen )
114 extern char cm_CachePath[];
115 extern cm_config_data_t cm_data;
116 extern int smb_hideDotFiles;
117 size_t cm_CachePathLen = strlen(cm_CachePath);
119 DWORD TempPathLen = ExpandEnvironmentStringsW(L"%TEMP%", NULL, 0);
120 MEMORYSTATUSEX memStatus;
121 DWORD maxMemoryCacheSize;
123 memStatus.dwLength = sizeof(memStatus);
124 if (GlobalMemoryStatusEx(&memStatus)) {
126 * Use the memory extent interface in the afs redirector
127 * whenever the cache size is less than equal to 10% of
128 * physical memory. Do not use too much because this memory
129 * will be locked by the redirector so it can't be swapped
132 maxMemoryCacheSize = (DWORD)(memStatus.ullTotalPhys / 1024 / 10);
135 * If we can't determine the amount of physical memory
136 * in the system, be conservative and limit the use of
137 * memory extent interface to 64MB data caches.
139 maxMemoryCacheSize = 65536;
142 *pRedirInitInfoLen = (DWORD) (sizeof(AFSRedirectorInitInfo) + (cm_CachePathLen + TempPathLen) * sizeof(WCHAR));
143 *ppRedirInitInfo = (AFSRedirectorInitInfo *)malloc(*pRedirInitInfoLen);
144 (*ppRedirInitInfo)->Flags = smb_hideDotFiles ? AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES : 0;
145 (*ppRedirInitInfo)->Flags |= cm_shortNames ? 0 : AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES;
146 (*ppRedirInitInfo)->MaximumChunkLength = cm_data.chunkSize;
147 (*ppRedirInitInfo)->GlobalFileId.Cell = cm_data.rootFid.cell;
148 (*ppRedirInitInfo)->GlobalFileId.Volume = cm_data.rootFid.volume;
149 (*ppRedirInitInfo)->GlobalFileId.Vnode = cm_data.rootFid.vnode;
150 (*ppRedirInitInfo)->GlobalFileId.Unique = cm_data.rootFid.unique;
151 (*ppRedirInitInfo)->GlobalFileId.Hash = cm_data.rootFid.hash;
152 (*ppRedirInitInfo)->ExtentCount.QuadPart = cm_data.buf_nbuffers;
153 (*ppRedirInitInfo)->CacheBlockSize = cm_data.blockSize;
154 (*ppRedirInitInfo)->MaxPathLinkCount = MAX_FID_COUNT;
155 (*ppRedirInitInfo)->NameArrayLength = MAX_FID_COUNT;
156 if (cm_virtualCache || cm_data.bufferSize <= maxMemoryCacheSize) {
157 osi_Log0(afsd_logp, "RDR_SetInitParams Initializing Memory Extent Interface");
158 (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = (LONGLONG)cm_data.bufDataBaseAddress;
159 (*ppRedirInitInfo)->MemoryCacheLength.QuadPart = cm_data.bufEndOfData - cm_data.bufDataBaseAddress;
160 (*ppRedirInitInfo)->CacheFileNameLength = 0;
161 RDR_extentBaseAddress = cm_data.bufDataBaseAddress;
163 (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = 0;
164 (*ppRedirInitInfo)->MemoryCacheLength.QuadPart = 0;
165 (*ppRedirInitInfo)->CacheFileNameLength = (ULONG) (cm_CachePathLen * sizeof(WCHAR));
166 err = mbstowcs((*ppRedirInitInfo)->CacheFileName, cm_CachePath, (cm_CachePathLen + 1) *sizeof(WCHAR));
168 free(*ppRedirInitInfo);
169 osi_Log0(afsd_logp, "RDR_SetInitParams Invalid Object Name");
170 return STATUS_OBJECT_NAME_INVALID;
172 RDR_extentBaseAddress = cm_data.baseAddress;
174 (*ppRedirInitInfo)->DumpFileLocationOffset = FIELD_OFFSET(AFSRedirectorInitInfo, CacheFileName) + (*ppRedirInitInfo)->CacheFileNameLength;
175 (*ppRedirInitInfo)->DumpFileLocationLength = (TempPathLen - 1) * sizeof(WCHAR);
176 ExpandEnvironmentStringsW(L"%TEMP%",
177 (LPWSTR)(((PBYTE)(*ppRedirInitInfo)) + (*ppRedirInitInfo)->DumpFileLocationOffset),
180 osi_Log0(afsd_logp,"RDR_SetInitParams Success");
184 static wchar_t cname[MAX_COMPUTERNAME_LENGTH+1] = L"";
187 RDR_GetLocalSystemUser( void)
190 cm_user_t *userp = NULL;
192 if ( cname[0] == '\0') {
193 int len = MAX_COMPUTERNAME_LENGTH+1;
194 GetComputerNameW(cname, &len);
197 unp = smb_FindUserByName(NTSID_LOCAL_SYSTEM, cname, SMB_FLAG_CREATE);
198 lock_ObtainMutex(&unp->mx);
200 unp->userp = cm_NewUser();
201 unp->flags |= SMB_USERNAMEFLAG_SID;
202 lock_ReleaseMutex(&unp->mx);
205 smb_ReleaseUsername(unp);
208 userp = cm_rootUserp;
216 RDR_UserFromCommRequest( IN AFSCommRequest *RequestBuffer)
219 return RDR_UserFromAuthGroup( &RequestBuffer->AuthGroup);
223 RDR_UserFromAuthGroup( IN GUID *pGuid)
226 cm_user_t * userp = NULL;
227 RPC_WSTR UuidString = NULL;
229 if (UuidToStringW((UUID *)pGuid, &UuidString) != RPC_S_OK)
232 if ( cname[0] == '\0') {
233 int len = MAX_COMPUTERNAME_LENGTH+1;
234 GetComputerNameW(cname, &len);
238 unp = smb_FindUserByName(UuidString, cname, SMB_FLAG_CREATE);
239 lock_ObtainMutex(&unp->mx);
241 unp->userp = cm_NewUser();
242 memcpy(&unp->userp->authgroup, pGuid, sizeof(GUID));
244 unp->flags |= SMB_USERNAMEFLAG_SID;
245 lock_ReleaseMutex(&unp->mx);
248 smb_ReleaseUsername(unp);
252 userp = cm_rootUserp;
256 osi_Log2(afsd_logp, "RDR_UserFromCommRequest Guid %S userp = 0x%p",
257 osi_LogSaveStringW(afsd_logp, UuidString),
261 RpcStringFreeW(&UuidString);
267 RDR_ReleaseUser( IN cm_user_t *userp )
269 osi_Log1(afsd_logp, "RDR_ReleaseUser userp = 0x%p", userp);
270 cm_ReleaseUser(userp);
275 * RDR_FlagScpInUse flags the scp with CM_SCACHEFLAG_RDR_IN_USE
278 RDR_FlagScpInUse( IN cm_scache_t *scp, IN BOOL bLocked )
281 lock_ObtainWrite(&scp->rw);
283 lock_AssertWrite(&scp->rw);
284 scp->flags |= CM_SCACHEFLAG_RDR_IN_USE;
287 lock_ReleaseWrite(&scp->rw);
291 * Obtain the status information for the specified object using
292 * an inline bulk status rpc. cm_BPlusDirEnumBulkStatOne() will
293 * obtain current status for the directory object, the object
294 * which is the focus of the inquiry and as many other objects
295 * in the directory for which there are not callbacks registered
296 * since we are likely to be asked for other objects in the directory.
299 RDR_BulkStatLookup( cm_scache_t *dscp,
304 cm_direnum_t * enump = NULL;
308 code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
310 code = cm_BPlusDirEnumerate(dscp, userp, reqp, TRUE, NULL, TRUE, &enump);
312 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BPlusDirEnumerate failure code=0x%x",
317 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BeginDirOp failure code=0x%x",
323 code = cm_BPlusDirEnumBulkStatOne(enump, scp);
325 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BPlusDirEnumBulkStatOne failure code=0x%x",
328 cm_BPlusDirFreeEnumeration(enump);
335 #define RDR_POP_FOLLOW_MOUNTPOINTS 0x01
336 #define RDR_POP_EVALUATE_SYMLINKS 0x02
337 #define RDR_POP_WOW64 0x04
338 #define RDR_POP_NO_GETSTATUS 0x08
341 RDR_PopulateCurrentEntry( IN AFSDirEnumEntry * pCurrentEntry,
342 IN DWORD dwMaxEntryLength,
343 IN cm_scache_t * dscp,
344 IN cm_scache_t * scp,
345 IN cm_user_t * userp,
348 IN wchar_t * shortName,
350 IN afs_uint32 cmError,
351 OUT AFSDirEnumEntry **ppNextEntry,
352 OUT DWORD * pdwRemainingLength)
355 WCHAR * wname, *wtarget;
358 afs_uint32 code = 0, code2 = 0;
359 BOOL bMustFake = FALSE;
361 osi_Log5(afsd_logp, "RDR_PopulateCurrentEntry dscp=0x%p scp=0x%p name=%S short=%S flags=0x%x",
362 dscp, scp, osi_LogSaveStringW(afsd_logp, name),
363 osi_LogSaveStringW(afsd_logp, shortName), dwFlags);
364 osi_Log1(afsd_logp, "... maxLength=%d", dwMaxEntryLength);
366 if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
368 *ppNextEntry = pCurrentEntry;
369 if (pdwRemainingLength)
370 *pdwRemainingLength = dwMaxEntryLength;
371 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry Not Enough Room for Entry %d < %d",
372 dwMaxEntryLength, sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t));
373 return CM_ERROR_TOOBIG;
381 dwEntryLength = sizeof(AFSDirEnumEntry);
383 lock_ObtainWrite(&scp->rw);
384 if (dwFlags & RDR_POP_NO_GETSTATUS) {
385 if (!cm_HaveCallback(scp))
388 #ifdef AFS_FREELANCE_CLIENT
389 if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID) {
391 * If the FID is from the Freelance Local Root always perform
392 * a single item status check.
394 code = cm_SyncOp( scp, NULL, userp, reqp, 0,
395 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
397 lock_ReleaseWrite(&scp->rw);
398 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_SyncOp failed for scp=0x%p code=0x%x",
406 * For non-Freelance objects, check to see if we have current
407 * status information. If not, perform a bulk status lookup of multiple
408 * entries in order to reduce the number of RPCs issued to the file server.
410 if (cm_EAccesFindEntry(userp, &scp->fid))
412 else if (!cm_HaveCallback(scp)) {
413 lock_ReleaseWrite(&scp->rw);
414 code = RDR_BulkStatLookup(dscp, scp, userp, reqp);
416 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RDR_BulkStatLookup failed for scp=0x%p code=0x%x",
420 lock_ObtainWrite(&scp->rw);
422 * RDR_BulkStatLookup can succeed but it may be the case that there
423 * still is not valid status info. If we get this far, generate fake
426 if (!cm_HaveCallback(scp))
432 /* Populate the error code */
433 smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
435 /* Populate the real or fake data */
436 pCurrentEntry->FileId.Cell = scp->fid.cell;
437 pCurrentEntry->FileId.Volume = scp->fid.volume;
438 pCurrentEntry->FileId.Vnode = scp->fid.vnode;
439 pCurrentEntry->FileId.Unique = scp->fid.unique;
440 pCurrentEntry->FileId.Hash = scp->fid.hash;
442 pCurrentEntry->FileType = scp->fileType;
444 pCurrentEntry->DataVersion.QuadPart = scp->dataVersion;
446 if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
447 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {
448 cm_LargeSearchTimeFromUnixTime(&ft, MAX_AFS_UINT32);
450 cm_LargeSearchTimeFromUnixTime(&ft, scp->cbExpires);
452 pCurrentEntry->Expiration.LowPart = ft.dwLowDateTime;
453 pCurrentEntry->Expiration.HighPart = ft.dwHighDateTime;
456 /* 1969-12-31 23:59:59 +00 */
457 ft.dwHighDateTime = 0x19DB200;
458 ft.dwLowDateTime = 0x5BB78980;
460 cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
461 pCurrentEntry->CreationTime.LowPart = ft.dwLowDateTime;
462 pCurrentEntry->CreationTime.HighPart = ft.dwHighDateTime;
463 pCurrentEntry->LastAccessTime = pCurrentEntry->CreationTime;
464 pCurrentEntry->LastWriteTime = pCurrentEntry->CreationTime;
465 pCurrentEntry->ChangeTime = pCurrentEntry->CreationTime;
467 pCurrentEntry->EndOfFile = scp->length;
468 pCurrentEntry->AllocationSize = scp->length;
471 switch (scp->fileType) {
472 case CM_SCACHETYPE_DIRECTORY:
473 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
475 case CM_SCACHETYPE_MOUNTPOINT:
476 case CM_SCACHETYPE_INVALID:
477 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
479 case CM_SCACHETYPE_SYMLINK:
480 if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
481 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
483 pCurrentEntry->FileAttributes = SMB_ATTR_REPARSE_POINT;
486 /* if we get here we either have a normal file
487 * or we have a file for which we have never
488 * received status info. In this case, we can
489 * check the even/odd value of the entry's vnode.
490 * odd means it is to be treated as a directory
491 * and even means it is to be treated as a file.
493 if (scp->fid.vnode & 0x1)
494 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
496 pCurrentEntry->FileAttributes = SMB_ATTR_NORMAL;
499 pCurrentEntry->FileAttributes = smb_ExtAttributes(scp);
500 pCurrentEntry->EaSize = 0;
501 pCurrentEntry->Links = scp->linkCount;
503 len = wcslen(shortName);
504 wcsncpy(pCurrentEntry->ShortName, shortName, len);
505 pCurrentEntry->ShortNameLength = (CCHAR)(len * sizeof(WCHAR));
507 pCurrentEntry->FileNameOffset = sizeof(AFSDirEnumEntry);
509 wname = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->FileNameOffset);
510 wcsncpy(wname, name, len);
511 pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
513 osi_Log3(afsd_logp, "RDR_PopulateCurrentEntry scp=0x%p fileType=%d dv=%u",
514 scp, scp->fileType, (afs_uint32)scp->dataVersion);
516 if (!(dwFlags & RDR_POP_NO_GETSTATUS))
517 cm_SyncOpDone( scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
519 if ((dwFlags & RDR_POP_NO_GETSTATUS) || !cm_HaveCallback(scp)) {
520 pCurrentEntry->TargetNameOffset = 0;
521 pCurrentEntry->TargetNameLength = 0;
524 switch (scp->fileType) {
525 case CM_SCACHETYPE_MOUNTPOINT:
526 if (dwFlags & RDR_POP_FOLLOW_MOUNTPOINTS) {
527 if ((code2 = cm_ReadMountPoint(scp, userp, reqp)) == 0) {
528 cm_scache_t *targetScp = NULL;
530 pCurrentEntry->TargetNameOffset = pCurrentEntry->FileNameOffset + pCurrentEntry->FileNameLength;
531 len = strlen(scp->mountPointStringp);
532 wtarget = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->TargetNameOffset);
535 cch = MultiByteToWideChar( CP_UTF8, 0, scp->mountPointStringp,
538 len * sizeof(WCHAR));
540 mbstowcs(wtarget, scp->mountPointStringp, len);
542 pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * len);
544 code2 = cm_FollowMountPoint(scp, dscp, userp, reqp, &targetScp);
547 pCurrentEntry->TargetFileId.Cell = targetScp->fid.cell;
548 pCurrentEntry->TargetFileId.Volume = targetScp->fid.volume;
549 pCurrentEntry->TargetFileId.Vnode = targetScp->fid.vnode;
550 pCurrentEntry->TargetFileId.Unique = targetScp->fid.unique;
551 pCurrentEntry->TargetFileId.Hash = targetScp->fid.hash;
553 osi_Log4(afsd_logp, "RDR_PopulateCurrentEntry target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
554 pCurrentEntry->TargetFileId.Cell, pCurrentEntry->TargetFileId.Volume,
555 pCurrentEntry->TargetFileId.Vnode, pCurrentEntry->TargetFileId.Unique);
557 cm_ReleaseSCache(targetScp);
559 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_FollowMountPoint failed scp=0x%p code=0x%x",
563 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_ReadMountPoint failed scp=0x%p code=0x%x",
568 case CM_SCACHETYPE_SYMLINK:
569 case CM_SCACHETYPE_DFSLINK:
571 pCurrentEntry->TargetNameOffset = pCurrentEntry->FileNameOffset + pCurrentEntry->FileNameLength;
572 wtarget = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->TargetNameOffset);
574 if (dwFlags & RDR_POP_EVALUATE_SYMLINKS) {
577 code2 = cm_HandleLink(scp, userp, reqp);
579 mp = scp->mountPointStringp;
582 /* Strip off the msdfs: prefix from the target name for the file system */
583 if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
584 osi_Log0(afsd_logp, "RDR_PopulateCurrentEntry DFSLink Detected");
585 pCurrentEntry->FileType = scp->fileType;
587 if (!strncmp("msdfs:", mp, 6)) {
592 /* only send one slash to the redirector */
593 if (mp[0] == '\\' && mp[1] == '\\') {
598 cch = MultiByteToWideChar( CP_UTF8, 0, mp,
601 len * sizeof(WCHAR));
603 mbstowcs(wtarget, mp, len);
606 pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * len);
608 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_HandleLink failed scp=0x%p code=0x%x",
617 pCurrentEntry->TargetNameOffset = 0;
618 pCurrentEntry->TargetNameLength = 0;
620 lock_ReleaseWrite(&scp->rw);
622 dwEntryLength += pCurrentEntry->FileNameLength + pCurrentEntry->TargetNameLength;
623 dwEntryLength += (dwEntryLength % 8) ? 8 - (dwEntryLength % 8) : 0; /* quad align */
625 *ppNextEntry = (AFSDirEnumEntry *)((PBYTE)pCurrentEntry + dwEntryLength);
626 if (pdwRemainingLength)
627 *pdwRemainingLength = dwMaxEntryLength - dwEntryLength;
629 osi_Log3(afsd_logp, "RDR_PopulateCurrentEntry Success FileNameLength=%d TargetNameLength=%d RemainingLength=%d",
630 pCurrentEntry->FileNameLength, pCurrentEntry->TargetNameLength, *pdwRemainingLength);
636 RDR_PopulateCurrentEntryNoScp( IN AFSDirEnumEntry * pCurrentEntry,
637 IN DWORD dwMaxEntryLength,
638 IN cm_scache_t * dscp,
640 IN cm_user_t * userp,
643 IN wchar_t * shortName,
645 IN afs_uint32 cmError,
646 OUT AFSDirEnumEntry **ppNextEntry,
647 OUT DWORD * pdwRemainingLength)
653 afs_uint32 code = 0, code2 = 0;
655 osi_Log4(afsd_logp, "RDR_PopulateCurrentEntryNoEntry dscp=0x%p name=%S short=%S flags=0x%x",
656 dscp, osi_LogSaveStringW(afsd_logp, name),
657 osi_LogSaveStringW(afsd_logp, shortName), dwFlags);
658 osi_Log1(afsd_logp, "... maxLength=%d", dwMaxEntryLength);
660 if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
662 *ppNextEntry = pCurrentEntry;
663 if (pdwRemainingLength)
664 *pdwRemainingLength = dwMaxEntryLength;
665 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntryNoEntry Not Enough Room for Entry %d < %d",
666 dwMaxEntryLength, sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t));
667 return CM_ERROR_TOOBIG;
675 dwEntryLength = sizeof(AFSDirEnumEntry);
677 /* Populate the error code */
678 smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
680 /* Populate the fake data */
681 pCurrentEntry->FileId.Cell = fidp->cell;
682 pCurrentEntry->FileId.Volume = fidp->volume;
683 pCurrentEntry->FileId.Vnode = fidp->vnode;
684 pCurrentEntry->FileId.Unique = fidp->unique;
685 pCurrentEntry->FileId.Hash = fidp->hash;
687 pCurrentEntry->FileType = CM_SCACHETYPE_UNKNOWN;
689 pCurrentEntry->DataVersion.QuadPart = CM_SCACHE_VERSION_BAD;
691 cm_LargeSearchTimeFromUnixTime(&ft, 0);
692 pCurrentEntry->Expiration.LowPart = ft.dwLowDateTime;
693 pCurrentEntry->Expiration.HighPart = ft.dwHighDateTime;
695 cm_LargeSearchTimeFromUnixTime(&ft, 0);
696 pCurrentEntry->CreationTime.LowPart = ft.dwLowDateTime;
697 pCurrentEntry->CreationTime.HighPart = ft.dwHighDateTime;
698 pCurrentEntry->LastAccessTime = pCurrentEntry->CreationTime;
699 pCurrentEntry->LastWriteTime = pCurrentEntry->CreationTime;
700 pCurrentEntry->ChangeTime = pCurrentEntry->CreationTime;
702 pCurrentEntry->EndOfFile.QuadPart = 0;
703 pCurrentEntry->AllocationSize.QuadPart = 0;
704 pCurrentEntry->FileAttributes = 0;
705 pCurrentEntry->EaSize = 0;
706 pCurrentEntry->Links = 0;
708 len = wcslen(shortName);
709 wcsncpy(pCurrentEntry->ShortName, shortName, len);
710 pCurrentEntry->ShortNameLength = (CCHAR)(len * sizeof(WCHAR));
712 pCurrentEntry->FileNameOffset = sizeof(AFSDirEnumEntry);
714 wname = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->FileNameOffset);
715 wcsncpy(wname, name, len);
716 pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
718 pCurrentEntry->TargetNameOffset = 0;
719 pCurrentEntry->TargetNameLength = 0;
721 dwEntryLength += pCurrentEntry->FileNameLength + pCurrentEntry->TargetNameLength;
722 dwEntryLength += (dwEntryLength % 8) ? 8 - (dwEntryLength % 8) : 0; /* quad align */
724 *ppNextEntry = (AFSDirEnumEntry *)((PBYTE)pCurrentEntry + dwEntryLength);
725 if (pdwRemainingLength)
726 *pdwRemainingLength = dwMaxEntryLength - dwEntryLength;
728 osi_Log3(afsd_logp, "RDR_PopulateCurrentEntryNoScp Success FileNameLength=%d TargetNameLength=%d RemainingLength=%d",
729 pCurrentEntry->FileNameLength, pCurrentEntry->TargetNameLength, *pdwRemainingLength);
735 RDR_EnumerateDirectory( IN cm_user_t *userp,
737 IN AFSDirQueryCB *QueryCB,
740 IN DWORD ResultBufferLength,
741 IN OUT AFSCommResult **ResultCB)
744 cm_direnum_t * enump = NULL;
745 AFSDirEnumResp * pDirEnumResp;
746 AFSDirEnumEntry * pCurrentEntry;
747 size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
748 DWORD dwMaxEntryLength;
751 cm_scache_t * dscp = NULL;
754 RDR_InitReq(&req, bWow64);
756 osi_Log4(afsd_logp, "RDR_EnumerateDirectory FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
757 DirID.Cell, DirID.Volume, DirID.Vnode, DirID.Unique);
759 *ResultCB = (AFSCommResult *)malloc(size);
761 osi_Log0(afsd_logp, "RDR_EnumerateDirectory Out of Memory");
765 memset(*ResultCB, 0, size);
767 if (QueryCB->EnumHandle == (ULONG_PTR)-1) {
768 osi_Log0(afsd_logp, "RDR_EnumerateDirectory No More Entries");
769 (*ResultCB)->ResultStatus = STATUS_NO_MORE_ENTRIES;
770 (*ResultCB)->ResultBufferLength = 0;
774 (*ResultCB)->ResultBufferLength = dwMaxEntryLength = ResultBufferLength;
775 if (ResultBufferLength) {
776 pDirEnumResp = (AFSDirEnumResp *)&(*ResultCB)->ResultData;
777 pCurrentEntry = (AFSDirEnumEntry *)&pDirEnumResp->Entry;
778 dwMaxEntryLength -= FIELD_OFFSET( AFSDirEnumResp, Entry); /* AFSDirEnumResp */
781 if (DirID.Cell != 0) {
782 fid.cell = DirID.Cell;
783 fid.volume = DirID.Volume;
784 fid.vnode = DirID.Vnode;
785 fid.unique = DirID.Unique;
786 fid.hash = DirID.Hash;
788 code = cm_GetSCache(&fid, NULL, &dscp, userp, &req);
790 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
791 (*ResultCB)->ResultStatus = status;
792 osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure code=0x%x status=0x%x",
797 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
798 osi_Log0(afsd_logp, "RDR_EnumerateDirectory Object Name Invalid - Cell = 0");
802 /* get the directory size */
803 lock_ObtainWrite(&dscp->rw);
804 code = cm_SyncOp(dscp, NULL, userp, &req, PRSFS_LOOKUP,
805 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
807 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
808 (*ResultCB)->ResultStatus = status;
809 lock_ReleaseWrite(&dscp->rw);
810 cm_ReleaseSCache(dscp);
811 osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_SyncOp failure code=0x%x status=0x%x",
816 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
817 lock_ReleaseWrite(&dscp->rw);
819 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
820 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
821 cm_ReleaseSCache(dscp);
822 osi_Log1(afsd_logp, "RDR_EnumerateDirectory Not a Directory dscp=0x%p",
827 osi_Log1(afsd_logp, "RDR_EnumerateDirectory dv=%u", (afs_uint32)dscp->dataVersion);
830 * If there is no enumeration handle, then this is a new query
831 * and we must perform an enumeration for the specified object.
833 if (QueryCB->EnumHandle == (ULONG_PTR)NULL) {
836 code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
838 code = cm_BPlusDirEnumerate(dscp, userp, &req,
839 TRUE /* dir locked */, NULL /* no mask */,
840 TRUE /* fetch status? */, &enump);
842 osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumerate failure code=0x%x",
847 osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BeginDirOp failure code=0x%x",
851 enump = (cm_direnum_t *)QueryCB->EnumHandle;
855 if (ResultBufferLength == 0) {
856 code = cm_BPlusDirEnumBulkStat(enump);
858 osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumBulkStat failure code=0x%x",
862 cm_direnum_entry_t * entryp = NULL;
864 pDirEnumResp->SnapshotDataVersion.QuadPart = enump->dataVersion;
867 if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
868 osi_Log0(afsd_logp, "RDR_EnumerateDirectory out of space, returning");
872 code = cm_BPlusDirNextEnumEntry(enump, &entryp);
874 if ((code == 0 || code == CM_ERROR_STOPNOW) && entryp) {
875 cm_scache_t *scp = NULL;
876 int stopnow = (code == CM_ERROR_STOPNOW);
878 if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
879 osi_Log0(afsd_logp, "RDR_EnumerateDirectory skipping . or ..");
886 code = cm_GetSCache(&entryp->fid, &dscp->fid, &scp, userp, &req);
888 osi_Log5(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure cell %u vol %u vnode %u uniq %u code=0x%x",
889 entryp->fid.cell, entryp->fid.volume, entryp->fid.vnode, entryp->fid.unique, code);
892 code = entryp->errorCode;
893 scp = code ? NULL : cm_FindSCache(&entryp->fid);
897 code = RDR_PopulateCurrentEntry( pCurrentEntry, dwMaxEntryLength,
898 dscp, scp, userp, &req,
900 cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
901 (bWow64 ? RDR_POP_WOW64 : 0) |
902 (bSkipStatus ? RDR_POP_NO_GETSTATUS : 0),
904 &pCurrentEntry, &dwMaxEntryLength);
905 cm_ReleaseSCache(scp);
907 code = RDR_PopulateCurrentEntryNoScp( pCurrentEntry, dwMaxEntryLength,
908 dscp, &entryp->fid, userp, &req,
910 cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
911 (bWow64 ? RDR_POP_WOW64 : 0),
913 &pCurrentEntry, &dwMaxEntryLength);
924 if (code || enump->next == enump->count || ResultBufferLength == 0) {
925 cm_BPlusDirFreeEnumeration(enump);
926 enump = (cm_direnum_t *)(ULONG_PTR)-1;
929 if (code == 0 || code == CM_ERROR_STOPNOW) {
930 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
931 osi_Log0(afsd_logp, "RDR_EnumerateDirectory SUCCESS");
933 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
934 (*ResultCB)->ResultStatus = status;
935 osi_Log2(afsd_logp, "RDR_EnumerateDirectory Failure code=0x%x status=0x%x",
939 if (ResultBufferLength) {
940 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwMaxEntryLength;
942 pDirEnumResp->EnumHandle = (ULONG_PTR) enump;
943 pDirEnumResp->CurrentDataVersion.QuadPart = dscp->dataVersion;
947 cm_ReleaseSCache(dscp);
953 RDR_EvaluateNodeByName( IN cm_user_t *userp,
954 IN AFSFileID ParentID,
955 IN WCHAR *FileNameCounted,
956 IN DWORD FileNameLength,
957 IN BOOL CaseSensitive,
961 IN DWORD ResultBufferLength,
962 IN OUT AFSCommResult **ResultCB)
964 AFSFileEvalResultCB *pEvalResultCB = NULL;
965 AFSDirEnumEntry * pCurrentEntry;
966 size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
968 cm_scache_t * scp = NULL;
969 cm_scache_t * dscp = NULL;
974 WCHAR * wszName = NULL;
977 wchar_t FileName[260];
979 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
981 RDR_InitReq(&req, bWow64);
983 osi_Log4(afsd_logp, "RDR_EvaluateNodeByName parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
984 ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
986 /* Allocate enough room to add a volume prefix if necessary */
987 cbName = FileNameLength + (CM_PREFIX_VOL_CCH + 64) * sizeof(WCHAR);
988 wszName = malloc(cbName);
990 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
993 StringCbCopyNW(wszName, cbName, FileName, FileNameLength);
994 osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, wszName));
996 *ResultCB = (AFSCommResult *)malloc(size);
998 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
1003 memset(*ResultCB, 0, size);
1004 (*ResultCB)->ResultBufferLength = 0;
1005 dwRemaining = ResultBufferLength;
1006 if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
1007 pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
1008 pCurrentEntry = &pEvalResultCB->DirEnum;
1009 dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
1012 if (ParentID.Cell != 0) {
1013 parentFid.cell = ParentID.Cell;
1014 parentFid.volume = ParentID.Volume;
1015 parentFid.vnode = ParentID.Vnode;
1016 parentFid.unique = ParentID.Unique;
1017 parentFid.hash = ParentID.Hash;
1019 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1021 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1022 (*ResultCB)->ResultStatus = status;
1023 if ( status == STATUS_INVALID_HANDLE)
1024 status = STATUS_OBJECT_PATH_INVALID;
1025 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName cm_GetSCache parentFID failure code=0x%x status=0x%x",
1031 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
1032 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Object Name Invalid - Cell = 0");
1036 /* get the directory size */
1037 lock_ObtainWrite(&dscp->rw);
1038 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1039 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1041 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1042 (*ResultCB)->ResultStatus = status;
1043 lock_ReleaseWrite(&dscp->rw);
1044 cm_ReleaseSCache(dscp);
1045 osi_Log3(afsd_logp, "RDR_EvaluateNodeByName cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1046 dscp, code, status);
1050 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1051 lock_ReleaseWrite(&dscp->rw);
1053 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1054 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1055 cm_ReleaseSCache(dscp);
1056 osi_Log1(afsd_logp, "RDR_EvaluateNodeByName Not a Directory dscp=0x%p",
1062 code = cm_Lookup(dscp, wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1064 if ((code == CM_ERROR_NOSUCHPATH || code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) &&
1065 dscp == cm_data.rootSCachep) {
1067 if (wcschr(wszName, '%') != NULL || wcschr(wszName, '#') != NULL) {
1069 * A volume reference: <cell>{%,#}<volume> -> @vol:<cell>{%,#}<volume>
1071 StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
1072 StringCbCatNW(wszName, cbName, FileName, FileNameLength);
1075 code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1077 #ifdef AFS_FREELANCE_CLIENT
1078 else if (dscp->fid.cell == AFS_FAKE_ROOT_CELL_ID && dscp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1079 dscp->fid.vnode == 1 && dscp->fid.unique == 1) {
1081 * If this is the Freelance volume root directory then treat unrecognized
1082 * names as cell names and attempt to find the appropriate "root.cell".
1084 StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
1085 if (FileName[0] == L'.') {
1086 StringCbCatNW(wszName, cbName, &FileName[1], FileNameLength);
1087 StringCbCatNW(wszName, cbName, L"%", sizeof(WCHAR));
1089 StringCbCatNW(wszName, cbName, FileName, FileNameLength);
1090 StringCbCatNW(wszName, cbName, L"#", sizeof(WCHAR));
1092 StringCbCatNW(wszName, cbName, L"root.cell", 9 * sizeof(WCHAR));
1095 code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1100 if (code == 0 && scp) {
1101 wchar_t shortName[13]=L"";
1103 if (!cm_shortNames) {
1104 shortName[0] = L'\0';
1106 cm_Gen8Dot3VolNameW(scp->fid.cell, scp->fid.volume, shortName, NULL);
1107 } else if (!cm_Is8Dot3(wszName)) {
1110 dfid.vnode = htonl(scp->fid.vnode);
1111 dfid.unique = htonl(scp->fid.unique);
1113 cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
1115 shortName[0] = L'\0';
1118 code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
1119 dscp, scp, userp, &req,
1120 FileName, shortName,
1121 (bWow64 ? RDR_POP_WOW64 : 0) |
1122 (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
1123 0, NULL, &dwRemaining);
1125 RDR_FlagScpInUse( scp, FALSE );
1126 cm_ReleaseSCache(scp);
1129 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1130 (*ResultCB)->ResultStatus = status;
1131 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
1134 pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1135 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1136 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1137 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName SUCCESS");
1140 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1141 (*ResultCB)->ResultStatus = status;
1142 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
1145 (*ResultCB)->ResultStatus = STATUS_NO_SUCH_FILE;
1146 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName No Such File");
1148 cm_ReleaseSCache(dscp);
1155 RDR_EvaluateNodeByID( IN cm_user_t *userp,
1156 IN AFSFileID ParentID, /* not used */
1157 IN AFSFileID SourceID,
1161 IN DWORD ResultBufferLength,
1162 IN OUT AFSCommResult **ResultCB)
1164 AFSFileEvalResultCB *pEvalResultCB = NULL;
1165 AFSDirEnumEntry * pCurrentEntry = NULL;
1166 size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
1167 afs_uint32 code = 0;
1168 cm_scache_t * scp = NULL;
1169 cm_scache_t * dscp = NULL;
1176 osi_Log4(afsd_logp, "RDR_EvaluateNodeByID source FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1177 SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
1178 osi_Log4(afsd_logp, "... parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1179 ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1181 *ResultCB = (AFSCommResult *)malloc(size);
1183 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Out of Memory");
1187 memset(*ResultCB, 0, size);
1188 (*ResultCB)->ResultBufferLength = 0;
1189 dwRemaining = ResultBufferLength;
1190 if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
1191 pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
1192 pCurrentEntry = &pEvalResultCB->DirEnum;
1193 dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
1196 RDR_InitReq(&req, bWow64);
1198 if (SourceID.Cell != 0) {
1199 cm_SetFid(&Fid, SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
1200 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
1202 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1203 (*ResultCB)->ResultStatus = status;
1204 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache SourceFID failure code=0x%x status=0x%x",
1209 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
1210 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Object Name Invalid - Cell = 0");
1214 if (ParentID.Cell != 0) {
1215 cm_SetFid(&parentFid, ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1216 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1218 cm_ReleaseSCache(scp);
1219 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1220 if ( status == STATUS_INVALID_HANDLE)
1221 status = STATUS_OBJECT_PATH_INVALID;
1222 (*ResultCB)->ResultStatus = status;
1223 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
1227 } else if (SourceID.Vnode == 1) {
1229 cm_HoldSCache(dscp);
1230 } else if (scp->parentVnode) {
1231 cm_SetFid(&parentFid, SourceID.Cell, SourceID.Volume, scp->parentVnode, scp->parentUnique);
1232 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1234 cm_ReleaseSCache(scp);
1235 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1236 if ( status == STATUS_INVALID_HANDLE)
1237 status = STATUS_OBJECT_PATH_INVALID;
1238 (*ResultCB)->ResultStatus = status;
1239 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
1244 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
1245 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Object Path Invalid - Unknown Parent");
1249 /* Make sure the directory is current */
1250 lock_ObtainWrite(&dscp->rw);
1251 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1252 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1254 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1255 (*ResultCB)->ResultStatus = status;
1256 lock_ReleaseWrite(&dscp->rw);
1257 cm_ReleaseSCache(dscp);
1258 cm_ReleaseSCache(scp);
1259 osi_Log3(afsd_logp, "RDR_EvaluateNodeByID cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1260 dscp, code, status);
1264 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1265 lock_ReleaseWrite(&dscp->rw);
1267 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1268 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1269 cm_ReleaseSCache(dscp);
1270 cm_ReleaseSCache(scp);
1271 osi_Log1(afsd_logp, "RDR_EvaluateNodeByID Not a Directory dscp=0x%p", dscp);
1275 code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
1276 dscp, scp, userp, &req, NULL, NULL,
1277 (bWow64 ? RDR_POP_WOW64 : 0) |
1278 (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
1279 0, NULL, &dwRemaining);
1282 RDR_FlagScpInUse( scp, FALSE );
1283 cm_ReleaseSCache(scp);
1284 cm_ReleaseSCache(dscp);
1287 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1288 (*ResultCB)->ResultStatus = status;
1289 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID FAILURE code=0x%x status=0x%x",
1292 pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1294 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1295 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1296 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID SUCCESS");
1302 RDR_CreateFileEntry( IN cm_user_t *userp,
1303 IN WCHAR *FileNameCounted,
1304 IN DWORD FileNameLength,
1305 IN AFSFileCreateCB *CreateCB,
1308 IN DWORD ResultBufferLength,
1309 IN OUT AFSCommResult **ResultCB)
1311 AFSFileCreateResultCB *pResultCB = NULL;
1312 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1315 cm_scache_t * dscp = NULL;
1316 afs_uint32 flags = 0;
1318 cm_scache_t * scp = NULL;
1321 wchar_t FileName[260];
1323 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
1325 osi_Log4(afsd_logp, "RDR_CreateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1326 CreateCB->ParentId.Cell, CreateCB->ParentId.Volume,
1327 CreateCB->ParentId.Vnode, CreateCB->ParentId.Unique);
1328 osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
1330 RDR_InitReq(&req, bWow64);
1331 memset(&setAttr, 0, sizeof(cm_attr_t));
1333 *ResultCB = (AFSCommResult *)malloc(size);
1335 osi_Log0(afsd_logp, "RDR_CreateFileEntry out of memory");
1343 parentFid.cell = CreateCB->ParentId.Cell;
1344 parentFid.volume = CreateCB->ParentId.Volume;
1345 parentFid.vnode = CreateCB->ParentId.Vnode;
1346 parentFid.unique = CreateCB->ParentId.Unique;
1347 parentFid.hash = CreateCB->ParentId.Hash;
1349 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1351 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1352 (*ResultCB)->ResultStatus = status;
1353 if ( status == STATUS_INVALID_HANDLE)
1354 status = STATUS_OBJECT_PATH_INVALID;
1355 osi_Log2(afsd_logp, "RDR_CreateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1360 lock_ObtainWrite(&dscp->rw);
1361 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1362 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1364 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1365 (*ResultCB)->ResultStatus = status;
1366 lock_ReleaseWrite(&dscp->rw);
1367 cm_ReleaseSCache(dscp);
1368 osi_Log3(afsd_logp, "RDR_CreateFileEntry cm_SyncOp failure (1) dscp=0x%p code=0x%x status=0x%x",
1369 dscp, code, status);
1373 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1374 lock_ReleaseWrite(&dscp->rw);
1376 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1377 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1378 cm_ReleaseSCache(dscp);
1379 osi_Log1(afsd_logp, "RDR_CreateFileEntry Not a Directory dscp=0x%p",
1384 /* Use current time */
1385 setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
1386 setAttr.clientModTime = time(NULL);
1388 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1389 if (smb_unixModeDefaultDir) {
1390 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1391 setAttr.unixModeBits = smb_unixModeDefaultDir;
1392 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)
1393 setAttr.unixModeBits &= ~0222; /* disable the write bits */
1396 code = cm_MakeDir(dscp, FileName, flags, &setAttr, userp, &req, &scp);
1398 if (smb_unixModeDefaultFile) {
1399 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1400 setAttr.unixModeBits = smb_unixModeDefaultFile;
1401 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)
1402 setAttr.unixModeBits &= ~0222; /* disable the write bits */
1405 setAttr.mask |= CM_ATTRMASK_LENGTH;
1406 setAttr.length.LowPart = CreateCB->AllocationSize.LowPart;
1407 setAttr.length.HighPart = CreateCB->AllocationSize.HighPart;
1408 code = cm_Create(dscp, FileName, flags, &setAttr, &scp, userp, &req);
1411 wchar_t shortName[13]=L"";
1415 (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
1417 (*ResultCB)->ResultBufferLength = sizeof( AFSFileCreateResultCB);
1419 pResultCB = (AFSFileCreateResultCB *)(*ResultCB)->ResultData;
1421 dwRemaining = ResultBufferLength - sizeof( AFSFileCreateResultCB) + sizeof( AFSDirEnumEntry);
1423 lock_ObtainWrite(&dscp->rw);
1424 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1425 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1427 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1428 (*ResultCB)->ResultStatus = status;
1429 lock_ReleaseWrite(&dscp->rw);
1430 cm_ReleaseSCache(dscp);
1431 cm_ReleaseSCache(scp);
1432 osi_Log3(afsd_logp, "RDR_CreateFileEntry cm_SyncOp failure (2) dscp=0x%p code=0x%x status=0x%x",
1433 dscp, code, status);
1437 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1439 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1440 lock_ReleaseWrite(&dscp->rw);
1442 if (cm_shortNames) {
1443 dfid.vnode = htonl(scp->fid.vnode);
1444 dfid.unique = htonl(scp->fid.unique);
1446 if (!cm_Is8Dot3(FileName))
1447 cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
1449 shortName[0] = '\0';
1452 code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
1453 dscp, scp, userp, &req, FileName, shortName,
1454 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
1455 0, NULL, &dwRemaining);
1458 RDR_FlagScpInUse( scp, FALSE );
1459 cm_ReleaseSCache(scp);
1460 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1461 osi_Log0(afsd_logp, "RDR_CreateFileEntry SUCCESS");
1463 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1464 (*ResultCB)->ResultStatus = status;
1465 (*ResultCB)->ResultBufferLength = 0;
1466 osi_Log2(afsd_logp, "RDR_CreateFileEntry FAILURE code=0x%x status=0x%x",
1470 cm_ReleaseSCache(dscp);
1476 RDR_UpdateFileEntry( IN cm_user_t *userp,
1477 IN AFSFileID FileId,
1478 IN AFSFileUpdateCB *UpdateCB,
1480 IN DWORD ResultBufferLength,
1481 IN OUT AFSCommResult **ResultCB)
1483 AFSFileUpdateResultCB *pResultCB = NULL;
1484 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1488 afs_uint32 flags = 0;
1490 cm_scache_t * scp = NULL;
1491 cm_scache_t * dscp = NULL;
1493 time_t clientModTime;
1496 BOOL bScpLocked = FALSE;
1498 RDR_InitReq(&req, bWow64);
1499 memset(&setAttr, 0, sizeof(cm_attr_t));
1501 osi_Log4(afsd_logp, "RDR_UpdateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1502 UpdateCB->ParentId.Cell, UpdateCB->ParentId.Volume,
1503 UpdateCB->ParentId.Vnode, UpdateCB->ParentId.Unique);
1504 osi_Log4(afsd_logp, "... object FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1505 FileId.Cell, FileId.Volume,
1506 FileId.Vnode, FileId.Unique);
1508 *ResultCB = (AFSCommResult *)malloc( size);
1510 osi_Log0(afsd_logp, "RDR_UpdateFileEntry Out of Memory");
1518 parentFid.cell = UpdateCB->ParentId.Cell;
1519 parentFid.volume = UpdateCB->ParentId.Volume;
1520 parentFid.vnode = UpdateCB->ParentId.Vnode;
1521 parentFid.unique = UpdateCB->ParentId.Unique;
1522 parentFid.hash = UpdateCB->ParentId.Hash;
1524 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1526 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1527 (*ResultCB)->ResultStatus = status;
1528 if ( status == STATUS_INVALID_HANDLE)
1529 status = STATUS_OBJECT_PATH_INVALID;
1530 osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1535 lock_ObtainWrite(&dscp->rw);
1537 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1538 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1540 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1541 (*ResultCB)->ResultStatus = status;
1542 lock_ReleaseWrite(&dscp->rw);
1543 cm_ReleaseSCache(dscp);
1544 osi_Log3(afsd_logp, "RDR_UpdateFileEntry cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1545 dscp, code, status);
1549 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1550 lock_ReleaseWrite(&dscp->rw);
1553 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1554 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1555 cm_ReleaseSCache(dscp);
1556 osi_Log1(afsd_logp, "RDR_UpdateFileEntry Not a Directory dscp=0x%p",
1561 Fid.cell = FileId.Cell;
1562 Fid.volume = FileId.Volume;
1563 Fid.vnode = FileId.Vnode;
1564 Fid.unique = FileId.Unique;
1565 Fid.hash = FileId.Hash;
1567 code = cm_GetSCache(&Fid, &dscp->fid, &scp, userp, &req);
1569 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1570 (*ResultCB)->ResultStatus = status;
1571 cm_ReleaseSCache(dscp);
1572 osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache object FID failure code=0x%x status=0x%x",
1577 lock_ObtainWrite(&scp->rw);
1579 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1580 CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
1582 lock_ReleaseWrite(&scp->rw);
1583 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1584 (*ResultCB)->ResultStatus = status;
1585 (*ResultCB)->ResultBufferLength = 0;
1586 cm_ReleaseSCache(dscp);
1587 cm_ReleaseSCache(scp);
1588 osi_Log3(afsd_logp, "RDR_UpdateFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
1592 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1594 if (UpdateCB->ChangeTime.QuadPart) {
1596 if (scp->fileType == CM_SCACHETYPE_FILE) {
1597 /* Do not set length and other attributes at the same time */
1598 if (scp->length.QuadPart != UpdateCB->AllocationSize.QuadPart) {
1599 osi_Log2(afsd_logp, "RDR_UpdateFileEntry Length Change 0x%x -> 0x%x",
1600 (afs_uint32)scp->length.QuadPart, (afs_uint32)UpdateCB->AllocationSize.QuadPart);
1601 setAttr.mask |= CM_ATTRMASK_LENGTH;
1602 setAttr.length.LowPart = UpdateCB->AllocationSize.LowPart;
1603 setAttr.length.HighPart = UpdateCB->AllocationSize.HighPart;
1604 lock_ReleaseWrite(&scp->rw);
1606 code = cm_SetAttr(scp, &setAttr, userp, &req);
1614 lock_ObtainWrite(&scp->rw);
1617 if ((scp->unixModeBits & 0200) && (UpdateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1618 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1619 setAttr.unixModeBits = scp->unixModeBits & ~0222;
1620 } else if (!(scp->unixModeBits & 0200) && !(UpdateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1621 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1622 setAttr.unixModeBits = scp->unixModeBits | 0222;
1626 if (UpdateCB->LastWriteTime.QuadPart) {
1627 ft.dwLowDateTime = UpdateCB->LastWriteTime.LowPart;
1628 ft.dwHighDateTime = UpdateCB->LastWriteTime.HighPart;
1630 cm_UnixTimeFromLargeSearchTime(& clientModTime, &ft);
1633 lock_ObtainWrite(&scp->rw);
1636 if (scp->clientModTime != clientModTime) {
1637 setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
1638 setAttr.clientModTime = clientModTime;
1643 lock_ReleaseWrite(&scp->rw);
1645 code = cm_SetAttr(scp, &setAttr, userp, &req);
1652 lock_ReleaseWrite(&scp->rw);
1656 DWORD dwRemaining = ResultBufferLength - sizeof( AFSFileUpdateResultCB) + sizeof( AFSDirEnumEntry);
1658 pResultCB = (AFSFileUpdateResultCB *)(*ResultCB)->ResultData;
1660 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1662 code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
1663 dscp, scp, userp, &req, NULL, NULL,
1664 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
1665 0, NULL, &dwRemaining);
1666 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1667 osi_Log0(afsd_logp, "RDR_UpdateFileEntry SUCCESS");
1669 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1670 (*ResultCB)->ResultStatus = status;
1671 (*ResultCB)->ResultBufferLength = 0;
1672 osi_Log2(afsd_logp, "RDR_UpdateFileEntry FAILURE code=0x%x status=0x%x",
1675 cm_ReleaseSCache(scp);
1676 cm_ReleaseSCache(dscp);
1682 RDR_CleanupFileEntry( IN cm_user_t *userp,
1683 IN AFSFileID FileId,
1684 IN WCHAR *FileNameCounted,
1685 IN DWORD FileNameLength,
1686 IN AFSFileCleanupCB *CleanupCB,
1688 IN BOOL bLastHandle,
1689 IN BOOL bDeleteFile,
1690 IN BOOL bUnlockFile,
1691 IN DWORD ResultBufferLength,
1692 IN OUT AFSCommResult **ResultCB)
1694 AFSFileCleanupResultCB *pResultCB = NULL;
1695 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1698 afs_uint32 code = 0;
1699 afs_uint32 flags = 0;
1701 cm_scache_t * scp = NULL;
1702 cm_scache_t * dscp = NULL;
1704 time_t clientModTime;
1707 BOOL bScpLocked = FALSE;
1708 BOOL bDscpLocked = FALSE;
1709 BOOL bFlushFile = FALSE;
1712 RDR_InitReq(&req, bWow64);
1713 memset(&setAttr, 0, sizeof(cm_attr_t));
1715 osi_Log4(afsd_logp, "RDR_CleanupFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1716 CleanupCB->ParentId.Cell, CleanupCB->ParentId.Volume,
1717 CleanupCB->ParentId.Vnode, CleanupCB->ParentId.Unique);
1718 osi_Log4(afsd_logp, "... object FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1719 FileId.Cell, FileId.Volume,
1720 FileId.Vnode, FileId.Unique);
1722 *ResultCB = (AFSCommResult *)malloc( size);
1724 osi_Log0(afsd_logp, "RDR_CleanupFileEntry Out of Memory");
1732 parentFid.cell = CleanupCB->ParentId.Cell;
1733 parentFid.volume = CleanupCB->ParentId.Volume;
1734 parentFid.vnode = CleanupCB->ParentId.Vnode;
1735 parentFid.unique = CleanupCB->ParentId.Unique;
1736 parentFid.hash = CleanupCB->ParentId.Hash;
1738 if (parentFid.cell) {
1739 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1741 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1742 if ( status == STATUS_INVALID_HANDLE)
1743 status = STATUS_OBJECT_PATH_INVALID;
1744 (*ResultCB)->ResultStatus = status;
1745 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1750 lock_ObtainWrite(&dscp->rw);
1752 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1753 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1755 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp failure dscp=0x%p code=0x%x",
1761 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1762 lock_ReleaseWrite(&dscp->rw);
1763 bDscpLocked = FALSE;
1765 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1766 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1767 cm_ReleaseSCache(dscp);
1768 osi_Log1(afsd_logp, "RDR_CleanupFileEntry Not a Directory dscp=0x%p",
1775 Fid.cell = FileId.Cell;
1776 Fid.volume = FileId.Volume;
1777 Fid.vnode = FileId.Vnode;
1778 Fid.unique = FileId.Unique;
1779 Fid.hash = FileId.Hash;
1781 code = cm_GetSCache(&Fid, dscp ? &dscp->fid : NULL, &scp, userp, &req);
1783 osi_Log1(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache object FID failure code=0x%x",
1788 lock_ObtainWrite(&scp->rw);
1790 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1791 CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
1793 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp failure scp=0x%p code=0x%x",
1797 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1799 if ((bLastHandle || bFlushFile) &&
1800 scp->redirBufCount > 0)
1802 LARGE_INTEGER heldExtents;
1803 AFSFileExtentCB extentList[1024];
1804 DWORD extentCount = 0;
1809 heldExtents.QuadPart = 0;
1811 for ( srbp = redirq_to_cm_buf_t(scp->redirQueueT);
1813 srbp = redirq_to_cm_buf_t(osi_QPrev(&srbp->redirq)))
1815 extentList[extentCount].Flags = 0;
1816 extentList[extentCount].Length = cm_data.blockSize;
1817 extentList[extentCount].FileOffset.QuadPart = srbp->offset.QuadPart;
1818 extentList[extentCount].CacheOffset.QuadPart = srbp->datap - RDR_extentBaseAddress;
1819 lock_ObtainWrite(&buf_globalLock);
1820 srbp->redirReleaseRequested = now;
1821 lock_ReleaseWrite(&buf_globalLock);
1824 if (extentCount == 1024) {
1825 lock_ReleaseWrite(&scp->rw);
1826 code = RDR_RequestExtentRelease(&scp->fid, heldExtents, extentCount, extentList);
1828 if (code == CM_ERROR_RETRY) {
1830 * The redirector either is not holding the extents or cannot let them
1831 * go because they are otherwise in use. At the moment, do nothing.
1838 lock_ObtainWrite(&scp->rw);
1842 if (code == 0 && extentCount > 0) {
1844 lock_ReleaseWrite(&scp->rw);
1847 code = RDR_RequestExtentRelease(&scp->fid, heldExtents, extentCount, extentList);
1852 /* No longer in use by redirector */
1854 lock_ObtainWrite(&scp->rw);
1859 lock_AssertWrite(&scp->rw);
1860 scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
1863 /* If not a readonly object, flush dirty data and update metadata */
1864 if (!(scp->flags & CM_SCACHEFLAG_RO)) {
1865 if ((bLastHandle || bFlushFile) &&
1866 buf_DirtyBuffersExist(&scp->fid)) {
1868 lock_ObtainWrite(&scp->rw);
1871 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
1872 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1875 lock_ReleaseWrite(&scp->rw);
1879 code = cm_FSync(scp, userp, &req, bScpLocked);
1881 if (bLastHandle && code)
1885 if (CleanupCB->ChangeTime.QuadPart) {
1887 if (scp->fileType == CM_SCACHETYPE_FILE) {
1888 /* Do not set length and other attributes at the same time */
1889 if (scp->length.QuadPart != CleanupCB->AllocationSize.QuadPart) {
1890 osi_Log2(afsd_logp, "RDR_CleanupFileEntry Length Change 0x%x -> 0x%x",
1891 (afs_uint32)scp->length.QuadPart, (afs_uint32)CleanupCB->AllocationSize.QuadPart);
1892 setAttr.mask |= CM_ATTRMASK_LENGTH;
1893 setAttr.length.LowPart = CleanupCB->AllocationSize.LowPart;
1894 setAttr.length.HighPart = CleanupCB->AllocationSize.HighPart;
1897 lock_ReleaseWrite(&scp->rw);
1900 code = cm_SetAttr(scp, &setAttr, userp, &req);
1908 lock_ObtainWrite(&scp->rw);
1912 if ((scp->unixModeBits & 0200) && (CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1913 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1914 setAttr.unixModeBits = scp->unixModeBits & ~0222;
1915 } else if (!(scp->unixModeBits & 0200) && !(CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1916 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1917 setAttr.unixModeBits = scp->unixModeBits | 0222;
1921 if (CleanupCB->LastWriteTime.QuadPart) {
1922 ft.dwLowDateTime = CleanupCB->LastWriteTime.LowPart;
1923 ft.dwHighDateTime = CleanupCB->LastWriteTime.HighPart;
1925 cm_UnixTimeFromLargeSearchTime(&clientModTime, &ft);
1926 if (scp->clientModTime != clientModTime) {
1927 setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
1928 setAttr.clientModTime = clientModTime;
1935 lock_ReleaseWrite(&scp->rw);
1938 code = cm_SetAttr(scp, &setAttr, userp, &req);
1944 /* Now drop the lock enforcing the share access */
1945 if ( CleanupCB->FileAccess != AFS_FILE_ACCESS_NOLOCK) {
1946 unsigned int sLockType;
1947 LARGE_INTEGER LOffset, LLength;
1949 if (CleanupCB->FileAccess == AFS_FILE_ACCESS_SHARED)
1950 sLockType = LOCKING_ANDX_SHARED_LOCK;
1954 key = cm_GenerateKey(CM_SESSION_IFS, SMB_FID_QLOCK_PID, CleanupCB->Identifier);
1956 LOffset.HighPart = SMB_FID_QLOCK_HIGH;
1957 LOffset.LowPart = SMB_FID_QLOCK_LOW;
1958 LLength.HighPart = 0;
1959 LLength.LowPart = SMB_FID_QLOCK_LENGTH;
1962 lock_ObtainWrite(&scp->rw);
1966 code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_LOCK);
1969 code = cm_Unlock(scp, sLockType, LOffset, LLength, key, 0, userp, &req);
1971 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
1973 if (code == CM_ERROR_RANGE_NOT_LOCKED)
1975 osi_Log3(afsd_logp, "RDR_CleanupFileEntry Range Not Locked -- FileAccess 0x%x ProcessId 0x%x HandleId 0x%x",
1976 CleanupCB->FileAccess, CleanupCB->ProcessId, CleanupCB->Identifier);
1982 if (bUnlockFile || bDeleteFile) {
1984 lock_ObtainWrite(&scp->rw);
1987 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1988 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
1990 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
1995 key = cm_GenerateKey(CM_SESSION_IFS, CleanupCB->ProcessId, 0);
1997 /* the scp is now locked and current */
1998 code = cm_UnlockByKey(scp, key,
1999 bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
2002 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2010 lock_ReleaseWrite(&dscp->rw);
2012 lock_ReleaseWrite(&scp->rw);
2014 if (code == 0 && dscp && bDeleteFile) {
2015 WCHAR FileName[260];
2017 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
2019 if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
2020 code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
2022 code = cm_Unlink(dscp, NULL, FileName, userp, &req);
2026 if ( ResultBufferLength >= sizeof( AFSFileCleanupResultCB))
2028 (*ResultCB)->ResultBufferLength = sizeof( AFSFileCleanupResultCB);
2029 pResultCB = (AFSFileCleanupResultCB *)&(*ResultCB)->ResultData;
2030 pResultCB->ParentDataVersion.QuadPart = dscp ? dscp->dataVersion : 0;
2032 (*ResultCB)->ResultBufferLength = 0;
2035 (*ResultCB)->ResultStatus = 0;
2036 osi_Log0(afsd_logp, "RDR_CleanupFileEntry SUCCESS");
2038 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2039 (*ResultCB)->ResultStatus = status;
2040 osi_Log2(afsd_logp, "RDR_CleanupFileEntry FAILURE code=0x%x status=0x%x",
2045 cm_ReleaseSCache(scp);
2047 cm_ReleaseSCache(dscp);
2053 RDR_DeleteFileEntry( IN cm_user_t *userp,
2054 IN AFSFileID ParentId,
2055 IN ULONGLONG ProcessId,
2056 IN WCHAR *FileNameCounted,
2057 IN DWORD FileNameLength,
2060 IN DWORD ResultBufferLength,
2061 IN OUT AFSCommResult **ResultCB)
2064 AFSFileDeleteResultCB *pResultCB = NULL;
2065 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2068 cm_scache_t * dscp = NULL;
2069 cm_scache_t * scp = NULL;
2070 afs_uint32 flags = 0;
2074 wchar_t FileName[260];
2077 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
2079 osi_Log4(afsd_logp, "RDR_DeleteFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2080 ParentId.Cell, ParentId.Volume,
2081 ParentId.Vnode, ParentId.Unique);
2082 osi_Log2(afsd_logp, "... name=%S checkOnly=%x",
2083 osi_LogSaveStringW(afsd_logp, FileName),
2086 RDR_InitReq(&req, bWow64);
2087 memset(&setAttr, 0, sizeof(cm_attr_t));
2089 *ResultCB = (AFSCommResult *)malloc( size);
2091 osi_Log0(afsd_logp, "RDR_DeleteFileEntry out of memory");
2099 parentFid.cell = ParentId.Cell;
2100 parentFid.volume = ParentId.Volume;
2101 parentFid.vnode = ParentId.Vnode;
2102 parentFid.unique = ParentId.Unique;
2103 parentFid.hash = ParentId.Hash;
2105 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
2107 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2108 if ( status == STATUS_INVALID_HANDLE)
2109 status = STATUS_OBJECT_PATH_INVALID;
2110 (*ResultCB)->ResultStatus = status;
2111 osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
2116 lock_ObtainWrite(&dscp->rw);
2118 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
2119 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2121 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2122 (*ResultCB)->ResultStatus = status;
2123 (*ResultCB)->ResultBufferLength = 0;
2124 lock_ReleaseWrite(&dscp->rw);
2125 cm_ReleaseSCache(dscp);
2126 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
2127 dscp, code, status);
2131 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2132 lock_ReleaseWrite(&dscp->rw);
2134 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2135 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2136 cm_ReleaseSCache(dscp);
2137 osi_Log1(afsd_logp, "RDR_DeleteFileEntry Not a Directory dscp=0x%p",
2142 code = cm_Lookup(dscp, FileName, 0, userp, &req, &scp);
2144 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2145 (*ResultCB)->ResultStatus = status;
2146 (*ResultCB)->ResultBufferLength = 0;
2147 cm_ReleaseSCache(dscp);
2148 osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_Lookup failure code=0x%x status=0x%x",
2153 lock_ObtainWrite(&scp->rw);
2154 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_DELETE,
2155 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2157 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2158 (*ResultCB)->ResultStatus = status;
2159 (*ResultCB)->ResultBufferLength = 0;
2160 lock_ReleaseWrite(&scp->rw);
2161 cm_ReleaseSCache(scp);
2162 cm_ReleaseSCache(dscp);
2163 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2169 /* Drop all locks since the file is being deleted */
2170 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2171 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2173 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2174 (*ResultCB)->ResultStatus = status;
2175 (*ResultCB)->ResultBufferLength = 0;
2176 lock_ReleaseWrite(&scp->rw);
2177 cm_ReleaseSCache(scp);
2178 cm_ReleaseSCache(dscp);
2179 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp Lock failure scp=0x%p code=0x%x status=0x%x",
2183 /* the scp is now locked and current */
2184 key = cm_GenerateKey(CM_SESSION_IFS, ProcessId, 0);
2186 code = cm_UnlockByKey(scp, key,
2187 CM_UNLOCK_FLAG_BY_FID,
2190 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2191 lock_ReleaseWrite(&scp->rw);
2193 if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
2194 code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
2196 code = cm_Unlink(dscp, NULL, FileName, userp, &req);
2198 lock_ReleaseWrite(&scp->rw);
2202 (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
2204 (*ResultCB)->ResultBufferLength = sizeof( AFSFileDeleteResultCB);
2206 pResultCB = (AFSFileDeleteResultCB *)(*ResultCB)->ResultData;
2208 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
2209 osi_Log0(afsd_logp, "RDR_DeleteFileEntry SUCCESS");
2211 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2212 (*ResultCB)->ResultStatus = status;
2213 (*ResultCB)->ResultBufferLength = 0;
2214 osi_Log2(afsd_logp, "RDR_DeleteFileEntry FAILURE code=0x%x status=0x%x",
2218 cm_ReleaseSCache(dscp);
2219 cm_ReleaseSCache(scp);
2225 RDR_RenameFileEntry( IN cm_user_t *userp,
2226 IN WCHAR *SourceFileNameCounted,
2227 IN DWORD SourceFileNameLength,
2228 IN AFSFileID SourceFileId,
2229 IN AFSFileRenameCB *pRenameCB,
2231 IN DWORD ResultBufferLength,
2232 IN OUT AFSCommResult **ResultCB)
2235 AFSFileRenameResultCB *pResultCB = NULL;
2236 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2237 AFSFileID SourceParentId = pRenameCB->SourceParentId;
2238 AFSFileID TargetParentId = pRenameCB->TargetParentId;
2239 WCHAR * TargetFileNameCounted = pRenameCB->TargetName;
2240 DWORD TargetFileNameLength = pRenameCB->TargetNameLength;
2241 cm_fid_t SourceParentFid;
2242 cm_fid_t TargetParentFid;
2244 cm_fid_t OrigTargetFid = {0,0,0,0,0};
2246 cm_scache_t * oldDscp;
2247 cm_scache_t * newDscp;
2249 wchar_t shortName[13];
2250 wchar_t SourceFileName[260];
2251 wchar_t TargetFileName[260];
2257 RDR_InitReq(&req, bWow64);
2259 StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
2260 StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
2262 osi_Log4(afsd_logp, "RDR_RenameFileEntry Source Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2263 SourceParentId.Cell, SourceParentId.Volume,
2264 SourceParentId.Vnode, SourceParentId.Unique);
2265 osi_Log2(afsd_logp, "... Source Name=%S Length %u", osi_LogSaveStringW(afsd_logp, SourceFileName), SourceFileNameLength);
2266 osi_Log4(afsd_logp, "... Target Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2267 TargetParentId.Cell, TargetParentId.Volume,
2268 TargetParentId.Vnode, TargetParentId.Unique);
2269 osi_Log2(afsd_logp, "... Target Name=%S Length %u", osi_LogSaveStringW(afsd_logp, TargetFileName), TargetFileNameLength);
2271 *ResultCB = (AFSCommResult *)malloc( size);
2279 pResultCB = (AFSFileRenameResultCB *)(*ResultCB)->ResultData;
2281 if (SourceFileNameLength == 0 || TargetFileNameLength == 0)
2283 osi_Log2(afsd_logp, "RDR_RenameFileEntry Invalid Name Length: src %u target %u",
2284 SourceFileNameLength, TargetFileNameLength);
2285 (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
2289 SourceParentFid.cell = SourceParentId.Cell;
2290 SourceParentFid.volume = SourceParentId.Volume;
2291 SourceParentFid.vnode = SourceParentId.Vnode;
2292 SourceParentFid.unique = SourceParentId.Unique;
2293 SourceParentFid.hash = SourceParentId.Hash;
2295 TargetParentFid.cell = TargetParentId.Cell;
2296 TargetParentFid.volume = TargetParentId.Volume;
2297 TargetParentFid.vnode = TargetParentId.Vnode;
2298 TargetParentFid.unique = TargetParentId.Unique;
2299 TargetParentFid.hash = TargetParentId.Hash;
2301 code = cm_GetSCache(&SourceParentFid, NULL, &oldDscp, userp, &req);
2303 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache source parent failed code 0x%x", code);
2304 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2305 if ( status == STATUS_INVALID_HANDLE)
2306 status = STATUS_OBJECT_PATH_INVALID;
2307 (*ResultCB)->ResultStatus = status;
2311 lock_ObtainWrite(&oldDscp->rw);
2312 code = cm_SyncOp(oldDscp, NULL, userp, &req, 0,
2313 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2315 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp oldDscp 0x%p failed code 0x%x", oldDscp, code);
2316 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2317 if ( status == STATUS_INVALID_HANDLE)
2318 status = STATUS_OBJECT_PATH_INVALID;
2319 (*ResultCB)->ResultStatus = status;
2320 lock_ReleaseWrite(&oldDscp->rw);
2321 cm_ReleaseSCache(oldDscp);
2325 cm_SyncOpDone(oldDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2326 lock_ReleaseWrite(&oldDscp->rw);
2329 if (oldDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2330 osi_Log1(afsd_logp, "RDR_RenameFileEntry oldDscp 0x%p not a directory", oldDscp);
2331 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2332 cm_ReleaseSCache(oldDscp);
2336 code = cm_GetSCache(&TargetParentFid, NULL, &newDscp, userp, &req);
2338 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target parent failed code 0x%x", code);
2339 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2340 (*ResultCB)->ResultStatus = status;
2341 cm_ReleaseSCache(oldDscp);
2345 lock_ObtainWrite(&newDscp->rw);
2346 code = cm_SyncOp(newDscp, NULL, userp, &req, 0,
2347 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2349 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp newDscp 0x%p failed code 0x%x", newDscp, code);
2350 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2351 (*ResultCB)->ResultStatus = status;
2352 lock_ReleaseWrite(&newDscp->rw);
2353 cm_ReleaseSCache(oldDscp);
2354 cm_ReleaseSCache(newDscp);
2358 cm_SyncOpDone(newDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2359 lock_ReleaseWrite(&newDscp->rw);
2362 if (newDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2363 osi_Log1(afsd_logp, "RDR_RenameFileEntry newDscp 0x%p not a directory", newDscp);
2364 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2365 cm_ReleaseSCache(oldDscp);
2366 cm_ReleaseSCache(newDscp);
2370 /* Obtain the original FID just for debugging purposes */
2371 code = cm_BeginDirOp( oldDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2373 code = cm_BPlusDirLookup(&dirop, SourceFileName, &SourceFid);
2374 code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
2375 cm_EndDirOp(&dirop);
2378 code = cm_Rename( oldDscp, NULL, SourceFileName,
2379 newDscp, TargetFileName, userp, &req);
2381 cm_scache_t *scp = 0;
2384 (*ResultCB)->ResultBufferLength = ResultBufferLength;
2385 dwRemaining = ResultBufferLength - sizeof( AFSFileRenameResultCB) + sizeof( AFSDirEnumEntry);
2386 (*ResultCB)->ResultStatus = 0;
2388 pResultCB->SourceParentDataVersion.QuadPart = oldDscp->dataVersion;
2389 pResultCB->TargetParentDataVersion.QuadPart = newDscp->dataVersion;
2391 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p SUCCESS",
2394 code = cm_BeginDirOp( newDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2396 code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
2397 cm_EndDirOp(&dirop);
2401 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_BPlusDirLookup failed code 0x%x",
2403 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
2404 cm_ReleaseSCache(oldDscp);
2405 cm_ReleaseSCache(newDscp);
2409 osi_Log4(afsd_logp, "RDR_RenameFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2410 TargetFid.cell, TargetFid.volume,
2411 TargetFid.vnode, TargetFid.unique);
2413 code = cm_GetSCache(&TargetFid, &newDscp->fid, &scp, userp, &req);
2415 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target failed code 0x%x", code);
2416 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2417 (*ResultCB)->ResultStatus = status;
2418 cm_ReleaseSCache(oldDscp);
2419 cm_ReleaseSCache(newDscp);
2423 /* Make sure the source vnode is current */
2424 lock_ObtainWrite(&scp->rw);
2425 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2426 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2428 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp scp 0x%p failed code 0x%x", scp, code);
2429 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2430 (*ResultCB)->ResultStatus = status;
2431 lock_ReleaseWrite(&scp->rw);
2432 cm_ReleaseSCache(oldDscp);
2433 cm_ReleaseSCache(newDscp);
2434 cm_ReleaseSCache(scp);
2438 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2439 lock_ReleaseWrite(&scp->rw);
2441 if (cm_shortNames) {
2442 dfid.vnode = htonl(scp->fid.vnode);
2443 dfid.unique = htonl(scp->fid.unique);
2445 if (!cm_Is8Dot3(TargetFileName))
2446 cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
2448 shortName[0] = '\0';
2451 RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
2452 newDscp, scp, userp, &req, TargetFileName, shortName,
2453 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
2454 0, NULL, &dwRemaining);
2455 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
2456 cm_ReleaseSCache(scp);
2458 osi_Log0(afsd_logp, "RDR_RenameFileEntry SUCCESS");
2460 osi_Log3(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p failed code 0x%x",
2461 oldDscp, newDscp, code);
2462 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2463 (*ResultCB)->ResultStatus = status;
2464 (*ResultCB)->ResultBufferLength = 0;
2467 cm_ReleaseSCache(oldDscp);
2468 cm_ReleaseSCache(newDscp);
2473 * AFS does not support cross-directory hard links but RDR_HardLinkFileEntry
2474 * is written as if AFS does. The check for cross-directory links is
2475 * implemented in cm_Link().
2477 * Windows supports optional ReplaceIfExists functionality. The AFS file
2478 * server does not. If the target name already exists and bReplaceIfExists
2479 * is true, check to see if the user has insert permission before calling
2480 * cm_Unlink() on the existing object. If the user does not have insert
2481 * permission return STATUS_ACCESS_DENIED.
2485 RDR_HardLinkFileEntry( IN cm_user_t *userp,
2486 IN WCHAR *SourceFileNameCounted,
2487 IN DWORD SourceFileNameLength,
2488 IN AFSFileID SourceFileId,
2489 IN AFSFileHardLinkCB *pHardLinkCB,
2491 IN DWORD ResultBufferLength,
2492 IN OUT AFSCommResult **ResultCB)
2495 AFSFileHardLinkResultCB *pResultCB = NULL;
2496 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2497 AFSFileID SourceParentId = pHardLinkCB->SourceParentId;
2498 AFSFileID TargetParentId = pHardLinkCB->TargetParentId;
2499 WCHAR * TargetFileNameCounted = pHardLinkCB->TargetName;
2500 DWORD TargetFileNameLength = pHardLinkCB->TargetNameLength;
2501 cm_fid_t SourceParentFid;
2502 cm_fid_t TargetParentFid;
2504 cm_fid_t OrigTargetFid = {0,0,0,0,0};
2505 cm_scache_t * srcDscp = NULL;
2506 cm_scache_t * targetDscp = NULL;
2507 cm_scache_t * srcScp = NULL;
2509 wchar_t shortName[13];
2510 wchar_t SourceFileName[260];
2511 wchar_t TargetFileName[260];
2517 RDR_InitReq(&req, bWow64);
2519 StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
2520 StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
2522 osi_Log4(afsd_logp, "RDR_HardLinkFileEntry Source Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2523 SourceParentId.Cell, SourceParentId.Volume,
2524 SourceParentId.Vnode, SourceParentId.Unique);
2525 osi_Log2(afsd_logp, "... Source Name=%S Length %u", osi_LogSaveStringW(afsd_logp, SourceFileName), SourceFileNameLength);
2526 osi_Log4(afsd_logp, "... Target Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2527 TargetParentId.Cell, TargetParentId.Volume,
2528 TargetParentId.Vnode, TargetParentId.Unique);
2529 osi_Log2(afsd_logp, "... Target Name=%S Length %u", osi_LogSaveStringW(afsd_logp, TargetFileName), TargetFileNameLength);
2531 *ResultCB = (AFSCommResult *)malloc( size);
2539 pResultCB = (AFSFileHardLinkResultCB *)(*ResultCB)->ResultData;
2541 if (SourceFileNameLength == 0 || TargetFileNameLength == 0)
2543 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry Invalid Name Length: src %u target %u",
2544 SourceFileNameLength, TargetFileNameLength);
2545 (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
2549 SourceFid.cell = SourceFileId.Cell;
2550 SourceFid.volume = SourceFileId.Volume;
2551 SourceFid.vnode = SourceFileId.Vnode;
2552 SourceFid.unique = SourceFileId.Unique;
2553 SourceFid.hash = SourceFileId.Hash;
2555 SourceParentFid.cell = SourceParentId.Cell;
2556 SourceParentFid.volume = SourceParentId.Volume;
2557 SourceParentFid.vnode = SourceParentId.Vnode;
2558 SourceParentFid.unique = SourceParentId.Unique;
2559 SourceParentFid.hash = SourceParentId.Hash;
2561 TargetParentFid.cell = TargetParentId.Cell;
2562 TargetParentFid.volume = TargetParentId.Volume;
2563 TargetParentFid.vnode = TargetParentId.Vnode;
2564 TargetParentFid.unique = TargetParentId.Unique;
2565 TargetParentFid.hash = TargetParentId.Hash;
2567 code = cm_GetSCache(&SourceFid, NULL, &srcScp, userp, &req);
2569 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache source failed code 0x%x", code);
2570 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2571 (*ResultCB)->ResultStatus = status;
2575 code = cm_GetSCache(&TargetParentFid, NULL, &targetDscp, userp, &req);
2577 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache target parent failed code 0x%x", code);
2578 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2579 (*ResultCB)->ResultStatus = status;
2580 cm_ReleaseSCache(srcScp);
2584 lock_ObtainWrite(&targetDscp->rw);
2585 code = cm_SyncOp(targetDscp, NULL, userp, &req, PRSFS_INSERT,
2586 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2588 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp targetDscp 0x%p failed code 0x%x", targetDscp, code);
2589 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2590 (*ResultCB)->ResultStatus = status;
2591 lock_ReleaseWrite(&targetDscp->rw);
2592 cm_ReleaseSCache(srcScp);
2593 cm_ReleaseSCache(targetDscp);
2597 cm_SyncOpDone(targetDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2598 lock_ReleaseWrite(&targetDscp->rw);
2600 if (targetDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2601 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry targetDscp 0x%p not a directory", targetDscp);
2602 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2603 cm_ReleaseSCache(srcScp);
2604 cm_ReleaseSCache(targetDscp);
2608 if ( cm_FidCmp(&SourceParentFid, &TargetParentFid) ) {
2609 code = cm_GetSCache(&SourceParentFid, NULL, &srcDscp, userp, &req);
2611 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache source parent failed code 0x%x", code);
2612 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2613 if ( status == STATUS_INVALID_HANDLE)
2614 status = STATUS_OBJECT_PATH_INVALID;
2615 (*ResultCB)->ResultStatus = status;
2616 cm_ReleaseSCache(srcScp);
2617 cm_ReleaseSCache(targetDscp);
2621 lock_ObtainWrite(&srcDscp->rw);
2622 code = cm_SyncOp(srcDscp, NULL, userp, &req, 0,
2623 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2625 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp srcDscp 0x%p failed code 0x%x", srcDscp, code);
2626 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2627 if ( status == STATUS_INVALID_HANDLE)
2628 status = STATUS_OBJECT_PATH_INVALID;
2629 (*ResultCB)->ResultStatus = status;
2630 lock_ReleaseWrite(&srcDscp->rw);
2631 if (srcDscp != targetDscp)
2632 cm_ReleaseSCache(srcDscp);
2633 cm_ReleaseSCache(targetDscp);
2634 cm_ReleaseSCache(srcScp);
2638 cm_SyncOpDone(srcDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2639 lock_ReleaseWrite(&srcDscp->rw);
2641 if (srcDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2642 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry srcDscp 0x%p not a directory", srcDscp);
2643 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2644 if (srcDscp != targetDscp)
2645 cm_ReleaseSCache(srcDscp);
2646 cm_ReleaseSCache(targetDscp);
2647 cm_ReleaseSCache(srcScp);
2651 srcDscp = targetDscp;
2654 /* Obtain the target FID if it exists */
2655 code = cm_BeginDirOp( targetDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2657 code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
2658 cm_EndDirOp(&dirop);
2661 if (OrigTargetFid.vnode) {
2663 /* An object exists with the target name */
2664 if (!pHardLinkCB->bReplaceIfExists) {
2665 osi_Log0(afsd_logp, "RDR_HardLinkFileEntry target name collision and !ReplaceIfExists");
2666 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_COLLISION;
2667 if (srcDscp != targetDscp)
2668 cm_ReleaseSCache(srcDscp);
2669 cm_ReleaseSCache(targetDscp);
2670 cm_ReleaseSCache(srcScp);
2674 lock_ObtainWrite(&targetDscp->rw);
2675 code = cm_SyncOp(targetDscp, NULL, userp, &req, PRSFS_INSERT | PRSFS_DELETE,
2676 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2678 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2679 (*ResultCB)->ResultStatus = status;
2680 lock_ReleaseWrite(&srcDscp->rw);
2681 if (srcDscp != targetDscp)
2682 cm_ReleaseSCache(srcDscp);
2683 cm_ReleaseSCache(targetDscp);
2684 cm_ReleaseSCache(srcScp);
2687 cm_SyncOpDone(targetDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2688 lock_ReleaseWrite(&targetDscp->rw);
2690 code = cm_Unlink(targetDscp, NULL, TargetFileName, userp, &req);
2692 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_Unlink code 0x%x", code);
2693 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2694 (*ResultCB)->ResultStatus = status;
2695 lock_ReleaseWrite(&srcDscp->rw);
2696 if (srcDscp != targetDscp)
2697 cm_ReleaseSCache(srcDscp);
2698 cm_ReleaseSCache(targetDscp);
2699 cm_ReleaseSCache(srcScp);
2704 code = cm_Link( targetDscp, TargetFileName, srcScp, 0, userp, &req);
2707 cm_scache_t *targetScp = 0;
2710 (*ResultCB)->ResultBufferLength = ResultBufferLength;
2711 dwRemaining = ResultBufferLength - sizeof( AFSFileHardLinkResultCB) + sizeof( AFSDirEnumEntry);
2712 (*ResultCB)->ResultStatus = 0;
2714 pResultCB->SourceParentDataVersion.QuadPart = srcDscp->dataVersion;
2715 pResultCB->TargetParentDataVersion.QuadPart = targetDscp->dataVersion;
2717 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_Link srcDscp 0x%p targetDscp 0x%p SUCCESS",
2718 srcDscp, targetDscp);
2720 code = cm_BeginDirOp( targetDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2722 code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
2723 cm_EndDirOp(&dirop);
2727 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_BPlusDirLookup failed code 0x%x",
2729 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
2730 if (srcDscp != targetDscp)
2731 cm_ReleaseSCache(srcDscp);
2732 cm_ReleaseSCache(srcScp);
2733 cm_ReleaseSCache(targetDscp);
2737 osi_Log4(afsd_logp, "RDR_HardLinkFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2738 TargetFid.cell, TargetFid.volume,
2739 TargetFid.vnode, TargetFid.unique);
2741 code = cm_GetSCache(&TargetFid, &targetDscp->fid, &targetScp, userp, &req);
2743 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache target failed code 0x%x", code);
2744 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2745 (*ResultCB)->ResultStatus = status;
2746 if (srcDscp != targetDscp)
2747 cm_ReleaseSCache(srcDscp);
2748 cm_ReleaseSCache(srcScp);
2749 cm_ReleaseSCache(targetDscp);
2753 /* Make sure the source vnode is current */
2754 lock_ObtainWrite(&targetScp->rw);
2755 code = cm_SyncOp(targetScp, NULL, userp, &req, 0,
2756 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2758 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp scp 0x%p failed code 0x%x",
2760 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2761 (*ResultCB)->ResultStatus = status;
2762 lock_ReleaseWrite(&targetScp->rw);
2763 cm_ReleaseSCache(targetScp);
2764 if (srcDscp != targetDscp)
2765 cm_ReleaseSCache(srcDscp);
2766 cm_ReleaseSCache(srcScp);
2767 cm_ReleaseSCache(targetDscp);
2771 cm_SyncOpDone(targetScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2772 lock_ReleaseWrite(&targetScp->rw);
2774 if (cm_shortNames) {
2775 dfid.vnode = htonl(targetScp->fid.vnode);
2776 dfid.unique = htonl(targetScp->fid.unique);
2778 if (!cm_Is8Dot3(TargetFileName))
2779 cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
2781 shortName[0] = '\0';
2784 RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
2785 targetDscp, targetScp, userp, &req, TargetFileName, shortName,
2786 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
2787 0, NULL, &dwRemaining);
2788 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
2789 cm_ReleaseSCache(targetScp);
2791 osi_Log0(afsd_logp, "RDR_HardLinkFileEntry SUCCESS");
2793 osi_Log3(afsd_logp, "RDR_HardLinkFileEntry cm_Link srcDscp 0x%p targetDscp 0x%p failed code 0x%x",
2794 srcDscp, targetDscp, code);
2795 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2796 (*ResultCB)->ResultStatus = status;
2797 (*ResultCB)->ResultBufferLength = 0;
2800 cm_ReleaseSCache(srcScp);
2801 if (srcDscp != targetDscp)
2802 cm_ReleaseSCache(srcDscp);
2803 cm_ReleaseSCache(targetDscp);
2808 RDR_FlushFileEntry( IN cm_user_t *userp,
2809 IN AFSFileID FileId,
2811 IN DWORD ResultBufferLength,
2812 IN OUT AFSCommResult **ResultCB)
2814 cm_scache_t *scp = NULL;
2823 RDR_InitReq(&req, bWow64);
2825 osi_Log4(afsd_logp, "RDR_FlushFileEntry File FID cell 0x%x vol 0x%x vno 0x%x uniq 0x%x",
2826 FileId.Cell, FileId.Volume,
2827 FileId.Vnode, FileId.Unique);
2829 snprintf( dbgstr, 1024,
2830 "RDR_FlushFileEntry File FID cell 0x%x vol 0x%x vno 0x%x uniq 0x%x\n",
2831 FileId.Cell, FileId.Volume,
2832 FileId.Vnode, FileId.Unique);
2833 OutputDebugStringA( dbgstr);
2836 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
2838 osi_Log0(afsd_logp, "RDR_FlushFileEntry out of memory");
2844 sizeof( AFSCommResult));
2846 /* Process the release */
2847 Fid.cell = FileId.Cell;
2848 Fid.volume = FileId.Volume;
2849 Fid.vnode = FileId.Vnode;
2850 Fid.unique = FileId.Unique;
2851 Fid.hash = FileId.Hash;
2853 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
2855 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2856 (*ResultCB)->ResultStatus = status;
2857 osi_Log2(afsd_logp, "RDR_FlushFileEntry cm_GetSCache FID failure code=0x%x status=0x%x",
2862 lock_ObtainWrite(&scp->rw);
2863 if (scp->flags & CM_SCACHEFLAG_DELETED) {
2864 lock_ReleaseWrite(&scp->rw);
2865 (*ResultCB)->ResultStatus = STATUS_INVALID_HANDLE;
2869 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2870 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2872 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2873 (*ResultCB)->ResultStatus = status;
2874 lock_ReleaseWrite(&scp->rw);
2875 cm_ReleaseSCache(scp);
2876 osi_Log3(afsd_logp, "RDR_FlushFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2881 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2882 lock_ReleaseWrite(&scp->rw);
2884 code = cm_FSync(scp, userp, &req, FALSE);
2885 cm_ReleaseSCache(scp);
2888 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2889 (*ResultCB)->ResultStatus = status;
2890 osi_Log2(afsd_logp, "RDR_FlushFileEntry FAILURE code=0x%x status=0x%x",
2893 (*ResultCB)->ResultStatus = 0;
2894 osi_Log0(afsd_logp, "RDR_FlushFileEntry SUCCESS");
2896 (*ResultCB)->ResultBufferLength = 0;
2902 RDR_CheckAccess( IN cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp,
2906 ULONG afs_acc, afs_gr;
2908 afs_uint32 code = 0;
2910 file = (scp->fileType == CM_SCACHETYPE_FILE);
2913 /* access definitions from prs_fs.h */
2915 if (access & FILE_READ_DATA)
2916 afs_acc |= PRSFS_READ;
2917 if (access & FILE_READ_EA || access & FILE_READ_ATTRIBUTES)
2918 afs_acc |= PRSFS_READ;
2919 if (file && ((access & FILE_WRITE_DATA) || (access & FILE_APPEND_DATA)))
2920 afs_acc |= PRSFS_WRITE;
2921 if (access & FILE_WRITE_EA || access & FILE_WRITE_ATTRIBUTES)
2922 afs_acc |= PRSFS_WRITE;
2923 if (dir && ((access & FILE_ADD_FILE) || (access & FILE_ADD_SUBDIRECTORY)))
2924 afs_acc |= PRSFS_INSERT;
2925 if (dir && (access & FILE_LIST_DIRECTORY))
2926 afs_acc |= PRSFS_LOOKUP;
2927 if (file && (access & FILE_EXECUTE))
2928 afs_acc |= PRSFS_WRITE;
2929 if (dir && (access & FILE_TRAVERSE))
2930 afs_acc |= PRSFS_READ;
2931 if (dir && (access & FILE_DELETE_CHILD))
2932 afs_acc |= PRSFS_DELETE;
2933 if ((access & DELETE))
2934 afs_acc |= PRSFS_DELETE;
2936 /* check ACL with server */
2937 lock_ObtainWrite(&scp->rw);
2940 if (cm_HaveAccessRights(scp, userp, reqp, afs_acc, &afs_gr))
2946 /* we don't know the required access rights */
2947 code = cm_GetAccessRights(scp, userp, reqp);
2953 lock_ReleaseWrite(&(scp->rw));
2957 if (afs_gr & PRSFS_READ)
2958 *granted |= FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES | FILE_EXECUTE;
2959 if (afs_gr & PRSFS_WRITE)
2960 *granted |= FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES | FILE_EXECUTE;
2961 if (afs_gr & PRSFS_INSERT)
2962 *granted |= (dir ? FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY : 0) | (file ? FILE_ADD_SUBDIRECTORY : 0);
2963 if (afs_gr & PRSFS_LOOKUP)
2964 *granted |= (dir ? FILE_LIST_DIRECTORY : 0);
2965 if (afs_gr & PRSFS_DELETE)
2966 *granted |= FILE_DELETE_CHILD | DELETE;
2967 if (afs_gr & PRSFS_LOCK)
2969 if (afs_gr & PRSFS_ADMINISTER)
2972 *granted |= SYNCHRONIZE | READ_CONTROL;
2974 /* don't give more access than what was requested */
2976 osi_Log3(afsd_logp, "RDR_CheckAccess SUCCESS scp=0x%p requested=0x%x granted=0x%x", scp, access, *granted);
2978 osi_Log2(afsd_logp, "RDR_CheckAccess FAILURE scp=0x%p code=0x%x",
2985 RDR_OpenFileEntry( IN cm_user_t *userp,
2986 IN AFSFileID FileId,
2987 IN AFSFileOpenCB *OpenCB,
2990 IN DWORD ResultBufferLength,
2991 IN OUT AFSCommResult **ResultCB)
2993 AFSFileOpenResultCB *pResultCB = NULL;
2994 cm_scache_t *scp = NULL;
2995 cm_user_t *sysUserp = NULL;
2997 cm_lock_data_t *ldp = NULL;
3002 RDR_InitReq(&req, bWow64);
3004 osi_Log4(afsd_logp, "RDR_OpenFileEntry File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3005 FileId.Cell, FileId.Volume,
3006 FileId.Vnode, FileId.Unique);
3008 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof( AFSFileOpenResultCB));
3010 osi_Log0(afsd_logp, "RDR_OpenFileEntry out of memory");
3016 sizeof( AFSCommResult) + sizeof( AFSFileOpenResultCB));
3018 pResultCB = (AFSFileOpenResultCB *)(*ResultCB)->ResultData;
3020 /* Process the release */
3021 Fid.cell = FileId.Cell;
3022 Fid.volume = FileId.Volume;
3023 Fid.vnode = FileId.Vnode;
3024 Fid.unique = FileId.Unique;
3025 Fid.hash = FileId.Hash;
3027 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
3029 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3030 (*ResultCB)->ResultStatus = status;
3031 osi_Log2(afsd_logp, "RDR_OpenFileEntry cm_GetSCache FID failure code=0x%x status=0x%x",
3036 lock_ObtainWrite(&scp->rw);
3037 code = cm_SyncOp(scp, NULL, userp, &req, 0,
3038 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3040 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3041 (*ResultCB)->ResultStatus = status;
3042 lock_ReleaseWrite(&scp->rw);
3043 cm_ReleaseSCache(scp);
3044 osi_Log3(afsd_logp, "RDR_OpenFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
3049 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3050 lock_ReleaseWrite(&scp->rw);
3052 sysUserp = RDR_GetLocalSystemUser();
3055 * Skip the open check if the request is coming from the local system account.
3056 * The local system has no tokens and therefore any requests sent to a file
3057 * server will fail. Unfortunately, there are special system processes that
3058 * perform actions on files and directories in preparation for memory mapping
3059 * executables. If the open check fails, the real request from the user process
3060 * will never be issued.
3062 * Permitting the file system to allow subsequent operations to proceed does
3063 * not compromise security. All requests to obtain file data or directory
3064 * enumerations will subsequently fail if they are not submitted under the
3065 * context of a process for that have access to the necessary credentials.
3068 if ( userp == sysUserp)
3070 osi_Log1(afsd_logp, "RDR_OpenFileEntry LOCAL_SYSTEM access check skipped scp=0x%p",
3072 pResultCB->GrantedAccess = OpenCB->DesiredAccess;
3073 pResultCB->FileAccess = AFS_FILE_ACCESS_NOLOCK;
3084 "RDR_OpenFileEntry repeating open check scp=0x%p userp=0x%p code=0x%x",
3087 code = cm_CheckNTOpen(scp, OpenCB->DesiredAccess, OpenCB->ShareAccess,
3089 OpenCB->ProcessId, OpenCB->Identifier,
3092 code = RDR_CheckAccess(scp, userp, &req, OpenCB->DesiredAccess, &pResultCB->GrantedAccess);
3093 cm_CheckNTOpenDone(scp, userp, &req, &ldp);
3094 } while (count < 100 && (code == CM_ERROR_RETRY || code == CM_ERROR_WOULDBLOCK));
3098 * If we are restricting sharing, we should do so with a suitable
3101 if (code == 0 && scp->fileType == CM_SCACHETYPE_FILE && !(OpenCB->ShareAccess & FILE_SHARE_WRITE)) {
3103 LARGE_INTEGER LOffset, LLength;
3106 LOffset.HighPart = SMB_FID_QLOCK_HIGH;
3107 LOffset.LowPart = SMB_FID_QLOCK_LOW;
3108 LLength.HighPart = 0;
3109 LLength.LowPart = SMB_FID_QLOCK_LENGTH;
3112 * If we are not opening the file for writing, then we don't
3113 * try to get an exclusive lock. No one else should be able to
3114 * get an exclusive lock on the file anyway, although someone
3115 * else can get a shared lock.
3117 if ((OpenCB->ShareAccess & FILE_SHARE_READ) || !(OpenCB->DesiredAccess & AFS_ACCESS_WRITE))
3119 sLockType = LOCKING_ANDX_SHARED_LOCK;
3124 key = cm_GenerateKey(CM_SESSION_IFS, SMB_FID_QLOCK_PID, OpenCB->Identifier);
3126 lock_ObtainWrite(&scp->rw);
3127 code = cm_Lock(scp, sLockType, LOffset, LLength, key, 0, userp, &req, NULL);
3128 lock_ReleaseWrite(&scp->rw);
3131 code = CM_ERROR_SHARING_VIOLATION;
3132 pResultCB->FileAccess = AFS_FILE_ACCESS_NOLOCK;
3134 if (sLockType == LOCKING_ANDX_SHARED_LOCK)
3135 pResultCB->FileAccess = AFS_FILE_ACCESS_SHARED;
3137 pResultCB->FileAccess = AFS_FILE_ACCESS_EXCLUSIVE;
3140 pResultCB->FileAccess = AFS_FILE_ACCESS_NOLOCK;
3143 cm_ReleaseUser(sysUserp);
3144 if (code == 0 && bHoldFid)
3145 RDR_FlagScpInUse( scp, FALSE );
3146 cm_ReleaseSCache(scp);
3149 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3150 (*ResultCB)->ResultStatus = status;
3151 osi_Log2(afsd_logp, "RDR_OpenFileEntry FAILURE code=0x%x status=0x%x",
3154 (*ResultCB)->ResultStatus = 0;
3155 (*ResultCB)->ResultBufferLength = sizeof( AFSFileOpenResultCB);
3156 osi_Log0(afsd_logp, "RDR_OpenFileEntry SUCCESS");
3162 RDR_ReleaseFileAccess( IN cm_user_t *userp,
3163 IN AFSFileID FileId,
3164 IN AFSFileAccessReleaseCB *ReleaseFileCB,
3166 IN DWORD ResultBufferLength,
3167 IN OUT AFSCommResult **ResultCB)
3170 unsigned int sLockType;
3171 LARGE_INTEGER LOffset, LLength;
3172 cm_scache_t *scp = NULL;
3178 RDR_InitReq(&req, bWow64);
3180 osi_Log4(afsd_logp, "RDR_ReleaseFileAccess File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3181 FileId.Cell, FileId.Volume,
3182 FileId.Vnode, FileId.Unique);
3184 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
3186 osi_Log0(afsd_logp, "RDR_ReleaseFileAccess out of memory");
3190 memset( *ResultCB, '\0', sizeof( AFSCommResult));
3192 if (ReleaseFileCB->FileAccess == AFS_FILE_ACCESS_NOLOCK)
3195 /* Process the release */
3196 Fid.cell = FileId.Cell;
3197 Fid.volume = FileId.Volume;
3198 Fid.vnode = FileId.Vnode;
3199 Fid.unique = FileId.Unique;
3200 Fid.hash = FileId.Hash;
3202 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
3204 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3205 (*ResultCB)->ResultStatus = status;
3206 osi_Log2(afsd_logp, "RDR_ReleaseFileAccess cm_GetSCache FID failure code=0x%x status=0x%x",
3211 if (ReleaseFileCB->FileAccess == AFS_FILE_ACCESS_SHARED)
3212 sLockType = LOCKING_ANDX_SHARED_LOCK;
3216 key = cm_GenerateKey(CM_SESSION_IFS, SMB_FID_QLOCK_PID, ReleaseFileCB->Identifier);
3218 LOffset.HighPart = SMB_FID_QLOCK_HIGH;
3219 LOffset.LowPart = SMB_FID_QLOCK_LOW;
3220 LLength.HighPart = 0;
3221 LLength.LowPart = SMB_FID_QLOCK_LENGTH;
3223 lock_ObtainWrite(&scp->rw);
3225 code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_LOCK);
3228 code = cm_Unlock(scp, sLockType, LOffset, LLength, key, 0, userp, &req);
3230 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
3232 if (code == CM_ERROR_RANGE_NOT_LOCKED)
3234 osi_Log3(afsd_logp, "RDR_ReleaseFileAccess Range Not Locked -- FileAccess 0x%x ProcessId 0x%x HandleId 0x%x",
3235 ReleaseFileCB->FileAccess, ReleaseFileCB->ProcessId, ReleaseFileCB->Identifier);
3239 lock_ReleaseWrite(&scp->rw);
3241 osi_Log0(afsd_logp, "RDR_ReleaseFileAccessEntry SUCCESS");
3245 HexCheckSum(unsigned char * buf, int buflen, unsigned char * md5cksum)
3248 static char tr[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
3251 return "buffer length too small to HexCheckSum";
3253 for (i=0;i<16;i++) {
3256 buf[i*2] = tr[k / 16];
3257 buf[i*2+1] = tr[k % 16];
3265 * Extent requests from the file system are triggered when a file
3266 * page is not resident in the Windows cache. The file system is
3267 * responsible for loading the page but cannot block the request
3268 * while doing so. The AFS Redirector forwards the requests to
3269 * the AFS cache manager while indicating to Windows that the page
3270 * is not yet available. A polling operation will then ensue with
3271 * the AFS Redirector issuing a RDR_RequestFileExtentsXXX call for
3272 * each poll attempt. As each request is received and processed
3273 * by a separate worker thread in the service, this can lead to
3274 * contention by multiple threads attempting to claim the same
3275 * cm_buf_t objects. Therefore, it is important that
3277 * (a) the service avoid processing more than one overlapping
3278 * extent request at a time
3279 * (b) background daemon processing be used to avoid blocking
3282 * Beginning with the 20091122 build of the redirector, the redirector
3283 * will not issue an additional RDR_RequestFileExtentsXXX call for
3284 * each poll request. Instead, afsd_service is required to track
3285 * the requests and return them to the redirector or fail the
3286 * portions of the request that cannot be satisfied.
3288 * The request processing returns any extents that can be returned
3289 * immediately to the redirector. The rest of the requested range(s)
3290 * are queued as background operations using RDR_BkgFetch().
3293 /* do the background fetch. */
3295 RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
3296 cm_user_t *userp, cm_req_t *reqp)
3302 osi_hyper_t fetched;
3303 osi_hyper_t tblocksize;
3306 cm_buf_t *bufp = NULL;
3307 DWORD dwResultBufferLength;
3308 AFSSetFileExtentsCB *pResultCB;
3312 int reportErrorToRedir = 0;
3313 int force_retry = 0;
3315 FileId.Cell = scp->fid.cell;
3316 FileId.Volume = scp->fid.volume;
3317 FileId.Vnode = scp->fid.vnode;
3318 FileId.Unique = scp->fid.unique;
3319 FileId.Hash = scp->fid.hash;
3321 fetched.LowPart = 0;
3322 fetched.HighPart = 0;
3323 tblocksize = ConvertLongToLargeInteger(cm_data.buf_blockSize);
3326 length.LowPart = p3;
3327 length.HighPart = p4;
3329 end = LargeIntegerAdd(base, length);
3331 osi_Log5(afsd_logp, "Starting BKG Fetch scp 0x%p offset 0x%x:%x length 0x%x:%x",
3332 scp, p2, p1, p4, p3);
3335 * Make sure we have a callback.
3336 * This is necessary so that we can return access denied
3337 * if a callback cannot be granted.
3339 lock_ObtainWrite(&scp->rw);
3340 code = cm_SyncOp(scp, NULL, userp, reqp, PRSFS_READ,
3341 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3343 lock_ReleaseWrite(&scp->rw);
3344 osi_Log2(afsd_logp, "RDR_BkgFetch cm_SyncOp failure scp=0x%p code=0x%x",
3346 smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
3347 RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
3350 lock_ReleaseWrite(&scp->rw);
3352 dwResultBufferLength = (DWORD)(sizeof( AFSSetFileExtentsCB) + sizeof( AFSFileExtentCB) * (length.QuadPart / cm_data.blockSize + 1));
3353 pResultCB = (AFSSetFileExtentsCB *)malloc( dwResultBufferLength );
3355 return CM_ERROR_RETRY;
3357 memset( pResultCB, '\0', dwResultBufferLength );
3358 pResultCB->FileId = FileId;
3360 for ( code = 0, offset = base;
3361 code == 0 && LargeIntegerLessThan(offset, end);
3362 offset = LargeIntegerAdd(offset, tblocksize) )
3364 int bBufRelease = TRUE;
3367 lock_ReleaseWrite(&scp->rw);
3371 code = buf_Get(scp, &offset, reqp, &bufp);
3374 * any error from buf_Get() is non-fatal.
3375 * we need to re-queue this extent fetch.
3382 lock_ObtainWrite(&scp->rw);
3386 code = cm_GetBuffer(scp, bufp, NULL, userp, reqp);
3388 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3389 #ifdef VALIDATE_CHECK_SUM
3395 if (bufp->flags & CM_BUF_DIRTY)
3396 cm_BufWrite(scp, &bufp->offset, cm_data.buf_blockSize, CM_BUF_WRITE_SCP_LOCKED, userp, reqp);
3398 lock_ObtainWrite(&buf_globalLock);
3399 if (!(bufp->flags & CM_BUF_DIRTY) &&
3400 bufp->cmFlags == 0 &&
3401 !(bufp->qFlags & CM_BUF_QREDIR)) {
3402 buf_InsertToRedirQueue(scp, bufp);
3403 lock_ReleaseWrite(&buf_globalLock);
3405 #ifdef VALIDATE_CHECK_SUM
3406 buf_ComputeCheckSum(bufp);
3408 pResultCB->FileExtents[count].Flags = 0;
3409 pResultCB->FileExtents[count].FileOffset.QuadPart = bufp->offset.QuadPart;
3410 pResultCB->FileExtents[count].CacheOffset.QuadPart = bufp->datap - RDR_extentBaseAddress;
3411 pResultCB->FileExtents[count].Length = cm_data.blockSize;
3413 fetched = LargeIntegerAdd(fetched, tblocksize);
3414 bBufRelease = FALSE;
3416 #ifdef VALIDATE_CHECK_SUM
3418 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3419 snprintf( dbgstr, 1024,
3420 "RDR_BkgFetch md5 %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3422 scp->fid.volume, scp->fid.vnode, scp->fid.unique,
3423 pResultCB->FileExtents[count].FileOffset.HighPart,
3424 pResultCB->FileExtents[count].FileOffset.LowPart,
3425 pResultCB->FileExtents[count].CacheOffset.HighPart,
3426 pResultCB->FileExtents[count].CacheOffset.LowPart);
3427 OutputDebugStringA( dbgstr);
3430 osi_Log4(afsd_logp, "RDR_BkgFetch Extent2FS bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3431 bufp, bufp->offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3433 lock_ReleaseWrite(&buf_globalLock);
3434 if ((bufp->cmFlags != 0) || (bufp->flags & CM_BUF_DIRTY)) {
3435 /* An I/O operation is already in progress */
3437 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",
3438 bufp, bufp->offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3440 osi_Log4(afsd_logp, "RDR_BkgFetch Extent2FS Already held by Redirector bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3441 bufp, bufp->offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3445 osi_Log4(afsd_logp, "RDR_BkgFetch Extent2FS Already held by Redirector bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3446 bufp, bufp->offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3450 * depending on what the error from cm_GetBuffer is
3451 * it may or may not be fatal. Only return fatal errors.
3452 * Re-queue a request for others.
3454 osi_Log5(afsd_logp, "RDR_BkgFetch Extent2FS FAILURE bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x code 0x%x",
3455 bufp, offset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize, code);
3457 case CM_ERROR_NOACCESS:
3458 case CM_ERROR_NOSUCHFILE:
3459 case CM_ERROR_NOSUCHPATH:
3460 case CM_ERROR_NOSUCHVOLUME:
3461 case CM_ERROR_NOSUCHCELL:
3462 case CM_ERROR_INVAL:
3463 case CM_ERROR_BADFD:
3464 case CM_ERROR_CLOCKSKEW:
3466 case CM_ERROR_QUOTA:
3467 case CM_ERROR_LOCK_CONFLICT:
3469 case CM_ERROR_INVAL_NET_RESP:
3470 case CM_ERROR_UNKNOWN:
3472 * these are fatal errors. deliver what we can
3475 reportErrorToRedir = 1;
3479 * non-fatal errors. re-queue the exent
3481 code = CM_ERROR_RETRY;
3491 lock_ObtainWrite(&scp->rw);
3495 /* wakeup anyone who is waiting */
3496 if (scp->flags & CM_SCACHEFLAG_WAITING) {
3497 osi_Log1(afsd_logp, "RDR Bkg Fetch Waking scp 0x%p", scp);
3498 osi_Wakeup((LONG_PTR) &scp->flags);
3500 lock_ReleaseWrite(&scp->rw);
3503 pResultCB->ExtentCount = count;
3504 RDR_SetFileExtents( pResultCB, dwResultBufferLength);
3508 if (reportErrorToRedir) {
3509 smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
3510 RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
3513 osi_Log4(afsd_logp, "Ending BKG Fetch scp 0x%p code 0x%x fetched 0x%x:%x",
3514 scp, code, fetched.HighPart, fetched.LowPart);
3516 return force_retry ? CM_ERROR_RETRY : code;
3521 RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
3522 IN AFSFileID FileId,
3523 IN AFSRequestExtentsCB *RequestExtentsCB,
3525 IN OUT DWORD * ResultBufferLength,
3526 IN OUT AFSSetFileExtentsCB **ResultCB)
3528 AFSSetFileExtentsCB *pResultCB = NULL;
3532 cm_scache_t *scp = NULL;
3535 afs_uint32 code = 0;
3537 LARGE_INTEGER ByteOffset, BeginOffset, EndOffset, QueueOffset;
3538 afs_uint32 QueueLength;
3540 BOOLEAN bBufRelease = TRUE;
3542 RDR_InitReq(&req, bWow64);
3543 req.flags |= CM_REQ_NORETRY;
3545 osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3546 FileId.Cell, FileId.Volume,
3547 FileId.Vnode, FileId.Unique);
3548 osi_Log4(afsd_logp, "... Flags 0x%x ByteOffset 0x%x:%x Length 0x%x",
3549 RequestExtentsCB->Flags,
3550 RequestExtentsCB->ByteOffset.HighPart, RequestExtentsCB->ByteOffset.LowPart,
3551 RequestExtentsCB->Length);
3552 Length = sizeof( AFSSetFileExtentsCB) + sizeof( AFSFileExtentCB) * (RequestExtentsCB->Length / cm_data.blockSize + 1);
3554 pResultCB = *ResultCB = (AFSSetFileExtentsCB *)malloc( Length );
3555 if (*ResultCB == NULL) {
3556 *ResultBufferLength = 0;
3559 *ResultBufferLength = Length;
3561 memset( pResultCB, '\0', Length );
3562 pResultCB->FileId = FileId;
3564 Fid.cell = FileId.Cell;
3565 Fid.volume = FileId.Volume;
3566 Fid.vnode = FileId.Vnode;
3567 Fid.unique = FileId.Unique;
3568 Fid.hash = FileId.Hash;
3570 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
3572 osi_Log1(afsd_logp, "RDR_RequestFileExtentsAsync cm_GetSCache FID failure code=0x%x",
3574 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3579 * Make sure we have a callback.
3580 * This is necessary so that we can return access denied
3581 * if a callback cannot be granted.
3583 lock_ObtainWrite(&scp->rw);
3584 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
3585 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3586 lock_ReleaseWrite(&scp->rw);
3588 cm_ReleaseSCache(scp);
3589 osi_Log2(afsd_logp, "RDR_RequestFileExtentsAsync cm_SyncOp failure scp=0x%p code=0x%x",
3591 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3592 RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
3596 /* Allocate the extents from the buffer package */
3598 ByteOffset = BeginOffset = RequestExtentsCB->ByteOffset,
3599 EndOffset.QuadPart = ByteOffset.QuadPart + RequestExtentsCB->Length;
3600 code == 0 && ByteOffset.QuadPart < EndOffset.QuadPart;
3601 ByteOffset.QuadPart += cm_data.blockSize)
3603 BOOL bHaveBuffer = FALSE;
3606 thyper.QuadPart = ByteOffset.QuadPart;
3608 code = buf_Get(scp, &thyper, &req, &bufp);
3610 lock_ObtainMutex(&bufp->mx);
3613 if (bufp->qFlags & CM_BUF_QREDIR) {
3615 } else if (bufp->flags & CM_BUF_DIRTY) {
3616 bHaveBuffer = FALSE;
3618 code = buf_CleanAsyncLocked(scp, bufp, &req, 0, NULL);
3623 case CM_ERROR_RETRY:
3624 /* Couldn't flush it, obtain it asynchronously so we don't block the thread. */
3625 bHaveBuffer = FALSE;
3629 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3630 RDR_SetFileStatus(&FileId, &userp->authgroup, status);
3631 bHaveBuffer = FALSE;
3636 osi_hyper_t minLength; /* effective end of file */
3638 lock_ObtainRead(&scp->rw);
3639 bHaveBuffer = cm_HaveBuffer(scp, bufp, TRUE);
3641 if (LargeIntegerGreaterThan(scp->length, scp->serverLength))
3642 minLength = scp->serverLength;
3644 minLength = scp->length;
3646 if (LargeIntegerGreaterThanOrEqualTo(bufp->offset, minLength)) {
3648 memset(bufp->datap, 0, cm_data.buf_blockSize);
3649 bufp->dataVersion = scp->dataVersion;
3652 else if (bufp->dataVersion == CM_BUF_VERSION_BAD) {
3653 bufp->dataVersion = scp->dataVersion;
3656 else if ((RequestExtentsCB->Flags & AFS_EXTENT_FLAG_CLEAN) &&
3657 ByteOffset.QuadPart <= bufp->offset.QuadPart &&
3658 EndOffset.QuadPart >= bufp->offset.QuadPart + cm_data.blockSize)
3660 memset(bufp->datap, 0, cm_data.blockSize);
3661 bufp->dataVersion = scp->dataVersion;
3662 buf_SetDirty(bufp, &req, 0, cm_data.blockSize, userp);
3665 lock_ReleaseRead(&scp->rw);
3669 * if this buffer is already up to date, skip it.
3672 if (ByteOffset.QuadPart == BeginOffset.QuadPart) {
3673 BeginOffset.QuadPart += cm_data.blockSize;
3675 QueueLength = (afs_uint32)(ByteOffset.QuadPart - BeginOffset.QuadPart);
3676 QueueOffset = BeginOffset;
3677 BeginOffset = ByteOffset;
3680 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3681 #ifdef VALIDATE_CHECK_SUM
3687 lock_ObtainWrite(&buf_globalLock);
3688 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3689 buf_InsertToRedirQueue(scp, bufp);
3690 lock_ReleaseWrite(&buf_globalLock);
3692 #ifdef VALIDATE_CHECK_SUM
3693 buf_ComputeCheckSum(bufp);
3695 /* we already have the buffer, return it now */
3696 pResultCB->FileExtents[count].Flags = 0;
3697 pResultCB->FileExtents[count].FileOffset = ByteOffset;
3698 pResultCB->FileExtents[count].CacheOffset.QuadPart = bufp->datap - RDR_extentBaseAddress;
3699 pResultCB->FileExtents[count].Length = cm_data.blockSize;
3702 bBufRelease = FALSE;
3704 #ifdef VALIDATE_CHECK_SUM
3706 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3707 snprintf( dbgstr, 1024,
3708 "RDR_RequestFileExtentsAsync md5 %s vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3710 scp->fid.volume, scp->fid.vnode, scp->fid.unique,
3711 pResultCB->FileExtents[count].FileOffset.HighPart,
3712 pResultCB->FileExtents[count].FileOffset.LowPart,
3713 pResultCB->FileExtents[count].CacheOffset.HighPart,
3714 pResultCB->FileExtents[count].CacheOffset.LowPart);
3715 OutputDebugStringA( dbgstr);
3718 osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync Extent2FS bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3719 bufp, ByteOffset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3721 lock_ReleaseWrite(&buf_globalLock);
3726 * The service is not handing off the extent to the redirector in this pass.
3727 * However, we know the buffer is in recent use so move the buffer to the
3728 * front of the queue
3730 lock_ObtainWrite(&buf_globalLock);
3731 buf_MoveToHeadOfRedirQueue(scp, bufp);
3732 lock_ReleaseWrite(&buf_globalLock);
3734 osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync Extent2FS Already held by Redirector bufp 0x%p foffset 0x%p coffset 0x%p len 0x%x",
3735 bufp, ByteOffset.QuadPart, bufp->datap - RDR_extentBaseAddress, cm_data.blockSize);
3739 lock_ReleaseMutex(&bufp->mx);
3744 req.flags &= ~CM_REQ_NORETRY;
3745 cm_QueueBKGRequest(scp, RDR_BkgFetch, QueueOffset.LowPart, QueueOffset.HighPart,
3746 QueueLength, 0, userp, &req);
3747 osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
3748 QueueOffset.HighPart, QueueOffset.LowPart, QueueLength);
3749 req.flags |= CM_REQ_NORETRY;
3752 /* No error from buf_Get() can be fatal */
3753 osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync buf_Get FAILURE offset 0x%x:%x code 0x%x",
3754 BeginOffset.HighPart, BeginOffset.LowPart, code);
3758 if (BeginOffset.QuadPart != EndOffset.QuadPart) {
3759 afs_uint32 length = (afs_uint32)(EndOffset.QuadPart - BeginOffset.QuadPart);
3761 req.flags &= ~CM_REQ_NORETRY;
3762 cm_QueueBKGRequest(scp, RDR_BkgFetch, BeginOffset.LowPart, BeginOffset.HighPart,
3763 length, 0, userp, &req);
3764 osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
3765 BeginOffset.HighPart, BeginOffset.LowPart, length);
3767 cm_ReleaseSCache(scp);
3769 (*ResultCB)->ExtentCount = count;
3770 osi_Log1(afsd_logp, "RDR_RequestFileExtentsAsync replying with 0x%x extent records", count);
3775 * When processing an extent release the extents must be accepted back by
3776 * the service even if there is an error condition returned to the redirector.
3777 * For example, there may no longer be a callback present or the file may
3778 * have been deleted on the file server. Regardless, the extents must be
3779 * put back into the pool.
3782 RDR_ReleaseFileExtents( IN cm_user_t *userp,
3783 IN AFSFileID FileId,
3784 IN AFSReleaseExtentsCB *ReleaseExtentsCB,
3786 IN DWORD ResultBufferLength,
3787 IN OUT AFSCommResult **ResultCB)
3790 cm_scache_t *scp = NULL;
3801 #ifdef VALIDATE_CHECK_SUM
3802 char md5dbg[33], md5dbg2[33], md5dbg3[33];
3807 RDR_InitReq(&req, bWow64);
3809 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3810 FileId.Cell, FileId.Volume,
3811 FileId.Vnode, FileId.Unique);
3813 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
3819 sizeof( AFSCommResult));
3821 /* Process the release */
3822 Fid.cell = FileId.Cell;
3823 Fid.volume = FileId.Volume;
3824 Fid.vnode = FileId.Vnode;
3825 Fid.unique = FileId.Unique;
3826 Fid.hash = FileId.Hash;
3828 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
3830 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3831 (*ResultCB)->ResultStatus = status;
3832 osi_Log2(afsd_logp, "RDR_ReleaseFileExtents cm_GetSCache FID failure code=0x%x status=0x%x",
3836 deleted = scp && (scp->flags & CM_SCACHEFLAG_DELETED);
3839 * We do not stop processing as a result of being unable to find the cm_scache object.
3840 * If this occurs something really bad has happened since the cm_scache object must have
3841 * been recycled while extents were held by the redirector. However, we will be resilient
3842 * and carry on without it.
3844 * If the file is known to be deleted, there is no point attempting to ask the
3845 * file server about it or update the attributes.
3847 if (scp && ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart &&
3852 memset(&setAttr, 0, sizeof(cm_attr_t));
3853 lock_ObtainWrite(&scp->rw);
3854 if (ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart) {
3856 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents new length fid vol 0x%x vno 0x%x length 0x%x:%x",
3857 scp->fid.volume, scp->fid.vnode,
3858 ReleaseExtentsCB->AllocationSize.HighPart,
3859 ReleaseExtentsCB->AllocationSize.LowPart);
3861 setAttr.mask |= CM_ATTRMASK_LENGTH;
3862 setAttr.length.LowPart = ReleaseExtentsCB->AllocationSize.LowPart;
3863 setAttr.length.HighPart = ReleaseExtentsCB->AllocationSize.HighPart;
3865 lock_ReleaseWrite(&scp->rw);
3867 code = cm_SetAttr(scp, &setAttr, userp, &req);
3870 for ( count = 0; count < ReleaseExtentsCB->ExtentCount; count++) {
3871 AFSFileExtentCB * pExtent = &ReleaseExtentsCB->FileExtents[count];
3873 thyper.QuadPart = pExtent->FileOffset.QuadPart;
3875 bufp = buf_Find(&Fid, &thyper);
3877 if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
3878 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3879 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3880 Fid.volume, Fid.vnode,
3881 pExtent->FileOffset.HighPart,
3882 pExtent->FileOffset.LowPart);
3883 osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; previously released",
3884 pExtent->CacheOffset.HighPart,
3885 pExtent->CacheOffset.LowPart);
3887 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3888 Fid.volume, Fid.vnode,
3889 pExtent->FileOffset.HighPart,
3890 pExtent->FileOffset.LowPart);
3891 osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; owned by redirector",
3892 pExtent->CacheOffset.HighPart,
3893 pExtent->CacheOffset.LowPart);
3899 if (pExtent->Flags & AFS_EXTENT_FLAG_IN_USE) {
3900 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x",
3901 Fid.volume, Fid.vnode,
3902 pExtent->FileOffset.HighPart,
3903 pExtent->FileOffset.LowPart);
3904 osi_Log2(afsd_logp, "... coffset 0x%x:%x IN_USE by file system",
3905 pExtent->CacheOffset.HighPart,
3906 pExtent->CacheOffset.LowPart);
3908 /* Move the buffer to the front of the queue */
3909 lock_ObtainWrite(&buf_globalLock);
3910 buf_MoveToHeadOfRedirQueue(scp, bufp);
3911 lock_ReleaseWrite(&buf_globalLock);
3916 if (bufp->datap - RDR_extentBaseAddress == pExtent->CacheOffset.QuadPart) {
3917 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
3918 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents extent vol 0x%x vno 0x%x foffset 0x%x:%x not held by file system",
3919 Fid.volume, Fid.vnode, pExtent->FileOffset.HighPart,
3920 pExtent->FileOffset.LowPart);
3921 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
3922 pExtent->CacheOffset.HighPart,
3923 pExtent->CacheOffset.LowPart);
3925 osi_Log4(afsd_logp, "RDR_ReleaseFileExtents bufp 0x%p vno 0x%x foffset 0x%x:%x",
3926 bufp, bufp->fid.vnode, pExtent->FileOffset.HighPart,
3927 pExtent->FileOffset.LowPart);
3928 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
3929 pExtent->CacheOffset.HighPart,
3930 pExtent->CacheOffset.LowPart);
3932 if (pExtent->Flags || ReleaseExtentsCB->Flags) {
3933 lock_ObtainMutex(&bufp->mx);
3934 if ( (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_RELEASE) ||
3935 (pExtent->Flags & AFS_EXTENT_FLAG_RELEASE) )
3937 if (bufp->qFlags & CM_BUF_QREDIR) {
3938 lock_ObtainWrite(&buf_globalLock);
3939 if (bufp->qFlags & CM_BUF_QREDIR) {
3940 buf_RemoveFromRedirQueue(scp, bufp);
3941 buf_ReleaseLocked(bufp, TRUE);
3943 lock_ReleaseWrite(&buf_globalLock);
3946 snprintf( dbgstr, 1024,
3947 "RDR_ReleaseFileExtents releasing: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3948 Fid.volume, Fid.vnode, Fid.unique,
3949 pExtent->FileOffset.HighPart,
3950 pExtent->FileOffset.LowPart,
3951 pExtent->CacheOffset.HighPart,
3952 pExtent->CacheOffset.LowPart);
3953 OutputDebugStringA( dbgstr);
3958 snprintf( dbgstr, 1024,
3959 "RDR_ReleaseFileExtents not releasing: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
3960 Fid.volume, Fid.vnode, Fid.unique,
3961 pExtent->FileOffset.HighPart,
3962 pExtent->FileOffset.LowPart,
3963 pExtent->CacheOffset.HighPart,
3964 pExtent->CacheOffset.LowPart);
3965 OutputDebugStringA( dbgstr);
3967 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents not releasing vol 0x%x vno 0x%x foffset 0x%x:%x",
3968 Fid.volume, Fid.vnode,
3969 pExtent->FileOffset.HighPart,
3970 pExtent->FileOffset.LowPart);
3971 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
3972 pExtent->CacheOffset.HighPart,
3973 pExtent->CacheOffset.LowPart);
3976 if ( (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
3977 (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY) )
3979 #ifdef VALIDATE_CHECK_SUM
3981 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
3985 * if the saved checksum matches the checksum of the current state of the buffer
3986 * then the buffer is the same as what was given to the kernel.
3988 if ( buf_ValidateCheckSum(bufp) ) {
3989 buf_ComputeCheckSum(bufp);
3991 if (pExtent->Flags & AFS_EXTENT_FLAG_MD5_SET)
3994 HexCheckSum(md5dbg2, sizeof(md5dbg2), pExtent->MD5);
3995 HexCheckSum(md5dbg3, sizeof(md5dbg3), bufp->md5cksum);
3997 if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
4000 snprintf( dbgstr, 1024,
4001 "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",
4002 md5dbg, md5dbg2,md5dbg3,
4003 Fid.volume, Fid.vnode, Fid.unique,
4004 pExtent->FileOffset.HighPart,
4005 pExtent->FileOffset.LowPart,
4006 pExtent->CacheOffset.HighPart,
4007 pExtent->CacheOffset.LowPart);
4008 OutputDebugStringA( dbgstr);
4010 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set and checksums do not match! vol 0x%x vno 0x%x foffset 0x%x:%x",
4011 Fid.volume, Fid.vnode,
4012 pExtent->FileOffset.HighPart,
4013 pExtent->FileOffset.LowPart);
4014 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
4015 pExtent->CacheOffset.HighPart,
4016 pExtent->CacheOffset.LowPart);
4017 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4021 snprintf( dbgstr, 1024,
4022 "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",
4023 md5dbg, md5dbg2, md5dbg3,
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);
4031 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
4032 Fid.volume, Fid.vnode,
4033 pExtent->FileOffset.HighPart,
4034 pExtent->FileOffset.LowPart);
4035 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
4036 pExtent->CacheOffset.HighPart,
4037 pExtent->CacheOffset.LowPart);
4041 snprintf( dbgstr, 1024,
4042 "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",
4043 Fid.volume, Fid.vnode, Fid.unique,
4044 pExtent->FileOffset.HighPart,
4045 pExtent->FileOffset.LowPart,
4046 pExtent->CacheOffset.HighPart,
4047 pExtent->CacheOffset.LowPart);
4048 OutputDebugStringA( dbgstr);
4050 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
4051 Fid.volume, Fid.vnode,
4052 pExtent->FileOffset.HighPart,
4053 pExtent->FileOffset.LowPart);
4054 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
4055 pExtent->CacheOffset.HighPart,
4056 pExtent->CacheOffset.LowPart);
4059 buf_ComputeCheckSum(bufp);
4061 if (pExtent->Flags & AFS_EXTENT_FLAG_MD5_SET)
4063 HexCheckSum(md5dbg3, sizeof(md5dbg3), bufp->md5cksum);
4064 if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
4066 snprintf( dbgstr, 1024,
4067 "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",
4068 md5dbg, md5dbg2,md5dbg3,
4069 Fid.volume, Fid.vnode, Fid.unique,
4070 pExtent->FileOffset.HighPart,
4071 pExtent->FileOffset.LowPart,
4072 pExtent->CacheOffset.HighPart,
4073 pExtent->CacheOffset.LowPart);
4074 OutputDebugStringA( dbgstr);
4076 snprintf( dbgstr, 1024,
4077 "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",
4078 md5dbg, md5dbg2,md5dbg3,
4079 Fid.volume, Fid.vnode, Fid.unique,
4080 pExtent->FileOffset.HighPart,
4081 pExtent->FileOffset.LowPart,
4082 pExtent->CacheOffset.HighPart,
4083 pExtent->CacheOffset.LowPart);
4084 OutputDebugStringA( dbgstr);
4087 snprintf( dbgstr, 1024,
4088 "RDR_ReleaseFileExtents dirty flag set: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4089 Fid.volume, Fid.vnode, Fid.unique,
4090 pExtent->FileOffset.HighPart,
4091 pExtent->FileOffset.LowPart,
4092 pExtent->CacheOffset.HighPart,
4093 pExtent->CacheOffset.LowPart);
4094 OutputDebugStringA( dbgstr);
4097 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4100 #else /* !VALIDATE_CHECK_SUM */
4101 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4103 #endif /* VALIDATE_CHECK_SUM */
4105 #ifdef VALIDATE_CHECK_SUM
4108 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
4110 if ( !buf_ValidateCheckSum(bufp) ) {
4111 buf_ComputeCheckSum(bufp);
4113 HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
4114 snprintf( dbgstr, 1024,
4115 "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",
4117 Fid.volume, Fid.vnode, Fid.unique,
4118 pExtent->FileOffset.HighPart,
4119 pExtent->FileOffset.LowPart,
4120 pExtent->CacheOffset.HighPart,
4121 pExtent->CacheOffset.LowPart);
4122 OutputDebugStringA( dbgstr);
4124 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag not set but extent has changed vol 0x%x vno 0x%x foffset 0x%x:%x",
4125 Fid.volume, Fid.vnode,
4126 pExtent->FileOffset.HighPart,
4127 pExtent->FileOffset.LowPart);
4128 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
4129 pExtent->CacheOffset.HighPart,
4130 pExtent->CacheOffset.LowPart);
4131 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4134 buf_ComputeCheckSum(bufp);
4136 HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
4137 snprintf( dbgstr, 1024,
4138 "RDR_ReleaseFileExtents dirty flag not set: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4139 Fid.volume, Fid.vnode, Fid.unique,
4140 pExtent->FileOffset.HighPart,
4141 pExtent->FileOffset.LowPart,
4142 pExtent->CacheOffset.HighPart,
4143 pExtent->CacheOffset.LowPart);
4144 OutputDebugStringA( dbgstr);
4146 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents dirty flag not set: vol 0x%x vno 0x%x foffset 0x%x:%x",
4147 Fid.volume, Fid.vnode,
4148 pExtent->FileOffset.HighPart,
4149 pExtent->FileOffset.LowPart);
4150 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
4151 pExtent->CacheOffset.HighPart,
4152 pExtent->CacheOffset.LowPart);
4155 #endif /* VALIDATE_CHECK_SUM */
4156 lock_ReleaseMutex(&bufp->mx);
4161 char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
4164 for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
4165 if (wbp->datap == datap)
4170 snprintf( dbgstr, 1024,
4171 "RDR_ReleaseFileExtents non-matching extent vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4172 Fid.volume, Fid.vnode, Fid.unique,
4173 pExtent->FileOffset.HighPart,
4174 pExtent->FileOffset.LowPart,
4175 pExtent->CacheOffset.HighPart,
4176 pExtent->CacheOffset.LowPart);
4177 OutputDebugStringA( dbgstr);
4179 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents non-matching extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4180 Fid.volume, Fid.vnode,
4181 pExtent->FileOffset.HighPart,
4182 pExtent->FileOffset.LowPart);
4183 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
4184 pExtent->CacheOffset.HighPart,
4185 pExtent->CacheOffset.LowPart);
4186 osi_Log5( afsd_logp, "... belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
4187 wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
4192 char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
4195 for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
4196 if (wbp->datap == datap)
4201 snprintf( dbgstr, 1024,
4202 "RDR_ReleaseFileExtents unknown extent vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4203 Fid.volume, Fid.vnode, Fid.unique,
4204 pExtent->FileOffset.HighPart,
4205 pExtent->FileOffset.LowPart,
4206 pExtent->CacheOffset.HighPart,
4207 pExtent->CacheOffset.LowPart);
4208 OutputDebugStringA( dbgstr);
4210 osi_Log4( afsd_logp, "RDR_ReleaseFileExtents unknown extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4211 Fid.volume, Fid.vnode,
4212 pExtent->FileOffset.HighPart,
4213 pExtent->FileOffset.LowPart);
4214 osi_Log2( afsd_logp, "... coffset 0x%x:%x",
4215 pExtent->CacheOffset.HighPart,
4216 pExtent->CacheOffset.LowPart);
4217 osi_Log5( afsd_logp, "... belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
4218 wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
4225 } else if (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_FLUSH) {
4226 lock_ObtainWrite(&scp->rw);
4227 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
4228 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
4229 lock_ReleaseWrite(&scp->rw);
4231 code = cm_FSync(scp, userp, &req, FALSE);
4234 osi_hyper_t offset = {0,0};
4235 afs_uint32 length = 0;
4236 afs_uint32 rights = 0;
4238 lock_ObtainWrite(&scp->rw);
4239 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
4240 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
4241 lock_ReleaseWrite(&scp->rw);
4244 * there is at least one dirty extent on this file. queue up background store
4245 * requests for contiguous blocks
4247 for ( count = 0; count < ReleaseExtentsCB->ExtentCount; count++) {
4248 if (ReleaseExtentsCB->FileExtents[count].FileOffset.QuadPart == offset.QuadPart + length &&
4249 length + cm_data.buf_blockSize <= cm_chunkSize)
4251 length += cm_data.buf_blockSize;
4253 if (!(offset.QuadPart == 0 && length == 0))
4254 cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
4255 length, 0, userp, &req);
4256 offset.QuadPart = ReleaseExtentsCB->FileExtents[count].FileOffset.QuadPart;
4257 length = cm_data.buf_blockSize;
4260 cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
4261 length, 0, userp, &req);
4264 cm_ReleaseSCache(scp);
4267 osi_Log5(afsd_logp, "RDR_ReleaseFileExtents File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x Released %d",
4268 FileId.Cell, FileId.Volume,
4269 FileId.Vnode, FileId.Unique, released);
4270 if (code && code != CM_ERROR_WOULDBLOCK) {
4271 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4272 (*ResultCB)->ResultStatus = status;
4273 osi_Log2(afsd_logp, "RDR_ReleaseFileExtents FAILURE code=0x%x status=0x%x",
4276 (*ResultCB)->ResultStatus = 0;
4277 osi_Log0(afsd_logp, "RDR_ReleaseFileExtents SUCCESS");
4279 (*ResultCB)->ResultBufferLength = 0;
4285 RDR_ProcessReleaseFileExtentsResult( IN AFSReleaseFileExtentsResultCB *ReleaseFileExtentsResultCB,
4286 IN DWORD ResultBufferLength)
4288 afs_uint32 code = 0;
4292 unsigned int fileno, extentno, total_extents = 0;
4293 AFSReleaseFileExtentsResultFileCB *pNextFileCB;
4295 #ifdef VALIDATE_CHECK_SUM
4296 char md5dbg[33], md5dbg2[33], md5dbg3[33];
4300 RDR_InitReq(&req, FALSE);
4302 for ( fileno = 0, pNextFileCB = &ReleaseFileExtentsResultCB->Files[0];
4303 fileno < ReleaseFileExtentsResultCB->FileCount;
4305 AFSReleaseFileExtentsResultFileCB *pFileCB = pNextFileCB;
4306 cm_user_t *userp = NULL;
4308 cm_scache_t * scp = NULL;
4314 userp = RDR_UserFromAuthGroup( &pFileCB->AuthGroup);
4316 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult %d.%d.%d.%d",
4317 pFileCB->FileId.Cell, pFileCB->FileId.Volume,
4318 pFileCB->FileId.Vnode, pFileCB->FileId.Unique);
4320 /* Process the release */
4321 Fid.cell = pFileCB->FileId.Cell;
4322 Fid.volume = pFileCB->FileId.Volume;
4323 Fid.vnode = pFileCB->FileId.Vnode;
4324 Fid.unique = pFileCB->FileId.Unique;
4325 Fid.hash = pFileCB->FileId.Hash;
4327 if (Fid.cell == 0) {
4328 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult Invalid FID %d.%d.%d.%d",
4329 Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
4330 code = CM_ERROR_INVAL;
4334 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
4336 osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult cm_GetSCache FID failure code=0x%x",
4339 * A failure to find the cm_scache object cannot prevent the service
4340 * from accepting the extents back from the redirector.
4344 deleted = scp && (scp->flags & CM_SCACHEFLAG_DELETED);
4346 /* if the scp was not found, do not perform the length check */
4347 if (scp && (pFileCB->AllocationSize.QuadPart != scp->length.QuadPart)) {
4350 memset(&setAttr, 0, sizeof(cm_attr_t));
4351 lock_ObtainWrite(&scp->rw);
4352 if (pFileCB->AllocationSize.QuadPart != scp->length.QuadPart) {
4353 osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult length change vol 0x%x vno 0x%x length 0x%x:%x",
4354 scp->fid.volume, scp->fid.vnode,
4355 pFileCB->AllocationSize.HighPart,
4356 pFileCB->AllocationSize.LowPart);
4357 setAttr.mask |= CM_ATTRMASK_LENGTH;
4358 setAttr.length.LowPart = pFileCB->AllocationSize.LowPart;
4359 setAttr.length.HighPart = pFileCB->AllocationSize.HighPart;
4361 lock_ReleaseWrite(&scp->rw);
4363 code = cm_SetAttr(scp, &setAttr, userp, &req);
4366 for ( extentno = 0; extentno < pFileCB->ExtentCount; total_extents++, extentno++ ) {
4367 AFSFileExtentCB *pExtent = &pFileCB->FileExtents[extentno];
4369 thyper.QuadPart = pExtent->FileOffset.QuadPart;
4371 bufp = buf_Find(&Fid, &thyper);
4373 if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
4374 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
4375 osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4376 Fid.volume, Fid.vnode,
4377 pExtent->FileOffset.HighPart,
4378 pExtent->FileOffset.LowPart);
4379 osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; previously released",
4380 pExtent->CacheOffset.HighPart,
4381 pExtent->CacheOffset.LowPart);
4383 osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4384 Fid.volume, Fid.vnode,
4385 pExtent->FileOffset.HighPart,
4386 pExtent->FileOffset.LowPart);
4387 osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; owned by redirector",
4388 pExtent->CacheOffset.HighPart,
4389 pExtent->CacheOffset.LowPart);
4395 if (pExtent->Flags & AFS_EXTENT_FLAG_IN_USE) {
4396 osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4397 Fid.volume, Fid.vnode,
4398 pExtent->FileOffset.HighPart,
4399 pExtent->FileOffset.LowPart);
4400 osi_Log2(afsd_logp, "... coffset 0x%x:%x IN_USE by file system",
4401 pExtent->CacheOffset.HighPart,
4402 pExtent->CacheOffset.LowPart);
4404 /* Move the buffer to the front of the queue */
4405 lock_ObtainWrite(&buf_globalLock);
4406 buf_MoveToHeadOfRedirQueue(scp, bufp);
4407 lock_ReleaseWrite(&buf_globalLock);
4412 if (bufp->datap - RDR_extentBaseAddress == pExtent->CacheOffset.QuadPart) {
4413 if (!(bufp->qFlags & CM_BUF_QREDIR)) {
4414 osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4415 Fid.volume, Fid.vnode,
4416 pExtent->FileOffset.HighPart,
4417 pExtent->FileOffset.LowPart);
4418 osi_Log2(afsd_logp, "... coffset 0x%x:%x not held by file system",
4419 pExtent->CacheOffset.HighPart,
4420 pExtent->CacheOffset.LowPart);
4422 snprintf(dbgstr, 1024,
4423 "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",
4424 ReleaseFileExtentsResultCB->Flags, pExtent->Flags,
4425 Fid.volume, Fid.vnode, Fid.unique,
4426 pExtent->FileOffset.HighPart,
4427 pExtent->FileOffset.LowPart,
4428 pExtent->CacheOffset.HighPart,
4429 pExtent->CacheOffset.LowPart);
4430 OutputDebugStringA( dbgstr);
4433 osi_Log5(afsd_logp, "RDR_ProcessReleaseFileExtentsResult bufp 0x%p foffset 0x%x:%x coffset 0x%x:%x",
4434 bufp, pExtent->FileOffset.HighPart, pExtent->FileOffset.LowPart,
4435 pExtent->CacheOffset.HighPart, pExtent->CacheOffset.LowPart);
4437 if (pExtent->Flags || ReleaseFileExtentsResultCB->Flags) {
4438 lock_ObtainMutex(&bufp->mx);
4439 if ( (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_RELEASE) ||
4440 (pExtent->Flags & AFS_EXTENT_FLAG_RELEASE) )
4442 if (bufp->qFlags & CM_BUF_QREDIR) {
4443 lock_ObtainWrite(&buf_globalLock);
4444 if (bufp->qFlags & CM_BUF_QREDIR) {
4445 buf_RemoveFromRedirQueue(scp, bufp);
4446 buf_ReleaseLocked(bufp, TRUE);
4448 lock_ReleaseWrite(&buf_globalLock);
4452 snprintf(dbgstr, 1024,
4453 "RDR_ProcessReleaseFileExtentsResult extent released: vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4454 Fid.volume, Fid.vnode, Fid.unique,
4455 pExtent->FileOffset.HighPart,
4456 pExtent->FileOffset.LowPart,
4457 pExtent->CacheOffset.HighPart,
4458 pExtent->CacheOffset.LowPart);
4459 OutputDebugStringA( dbgstr);
4464 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult not releasing vol 0x%x vno 0x%x foffset 0x%x:%x",
4465 Fid.volume, Fid.vnode,
4466 pExtent->FileOffset.HighPart,
4467 pExtent->FileOffset.LowPart);
4468 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4469 pExtent->CacheOffset.HighPart,
4470 pExtent->CacheOffset.LowPart);
4472 snprintf(dbgstr, 1024,
4473 "RDR_ProcessReleaseFileExtentsResult not released! vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4474 Fid.volume, Fid.vnode, Fid.unique,
4475 pExtent->FileOffset.HighPart,
4476 pExtent->FileOffset.LowPart,
4477 pExtent->CacheOffset.HighPart,
4478 pExtent->CacheOffset.LowPart);
4479 OutputDebugStringA( dbgstr);
4483 if ((ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
4484 (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY))
4486 #ifdef VALIDATE_CHECK_SUM
4487 if ( buf_ValidateCheckSum(bufp) ) {
4489 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
4490 if (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_MD5_SET)
4491 HexCheckSum(md5dbg2, sizeof(md5dbg2), pExtent->MD5);
4493 buf_ComputeCheckSum(bufp);
4495 HexCheckSum(md5dbg3, sizeof(md5dbg), bufp->md5cksum);
4497 if (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_MD5_SET)
4499 if (memcmp(bufp->md5cksum, pExtent->MD5, 16))
4502 snprintf(dbgstr, 1024,
4503 "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",
4505 Fid.volume, Fid.vnode, Fid.unique,
4506 pExtent->FileOffset.HighPart,
4507 pExtent->FileOffset.LowPart,
4508 pExtent->CacheOffset.HighPart,
4509 pExtent->CacheOffset.LowPart);
4510 OutputDebugStringA( dbgstr);
4513 "RDR_ProcessReleaseFileExtentsResult dirty flag set and checksums do not match! vol 0x%x vno 0x%x foffset 0x%x:%x",
4514 Fid.volume, Fid.vnode,
4515 pExtent->FileOffset.HighPart,
4516 pExtent->FileOffset.LowPart);
4518 "... coffset 0x%x:%x",
4519 pExtent->CacheOffset.HighPart,
4520 pExtent->CacheOffset.LowPart);
4523 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4528 snprintf(dbgstr, 1024,
4529 "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",
4530 md5dbg, md5dbg2, md5dbg3,
4531 Fid.volume, Fid.vnode, Fid.unique,
4532 pExtent->FileOffset.HighPart,
4533 pExtent->FileOffset.LowPart,
4534 pExtent->CacheOffset.HighPart,
4535 pExtent->CacheOffset.LowPart);
4536 OutputDebugStringA( dbgstr);
4539 "RDR_ProcessReleaseFileExtentsResult dirty flag set but extent has not changed vol 0x%x vno 0x%x foffset 0x%x:%x",
4540 Fid.volume, Fid.vnode,
4541 pExtent->FileOffset.HighPart,
4542 pExtent->FileOffset.LowPart);
4544 "... coffset 0x%x:%x",
4545 pExtent->CacheOffset.HighPart,
4546 pExtent->CacheOffset.LowPart);
4550 #else /* !VALIDATE_CHECK_SUM */
4552 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4556 snprintf(dbgstr, 1024,
4557 "RDR_ProcessReleaseFileExtentsResult dirty! vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4558 Fid.volume, Fid.vnode, Fid.unique,
4559 pExtent->FileOffset.HighPart,
4560 pExtent->FileOffset.LowPart,
4561 pExtent->CacheOffset.HighPart,
4562 pExtent->CacheOffset.LowPart);
4563 OutputDebugStringA( dbgstr);
4565 #endif /* VALIDATE_CHECK_SUM */
4567 #ifdef VALIDATE_CHECK_SUM
4570 HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
4572 if (!buf_ValidateCheckSum(bufp) ) {
4573 buf_ComputeCheckSum(bufp);
4575 HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
4576 snprintf(dbgstr, 1024,
4577 "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",
4579 Fid.volume, Fid.vnode, Fid.unique,
4580 pExtent->FileOffset.HighPart,
4581 pExtent->FileOffset.LowPart,
4582 pExtent->CacheOffset.HighPart,
4583 pExtent->CacheOffset.LowPart);
4584 OutputDebugStringA( dbgstr);
4586 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult dirty flag NOT set but extent has changed! vol 0x%x vno 0x%x foffset 0x%x:%x",
4587 Fid.volume, Fid.vnode,
4588 pExtent->FileOffset.HighPart,
4589 pExtent->FileOffset.LowPart);
4590 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4591 pExtent->CacheOffset.HighPart,
4592 pExtent->CacheOffset.LowPart);
4595 buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
4599 buf_ComputeCheckSum(bufp);
4601 HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
4602 snprintf(dbgstr, 1024,
4603 "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",
4605 Fid.volume, Fid.vnode, Fid.unique,
4606 pExtent->FileOffset.HighPart,
4607 pExtent->FileOffset.LowPart,
4608 pExtent->CacheOffset.HighPart,
4609 pExtent->CacheOffset.LowPart);
4610 OutputDebugStringA( dbgstr);
4614 #endif /* VALIDATE_CHECK_SUM */
4615 lock_ReleaseMutex(&bufp->mx);
4619 /* CacheOffset doesn't match bufp->datap */
4620 char * datap = RDR_extentBaseAddress + pExtent->CacheOffset.QuadPart;
4623 for (wbp = cm_data.buf_allp; wbp; wbp = wbp->allp) {
4624 if (wbp->datap == datap)
4629 snprintf(dbgstr, 1024,
4630 "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",
4631 Fid.volume, Fid.vnode, Fid.unique,
4632 pExtent->FileOffset.HighPart,
4633 pExtent->FileOffset.LowPart,
4634 pExtent->CacheOffset.HighPart,
4635 pExtent->CacheOffset.LowPart,
4637 OutputDebugStringA( dbgstr);
4639 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult non-matching extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4640 Fid.volume, Fid.vnode,
4641 pExtent->FileOffset.HighPart,
4642 pExtent->FileOffset.LowPart);
4643 osi_Log3(afsd_logp, "... coffset 0x%x:%x flags 0x%x",
4644 pExtent->CacheOffset.HighPart,
4645 pExtent->CacheOffset.LowPart,
4648 osi_Log5(afsd_logp, "... coffset belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
4649 wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
4651 osi_Log0(afsd_logp, "... coffset cannot be found");
4655 if (pExtent->Flags & AFS_EXTENT_FLAG_UNKNOWN) {
4656 osi_Log4(afsd_logp, "RDR_ReleaseFileExtentsResult extent vol 0x%x vno 0x%x foffset 0x%x:%x",
4657 Fid.volume, Fid.vnode, pExtent->FileOffset.HighPart,
4658 pExtent->FileOffset.LowPart);
4659 osi_Log2(afsd_logp, "... coffset 0x%x:%x UNKNOWN to redirector; cm_buf not found -- recycled?",
4660 pExtent->CacheOffset.HighPart,
4661 pExtent->CacheOffset.LowPart);
4667 snprintf(dbgstr, 1024,
4668 "RDR_ProcessReleaseFileExtentsResult buf not found vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
4669 Fid.volume, Fid.vnode, Fid.unique,
4670 pExtent->FileOffset.HighPart,
4671 pExtent->FileOffset.LowPart,
4672 pExtent->CacheOffset.HighPart,
4673 pExtent->CacheOffset.LowPart);
4674 OutputDebugStringA( dbgstr);
4676 osi_Log4(afsd_logp, "RDR_ProcessReleaseFileExtentsResult buf not found vol 0x%x vno 0x%x foffset 0x%x:%x",
4677 Fid.volume, Fid.vnode,
4678 pExtent->FileOffset.HighPart,
4679 pExtent->FileOffset.LowPart);
4680 osi_Log2(afsd_logp, "... coffset 0x%x:%x",
4681 pExtent->CacheOffset.HighPart,
4682 pExtent->CacheOffset.LowPart);
4687 osi_hyper_t offset = {0,0};
4688 afs_uint32 length = 0;
4691 * there is at least one dirty extent on this file. queue up background store
4692 * requests for contiguous blocks
4694 for ( extentno = 0; extentno < pFileCB->ExtentCount; extentno++ ) {
4695 AFSFileExtentCB *pExtent = &pFileCB->FileExtents[extentno];
4696 if (pExtent->FileOffset.QuadPart == offset.QuadPart + length &&
4697 length < cm_chunkSize) {
4698 length += cm_data.buf_blockSize;
4700 if (!(offset.QuadPart == 0 && length == 0))
4701 cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
4702 length, 0, userp, &req);
4703 offset.QuadPart = pExtent->FileOffset.QuadPart;
4704 length = cm_data.buf_blockSize;
4707 cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
4708 length, 0, userp, &req);
4711 osi_Log5(afsd_logp, "RDR_ProcessReleaseFileExtentsResult File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x Released %d",
4712 Fid.cell, Fid.volume, Fid.vnode, Fid.unique, released);
4716 cm_ReleaseUser(userp);
4718 cm_ReleaseSCache(scp);
4720 p = (char *)pFileCB;
4721 p += sizeof(AFSReleaseFileExtentsResultFileCB);
4722 p += sizeof(AFSFileExtentCB) * (pFileCB->ExtentCount - 1);
4723 pNextFileCB = (AFSReleaseFileExtentsResultFileCB *)p;
4726 if (total_extents == 0) {
4727 osi_Log0(afsd_logp, "RDR_ProcessReleaseFileExtentsResult is empty");
4728 code = CM_ERROR_RETRY;
4732 osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult FAILURE code=0x%x", code);
4734 osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult DONE code=0x%x", code);
4740 RDR_ReleaseFailedSetFileExtents( IN cm_user_t *userp,
4741 IN AFSSetFileExtentsCB *SetFileExtentsResultCB,
4742 IN DWORD ResultBufferLength)
4744 afs_uint32 code = 0;
4746 unsigned int extentno;
4748 cm_scache_t * scp = NULL;
4751 RDR_InitReq(&req, FALSE);
4753 osi_Log4(afsd_logp, "RDR_ReleaseFailedSetFileExtents %d.%d.%d.%d",
4754 SetFileExtentsResultCB->FileId.Cell, SetFileExtentsResultCB->FileId.Volume,
4755 SetFileExtentsResultCB->FileId.Vnode, SetFileExtentsResultCB->FileId.Unique);
4757 /* Process the release */
4758 Fid.cell = SetFileExtentsResultCB->FileId.Cell;
4759 Fid.volume = SetFileExtentsResultCB->FileId.Volume;
4760 Fid.vnode = SetFileExtentsResultCB->FileId.Vnode;
4761 Fid.unique = SetFileExtentsResultCB->FileId.Unique;
4762 Fid.hash = SetFileExtentsResultCB->FileId.Hash;
4764 if (Fid.cell == 0) {
4765 osi_Log4(afsd_logp, "RDR_ReleaseFailedSetFile Invalid FID %d.%d.%d.%d",
4766 Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
4767 code = CM_ERROR_INVAL;
4771 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
4773 osi_Log1(afsd_logp, "RDR_ReleaseFailedSetFileExtents cm_GetSCache FID failure code=0x%x",
4775 /* Failure to find the cm_scache object cannot block return of the extents */
4778 for ( extentno = 0; extentno < SetFileExtentsResultCB->ExtentCount; extentno++ ) {
4781 AFSFileExtentCB *pExtent = &SetFileExtentsResultCB->FileExtents[extentno];
4783 thyper.QuadPart = pExtent->FileOffset.QuadPart;
4785 bufp = buf_Find(&Fid, &thyper);
4787 osi_Log5(afsd_logp, "RDR_ReleaseFailedSetFileExtents bufp 0x%p foffset 0x%x:%x coffset 0x%x:%x",
4788 bufp, pExtent->FileOffset.HighPart, pExtent->FileOffset.LowPart,
4789 pExtent->CacheOffset.HighPart, pExtent->CacheOffset.LowPart);
4791 lock_ObtainMutex(&bufp->mx);
4792 if (bufp->qFlags & CM_BUF_QREDIR) {
4793 lock_ObtainWrite(&buf_globalLock);
4794 if (bufp->qFlags & CM_BUF_QREDIR) {
4795 buf_RemoveFromRedirQueue(scp, bufp);
4796 buf_ReleaseLocked(bufp, TRUE);
4798 lock_ReleaseWrite(&buf_globalLock);
4800 lock_ReleaseMutex(&bufp->mx);
4807 cm_ReleaseUser(userp);
4809 cm_ReleaseSCache(scp);
4811 osi_Log1(afsd_logp, "RDR_ReleaseFailedSetFileExtents DONE code=0x%x", code);
4816 RDR_PioctlOpen( IN cm_user_t *userp,
4817 IN AFSFileID ParentId,
4818 IN AFSPIOCtlOpenCloseRequestCB *pPioctlCB,
4820 IN DWORD ResultBufferLength,
4821 IN OUT AFSCommResult **ResultCB)
4827 RDR_InitReq(&req, bWow64);
4829 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
4835 sizeof( AFSCommResult));
4837 /* Get the active directory */
4838 ParentFid.cell = ParentId.Cell;
4839 ParentFid.volume = ParentId.Volume;
4840 ParentFid.vnode = ParentId.Vnode;
4841 ParentFid.unique = ParentId.Unique;
4842 ParentFid.hash = ParentId.Hash;
4844 /* Get the root directory */
4845 RootFid.cell = pPioctlCB->RootId.Cell;
4846 RootFid.volume = pPioctlCB->RootId.Volume;
4847 RootFid.vnode = pPioctlCB->RootId.Vnode;
4848 RootFid.unique = pPioctlCB->RootId.Unique;
4849 RootFid.hash = pPioctlCB->RootId.Hash;
4851 /* Create the pioctl index */
4852 RDR_SetupIoctl(pPioctlCB->RequestId, &ParentFid, &RootFid, userp, &req);
4859 RDR_PioctlClose( IN cm_user_t *userp,
4860 IN AFSFileID ParentId,
4861 IN AFSPIOCtlOpenCloseRequestCB *pPioctlCB,
4863 IN DWORD ResultBufferLength,
4864 IN OUT AFSCommResult **ResultCB)
4866 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
4872 sizeof( AFSCommResult));
4874 /* Cleanup the pioctl index */
4875 RDR_CleanupIoctl(pPioctlCB->RequestId);
4882 RDR_PioctlWrite( IN cm_user_t *userp,
4883 IN AFSFileID ParentId,
4884 IN AFSPIOCtlIORequestCB *pPioctlCB,
4886 IN DWORD ResultBufferLength,
4887 IN OUT AFSCommResult **ResultCB)
4889 AFSPIOCtlIOResultCB *pResultCB;
4890 cm_scache_t *dscp = NULL;
4895 RDR_InitReq(&req, bWow64);
4897 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4903 sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4905 pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
4907 code = RDR_IoctlWrite(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer);
4909 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4910 (*ResultCB)->ResultStatus = status;
4914 pResultCB->BytesProcessed = pPioctlCB->BufferLength;
4915 (*ResultCB)->ResultBufferLength = sizeof( AFSPIOCtlIOResultCB);
4919 RDR_PioctlRead( IN cm_user_t *userp,
4920 IN AFSFileID ParentId,
4921 IN AFSPIOCtlIORequestCB *pPioctlCB,
4923 IN BOOL bIsLocalSystem,
4924 IN DWORD ResultBufferLength,
4925 IN OUT AFSCommResult **ResultCB)
4927 AFSPIOCtlIOResultCB *pResultCB;
4928 cm_scache_t *dscp = NULL;
4932 afs_uint32 pflags = (bIsLocalSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
4934 RDR_InitReq(&req, bWow64);
4936 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4942 sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
4944 pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
4946 code = RDR_IoctlRead(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer,
4947 &pResultCB->BytesProcessed, pflags);
4949 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
4950 (*ResultCB)->ResultStatus = status;
4954 (*ResultCB)->ResultBufferLength = sizeof( AFSPIOCtlIOResultCB);
4958 RDR_ByteRangeLockSync( IN cm_user_t *userp,
4959 IN AFSFileID FileId,
4960 IN AFSByteRangeLockRequestCB *pBRLRequestCB,
4962 IN DWORD ResultBufferLength,
4963 IN OUT AFSCommResult **ResultCB)
4965 AFSByteRangeLockResultCB *pResultCB = NULL;
4966 LARGE_INTEGER ProcessId;
4968 cm_scache_t *scp = NULL;
4976 ProcessId.QuadPart = pBRLRequestCB->ProcessId;
4978 RDR_InitReq(&req, bWow64);
4980 osi_Log4(afsd_logp, "RDR_ByteRangeLockSync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
4981 FileId.Cell, FileId.Volume,
4982 FileId.Vnode, FileId.Unique);
4983 osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
4984 ProcessId.HighPart, ProcessId.LowPart);
4986 Length = sizeof( AFSByteRangeLockResultCB) + ((pBRLRequestCB->Count - 1) * sizeof(AFSByteRangeLockResult));
4987 if (Length > ResultBufferLength) {
4988 *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult));
4991 memset( *ResultCB, 0, sizeof(AFSCommResult));
4992 (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
4996 *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
4999 memset( *ResultCB, '\0', Length + sizeof( AFSCommResult) );
5000 (*ResultCB)->ResultBufferLength = Length;
5002 pResultCB = (AFSByteRangeLockResultCB *)(*ResultCB)->ResultData;
5003 pResultCB->FileId = FileId;
5004 pResultCB->Count = pBRLRequestCB->Count;
5006 /* Allocate the extents from the buffer package */
5007 Fid.cell = FileId.Cell;
5008 Fid.volume = FileId.Volume;
5009 Fid.vnode = FileId.Vnode;
5010 Fid.unique = FileId.Unique;
5011 Fid.hash = FileId.Hash;
5013 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
5015 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5016 (*ResultCB)->ResultStatus = status;
5017 (*ResultCB)->ResultBufferLength = 0;
5018 osi_Log2(afsd_logp, "RDR_ByteRangeLockSync cm_GetSCache FID failure code=0x%x status=0x%x",
5023 lock_ObtainWrite(&scp->rw);
5025 /* start by looking up the file's end */
5026 code = cm_SyncOp(scp, NULL, userp, &req, 0,
5027 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
5029 lock_ReleaseWrite(&scp->rw);
5030 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5031 (*ResultCB)->ResultStatus = status;
5032 (*ResultCB)->ResultBufferLength = 0;
5033 osi_Log3(afsd_logp, "RDR_ByteRangeLockSync cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
5038 /* the scp is now locked and current */
5039 key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
5041 for ( i=0; i<pBRLRequestCB->Count; i++ ) {
5042 pResultCB->Result[i].LockType = pBRLRequestCB->Request[i].LockType;
5043 pResultCB->Result[i].Offset = pBRLRequestCB->Request[i].Offset;
5044 pResultCB->Result[i].Length = pBRLRequestCB->Request[i].Length;
5047 pBRLRequestCB->Request[i].LockType == AFS_BYTE_RANGE_LOCK_TYPE_SHARED,
5048 pBRLRequestCB->Request[i].Offset,
5049 pBRLRequestCB->Request[i].Length,
5050 key, 0, userp, &req, NULL);
5053 osi_Log4(afsd_logp, "RDR_ByteRangeLockSync FAILURE code 0x%x type 0x%u offset 0x%x:%x",
5055 pBRLRequestCB->Request[i].LockType,
5056 pBRLRequestCB->Request[i].Offset.HighPart,
5057 pBRLRequestCB->Request[i].Offset.LowPart);
5058 osi_Log2(afsd_logp, "... length 0x%x:%x",
5059 pBRLRequestCB->Request[i].Length.HighPart,
5060 pBRLRequestCB->Request[i].Length.LowPart);
5065 pResultCB->Result[i].Status = 0;
5067 case CM_ERROR_WOULDBLOCK:
5068 pResultCB->Result[i].Status = STATUS_FILE_LOCK_CONFLICT;
5071 pResultCB->Result[i].Status = STATUS_LOCK_NOT_GRANTED;
5075 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
5076 lock_ReleaseWrite(&scp->rw);
5077 cm_ReleaseSCache(scp);
5079 (*ResultCB)->ResultStatus = 0;
5080 osi_Log0(afsd_logp, "RDR_ByteRangeLockSync SUCCESS");
5085 RDR_ByteRangeUnlock( IN cm_user_t *userp,
5086 IN AFSFileID FileId,
5087 IN AFSByteRangeUnlockRequestCB *pBRURequestCB,
5089 IN DWORD ResultBufferLength,
5090 IN OUT AFSCommResult **ResultCB)
5092 AFSByteRangeUnlockResultCB *pResultCB = NULL;
5093 LARGE_INTEGER ProcessId;
5095 cm_scache_t *scp = NULL;
5103 ProcessId.QuadPart = pBRURequestCB->ProcessId;
5105 RDR_InitReq(&req, bWow64);
5107 osi_Log4(afsd_logp, "RDR_ByteRangeUnlock File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5108 FileId.Cell, FileId.Volume,
5109 FileId.Vnode, FileId.Unique);
5110 osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
5111 ProcessId.HighPart, ProcessId.LowPart);
5113 Length = sizeof( AFSByteRangeUnlockResultCB) + ((pBRURequestCB->Count - 1) * sizeof(AFSByteRangeLockResult));
5114 if (Length > ResultBufferLength) {
5115 *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult));
5118 memset( *ResultCB, 0, sizeof(AFSCommResult));
5119 (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5123 *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
5126 memset( *ResultCB, '\0', Length + sizeof( AFSCommResult) );
5127 (*ResultCB)->ResultBufferLength = Length;
5129 pResultCB = (AFSByteRangeUnlockResultCB *)(*ResultCB)->ResultData;
5130 pResultCB->Count = pBRURequestCB->Count;
5132 /* Allocate the extents from the buffer package */
5133 Fid.cell = FileId.Cell;
5134 Fid.volume = FileId.Volume;
5135 Fid.vnode = FileId.Vnode;
5136 Fid.unique = FileId.Unique;
5137 Fid.hash = FileId.Hash;
5139 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
5141 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5142 (*ResultCB)->ResultStatus = status;
5143 (*ResultCB)->ResultBufferLength = 0;
5144 osi_Log2(afsd_logp, "RDR_ByteRangeUnlock cm_GetSCache FID failure code=0x%x status=0x%x",
5149 lock_ObtainWrite(&scp->rw);
5151 /* start by looking up the file's end */
5152 code = cm_SyncOp(scp, NULL, userp, &req, 0,
5153 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
5155 lock_ReleaseWrite(&scp->rw);
5156 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5157 (*ResultCB)->ResultStatus = status;
5158 (*ResultCB)->ResultBufferLength = 0;
5159 osi_Log3(afsd_logp, "RDR_ByteRangeUnlock cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
5164 /* the scp is now locked and current */
5165 key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
5167 for ( i=0; i<pBRURequestCB->Count; i++ ) {
5168 pResultCB->Result[i].LockType = pBRURequestCB->Request[i].LockType;
5169 pResultCB->Result[i].Offset = pBRURequestCB->Request[i].Offset;
5170 pResultCB->Result[i].Length = pBRURequestCB->Request[i].Length;
5172 code = cm_Unlock(scp,
5173 pBRURequestCB->Request[i].LockType == AFS_BYTE_RANGE_LOCK_TYPE_SHARED,
5174 pBRURequestCB->Request[i].Offset,
5175 pBRURequestCB->Request[i].Length,
5176 key, CM_UNLOCK_FLAG_MATCH_RANGE, userp, &req);
5179 osi_Log4(afsd_logp, "RDR_ByteRangeUnlock FAILURE code 0x%x type 0x%u offset 0x%x:%x",
5180 code, pBRURequestCB->Request[i].LockType,
5181 pBRURequestCB->Request[i].Offset.HighPart,
5182 pBRURequestCB->Request[i].Offset.LowPart);
5183 osi_Log2(afsd_logp, "... length 0x%x:%x",
5184 pBRURequestCB->Request[i].Length.HighPart,
5185 pBRURequestCB->Request[i].Length.LowPart);
5187 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5188 pResultCB->Result[i].Status = status;
5191 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
5192 lock_ReleaseWrite(&scp->rw);
5193 cm_ReleaseSCache(scp);
5195 (*ResultCB)->ResultStatus = 0;
5196 osi_Log0(afsd_logp, "RDR_ByteRangeUnlock SUCCESS");
5201 RDR_ByteRangeUnlockAll( IN cm_user_t *userp,
5202 IN AFSFileID FileId,
5203 IN AFSByteRangeUnlockRequestCB *pBRURequestCB,
5205 IN DWORD ResultBufferLength,
5206 IN OUT AFSCommResult **ResultCB)
5208 AFSByteRangeUnlockResultCB *pResultCB = NULL;
5209 LARGE_INTEGER ProcessId;
5210 cm_scache_t *scp = NULL;
5217 ProcessId.QuadPart = pBRURequestCB->ProcessId;
5219 RDR_InitReq(&req, bWow64);
5221 osi_Log4(afsd_logp, "RDR_ByteRangeUnlockAll File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5222 FileId.Cell, FileId.Volume,
5223 FileId.Vnode, FileId.Unique);
5224 osi_Log2(afsd_logp, "... ProcessId 0x%x:%x",
5225 ProcessId.HighPart, ProcessId.LowPart);
5227 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5230 memset( *ResultCB, '\0', sizeof( AFSCommResult));
5231 (*ResultCB)->ResultBufferLength = 0;
5233 /* Allocate the extents from the buffer package */
5234 Fid.cell = FileId.Cell;
5235 Fid.volume = FileId.Volume;
5236 Fid.vnode = FileId.Vnode;
5237 Fid.unique = FileId.Unique;
5238 Fid.hash = FileId.Hash;
5240 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
5242 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5243 (*ResultCB)->ResultStatus = status;
5244 (*ResultCB)->ResultBufferLength = 0;
5245 osi_Log2(afsd_logp, "RDR_ByteRangeUnlockAll cm_GetSCache FID failure code=0x%x status=0x%x",
5250 lock_ObtainWrite(&scp->rw);
5252 /* start by looking up the file's end */
5253 code = cm_SyncOp(scp, NULL, userp, &req, 0,
5254 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
5256 lock_ReleaseWrite(&scp->rw);
5257 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5258 (*ResultCB)->ResultStatus = status;
5259 (*ResultCB)->ResultBufferLength = 0;
5260 osi_Log3(afsd_logp, "RDR_ByteRangeUnlockAll cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
5265 /* the scp is now locked and current */
5266 key = cm_GenerateKey(CM_SESSION_IFS, ProcessId.QuadPart, 0);
5268 code = cm_UnlockByKey(scp, key, 0, userp, &req);
5270 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
5271 lock_ReleaseWrite(&scp->rw);
5272 cm_ReleaseSCache(scp);
5274 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5275 (*ResultCB)->ResultStatus = status;
5278 osi_Log1(afsd_logp, "RDR_ByteRangeUnlockAll FAILURE code 0x%x", code);
5280 osi_Log0(afsd_logp, "RDR_ByteRangeUnlockAll SUCCESS");
5286 RDR_GetVolumeInfo( IN cm_user_t *userp,
5287 IN AFSFileID FileId,
5289 IN DWORD ResultBufferLength,
5290 IN OUT AFSCommResult **ResultCB)
5292 AFSVolumeInfoCB *pResultCB = NULL;
5294 cm_scache_t *scp = NULL;
5295 cm_volume_t *volp = NULL;
5297 cm_cell_t *cellp = NULL;
5302 FILETIME ft = {0x832cf000, 0x01abfcc4}; /* October 1, 1982 00:00:00 +0600 */
5304 char volName[32]="(unknown)";
5305 char offLineMsg[256]="server temporarily inaccessible";
5306 char motd[256]="server temporarily inaccessible";
5308 AFSFetchVolumeStatus volStat;
5312 struct rx_connection * rxconnp;
5316 RDR_InitReq(&req, bWow64);
5318 osi_Log4(afsd_logp, "RDR_GetVolumeInfo File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5319 FileId.Cell, FileId.Volume,
5320 FileId.Vnode, FileId.Unique);
5322 Length = sizeof( AFSCommResult) + sizeof(AFSVolumeInfoCB);
5323 if (sizeof(AFSVolumeInfoCB) > ResultBufferLength) {
5324 *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
5327 memset( *ResultCB, 0, sizeof(AFSCommResult));
5328 (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5332 *ResultCB = (AFSCommResult *)malloc( Length );
5335 memset( *ResultCB, '\0', Length );
5336 (*ResultCB)->ResultBufferLength = sizeof(AFSVolumeInfoCB);
5337 pResultCB = (AFSVolumeInfoCB *)(*ResultCB)->ResultData;
5339 if (FileId.Cell != 0) {
5340 cm_SetFid(&Fid, FileId.Cell, FileId.Volume, 1, 1);
5341 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
5343 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5344 (*ResultCB)->ResultStatus = status;
5345 (*ResultCB)->ResultBufferLength = 0;
5346 osi_Log2(afsd_logp, "RDR_GetVolumeInfo cm_GetSCache FID failure code=0x%x status=0x%x",
5351 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
5352 osi_Log0(afsd_logp, "RDR_GetVolumeInfo Object Name Invalid - Cell = 0");
5355 lock_ObtainWrite(&scp->rw);
5358 pResultCB->SectorsPerAllocationUnit = 1;
5359 pResultCB->BytesPerSector = 1024;
5361 pResultCB->CellID = scp->fid.cell;
5362 pResultCB->VolumeID = scp->fid.volume;
5363 pResultCB->Characteristics = FILE_REMOTE_DEVICE;
5364 pResultCB->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK |
5365 FILE_SUPPORTS_HARD_LINKS | FILE_SUPPORTS_REPARSE_POINTS;
5367 if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
5368 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
5370 pResultCB->TotalAllocationUnits.QuadPart = 100;
5371 memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
5373 pResultCB->AvailableAllocationUnits.QuadPart = 0;
5374 pResultCB->Characteristics |= FILE_READ_ONLY_DEVICE;
5376 pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( "Freelance.Local.Root", -1, pResultCB->VolumeLabel,
5377 (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
5378 if ( pResultCB->VolumeLabelLength )
5379 pResultCB->VolumeLabelLength--;
5381 memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
5383 volp = cm_GetVolumeByFID(&scp->fid);
5385 code = CM_ERROR_NOSUCHVOLUME;
5388 volType = cm_VolumeType(volp, scp->fid.volume);
5390 pResultCB->Characteristics |= ((volType == ROVOL || volType == BACKVOL) ? FILE_READ_ONLY_DEVICE : 0);
5392 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
5393 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
5399 OfflineMsg = offLineMsg;
5401 lock_ReleaseWrite(&scp->rw);
5405 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
5408 rxconnp = cm_GetRxConn(connp);
5409 code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
5410 &volStat, &Name, &OfflineMsg, &MOTD);
5411 rx_PutConnection(rxconnp);
5413 } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
5414 code = cm_MapRPCError(code, &req);
5418 if (volStat.MaxQuota)
5420 pResultCB->TotalAllocationUnits.QuadPart = volStat.MaxQuota;
5421 if (volType == ROVOL || volType == BACKVOL) {
5422 pResultCB->AvailableAllocationUnits.QuadPart = 0;
5426 pResultCB->AvailableAllocationUnits.QuadPart =
5427 min(volStat.MaxQuota - volStat.BlocksInUse, volStat.PartBlocksAvail);
5432 pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
5433 if (volType == ROVOL || volType == BACKVOL) {
5434 pResultCB->AvailableAllocationUnits.QuadPart = 0;
5438 pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
5443 * Lie about the available space. Out of quota errors will need
5444 * detected when the file server rejects the store data.
5446 pResultCB->TotalAllocationUnits.QuadPart = 0x7FFFFFFF;
5447 pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
5451 pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( volp->namep, -1, pResultCB->VolumeLabel,
5452 (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
5453 if ( pResultCB->VolumeLabelLength )
5454 pResultCB->VolumeLabelLength--;
5458 lock_ObtainWrite(&scp->rw);
5461 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
5464 pResultCB->VolumeLabelLength *= sizeof(WCHAR); /* convert to bytes from chars */
5468 lock_ReleaseWrite(&scp->rw);
5471 cm_ReleaseSCache(scp);
5473 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5474 (*ResultCB)->ResultStatus = status;
5475 osi_Log0(afsd_logp, "RDR_GetVolumeInfo SUCCESS");
5480 RDR_GetVolumeSizeInfo( IN cm_user_t *userp,
5481 IN AFSFileID FileId,
5483 IN DWORD ResultBufferLength,
5484 IN OUT AFSCommResult **ResultCB)
5486 AFSVolumeSizeInfoCB *pResultCB = NULL;
5488 cm_scache_t *scp = NULL;
5489 cm_volume_t *volp = NULL;
5491 cm_cell_t *cellp = NULL;
5497 char volName[32]="(unknown)";
5498 char offLineMsg[256]="server temporarily inaccessible";
5499 char motd[256]="server temporarily inaccessible";
5501 AFSFetchVolumeStatus volStat;
5505 struct rx_connection * rxconnp;
5509 RDR_InitReq(&req, bWow64);
5511 osi_Log4(afsd_logp, "RDR_GetVolumeSizeInfo File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5512 FileId.Cell, FileId.Volume,
5513 FileId.Vnode, FileId.Unique);
5515 Length = sizeof( AFSCommResult) + sizeof(AFSVolumeSizeInfoCB);
5516 if (sizeof(AFSVolumeSizeInfoCB) > ResultBufferLength) {
5517 *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
5520 memset( *ResultCB, 0, sizeof(AFSCommResult));
5521 (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5525 *ResultCB = (AFSCommResult *)malloc( Length );
5528 memset( *ResultCB, '\0', Length );
5529 (*ResultCB)->ResultBufferLength = sizeof(AFSVolumeSizeInfoCB);
5530 pResultCB = (AFSVolumeSizeInfoCB *)(*ResultCB)->ResultData;
5532 if (FileId.Cell != 0) {
5533 cm_SetFid(&Fid, FileId.Cell, FileId.Volume, 1, 1);
5534 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
5536 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5537 (*ResultCB)->ResultStatus = status;
5538 (*ResultCB)->ResultBufferLength = 0;
5539 osi_Log2(afsd_logp, "RDR_GetVolumeSizeInfo cm_GetSCache FID failure code=0x%x status=0x%x",
5544 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
5545 osi_Log0(afsd_logp, "RDR_GetVolumeSizeInfo Object Name Invalid - Cell = 0");
5548 lock_ObtainWrite(&scp->rw);
5551 pResultCB->SectorsPerAllocationUnit = 1;
5552 pResultCB->BytesPerSector = 1024;
5554 if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
5555 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
5557 pResultCB->TotalAllocationUnits.QuadPart = 100;
5558 pResultCB->AvailableAllocationUnits.QuadPart = 0;
5560 volp = cm_GetVolumeByFID(&scp->fid);
5562 code = CM_ERROR_NOSUCHVOLUME;
5566 volType = cm_VolumeType(volp, scp->fid.volume);
5568 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
5569 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
5575 OfflineMsg = offLineMsg;
5577 lock_ReleaseWrite(&scp->rw);
5581 code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
5584 rxconnp = cm_GetRxConn(connp);
5585 code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
5586 &volStat, &Name, &OfflineMsg, &MOTD);
5587 rx_PutConnection(rxconnp);
5589 } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
5590 code = cm_MapRPCError(code, &req);
5594 if (volStat.MaxQuota)
5596 pResultCB->TotalAllocationUnits.QuadPart = volStat.MaxQuota;
5597 if (volType == ROVOL || volType == BACKVOL) {
5598 pResultCB->AvailableAllocationUnits.QuadPart = 0;
5602 pResultCB->AvailableAllocationUnits.QuadPart =
5603 min(volStat.MaxQuota - volStat.BlocksInUse, volStat.PartBlocksAvail);
5608 pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
5609 if (volType == ROVOL || volType == BACKVOL) {
5610 pResultCB->AvailableAllocationUnits.QuadPart = 0;
5614 pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
5619 * Lie about the available space. Out of quota errors will need
5620 * detected when the file server rejects the store data.
5622 pResultCB->TotalAllocationUnits.QuadPart = 0x7FFFFFFF;
5623 pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
5629 lock_ObtainWrite(&scp->rw);
5632 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
5638 lock_ReleaseWrite(&scp->rw);
5641 cm_ReleaseSCache(scp);
5643 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5644 (*ResultCB)->ResultStatus = status;
5645 osi_Log0(afsd_logp, "RDR_GetVolumeSizeInfo SUCCESS");
5650 RDR_HoldFid( IN cm_user_t *userp,
5651 IN AFSHoldFidRequestCB * pHoldFidCB,
5653 IN DWORD ResultBufferLength,
5654 IN OUT AFSCommResult **ResultCB)
5656 AFSHoldFidResultCB *pResultCB = NULL;
5661 RDR_InitReq(&req, FALSE);
5663 osi_Log1(afsd_logp, "RDR_HoldFid Count=%u", pHoldFidCB->Count);
5665 Length = sizeof(AFSHoldFidResultCB) + (pHoldFidCB->Count-1) * sizeof(AFSFidResult);
5666 if (Length > ResultBufferLength) {
5667 *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
5670 memset( *ResultCB, 0, sizeof(AFSCommResult));
5671 (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5674 *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
5677 memset( *ResultCB, '\0', Length );
5678 (*ResultCB)->ResultBufferLength = Length;
5679 pResultCB = (AFSHoldFidResultCB *)(*ResultCB)->ResultData;
5681 for ( index = 0; index < pHoldFidCB->Count; index++ )
5683 cm_scache_t *scp = NULL;
5686 Fid.cell = pResultCB->Result[index].FileID.Cell = pHoldFidCB->FileID[index].Cell;
5687 Fid.volume = pResultCB->Result[index].FileID.Volume = pHoldFidCB->FileID[index].Volume;
5688 Fid.vnode = pResultCB->Result[index].FileID.Vnode = pHoldFidCB->FileID[index].Vnode;
5689 Fid.unique = pResultCB->Result[index].FileID.Unique = pHoldFidCB->FileID[index].Unique;
5690 Fid.hash = pResultCB->Result[index].FileID.Hash = pHoldFidCB->FileID[index].Hash;
5692 osi_Log4( afsd_logp,
5693 "RDR_HoldFid File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5694 Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
5696 scp = cm_FindSCache(&Fid);
5698 RDR_FlagScpInUse( scp, FALSE );
5699 cm_ReleaseSCache(scp);
5701 pResultCB->Result[index].Status = 0;
5704 (*ResultCB)->ResultStatus = 0;
5705 osi_Log0(afsd_logp, "RDR_HoldFid SUCCESS");
5710 RDR_ReleaseFid( IN cm_user_t *userp,
5711 IN AFSReleaseFidRequestCB * pReleaseFidCB,
5713 IN DWORD ResultBufferLength,
5714 IN OUT AFSCommResult **ResultCB)
5716 AFSReleaseFidResultCB *pResultCB = NULL;
5721 RDR_InitReq(&req, FALSE);
5723 osi_Log1(afsd_logp, "RDR_ReleaseFid Count=%u", pReleaseFidCB->Count);
5725 Length = sizeof(AFSReleaseFidResultCB) + (pReleaseFidCB->Count ? pReleaseFidCB->Count-1 : 0) * sizeof(AFSFidResult);
5726 if (Length > ResultBufferLength) {
5727 *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
5730 memset( *ResultCB, 0, sizeof(AFSCommResult));
5731 (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
5734 *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
5737 memset( *ResultCB, '\0', Length );
5738 (*ResultCB)->ResultBufferLength = Length;
5739 pResultCB = (AFSReleaseFidResultCB *)(*ResultCB)->ResultData;
5741 for ( index = 0; index < pReleaseFidCB->Count; index++ )
5743 cm_scache_t *scp = NULL;
5746 Fid.cell = pResultCB->Result[index].FileID.Cell = pReleaseFidCB->FileID[index].Cell;
5747 Fid.volume = pResultCB->Result[index].FileID.Volume = pReleaseFidCB->FileID[index].Volume;
5748 Fid.vnode = pResultCB->Result[index].FileID.Vnode = pReleaseFidCB->FileID[index].Vnode;
5749 Fid.unique = pResultCB->Result[index].FileID.Unique = pReleaseFidCB->FileID[index].Unique;
5750 Fid.hash = pResultCB->Result[index].FileID.Hash = pReleaseFidCB->FileID[index].Hash;
5752 osi_Log4( afsd_logp,
5753 "RDR_ReleaseFid File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
5754 Fid.cell, Fid.volume, Fid.vnode, Fid.unique);
5756 scp = cm_FindSCache(&Fid);
5758 lock_ObtainWrite(&scp->rw);
5759 scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
5760 lock_ReleaseWrite(&scp->rw);
5762 cm_ReleaseSCache(scp);
5764 pResultCB->Result[index].Status = 0;
5766 pResultCB->Count = pReleaseFidCB->Count;
5768 (*ResultCB)->ResultStatus = 0;
5769 osi_Log0(afsd_logp, "RDR_ReleaseFid SUCCESS");
5774 * The redirector makes several assumptions regarding the
5775 * SRVSVC and WKSSVC pipes transactions. First, the interface
5776 * versions are those indicated below. Secondly, the encoding
5777 * will be performed using NDR version 2. These assumptions
5778 * may not hold in the future and end-to-end MSRPC Bind
5779 * negotiations may need to be supported. Of course, these
5780 * are the only interface versions that are supported by the
5783 #define MSRPC_PIPE_PREFIX L".\\"
5785 static const UUID MSRPC_SRVSVC_UUID = {0x4B324FC8, 0x1670, 0x01D3,
5786 {0x12, 0x78, 0x5A, 0x47, 0xBF, 0x6E, 0xE1, 0x88}};
5787 #define MSRPC_SRVSVC_NAME L"PIPE\\SRVSVC"
5788 #define MSRPC_SRVSVC_VERS 3
5790 static const UUID MSRPC_WKSSVC_UUID = {0x6BFFD098, 0xA112, 0x3610,
5791 {0x98, 0x33, 0x46, 0xC3, 0xF8, 0x7E, 0x34, 0x5A}};
5792 #define MSRPC_WKSSVC_NAME L"PIPE\\WKSSVC"
5793 #define MSRPC_WKSSVC_VERS 1
5795 static const UUID MSRPC_NDR_UUID = {0x8A885D04, 0x1CEB, 0x11C9,
5796 {0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60}};
5797 #define MSRPC_NDR_NAME L"NDR"
5798 #define MSRPC_NDR_VERS 2
5800 extern RPC_IF_HANDLE srvsvc_v3_0_s_ifspec;
5801 extern RPC_IF_HANDLE wkssvc_v1_0_s_ifspec;
5804 RDR_PipeOpen( IN cm_user_t *userp,
5805 IN AFSFileID ParentId,
5807 IN DWORD NameLength,
5808 IN AFSPipeOpenCloseRequestCB *pPipe_CB,
5810 IN DWORD ResultBufferLength,
5811 IN OUT AFSCommResult **ResultCB)
5816 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5822 sizeof( AFSCommResult));
5824 /* Get the active directory */
5825 ParentFid.cell = ParentId.Cell;
5826 ParentFid.volume = ParentId.Volume;
5827 ParentFid.vnode = ParentId.Vnode;
5828 ParentFid.unique = ParentId.Unique;
5829 ParentFid.hash = ParentId.Hash;
5831 /* Get the root directory */
5832 RootFid.cell = pPipe_CB->RootId.Cell;
5833 RootFid.volume = pPipe_CB->RootId.Volume;
5834 RootFid.vnode = pPipe_CB->RootId.Vnode;
5835 RootFid.unique = pPipe_CB->RootId.Unique;
5836 RootFid.hash = pPipe_CB->RootId.Hash;
5838 /* Create the pipe index */
5839 (*ResultCB)->ResultStatus =
5840 RDR_SetupPipe( pPipe_CB->RequestId, &ParentFid, &RootFid,
5841 Name, NameLength, userp);
5847 RDR_PipeClose( IN cm_user_t *userp,
5848 IN AFSFileID ParentId,
5849 IN AFSPipeOpenCloseRequestCB *pPipe_CB,
5851 IN DWORD ResultBufferLength,
5852 IN OUT AFSCommResult **ResultCB)
5854 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5860 sizeof( AFSCommResult));
5862 /* Cleanup the pipe index */
5863 RDR_CleanupPipe(pPipe_CB->RequestId);
5870 RDR_PipeWrite( IN cm_user_t *userp,
5871 IN AFSFileID ParentId,
5872 IN AFSPipeIORequestCB *pPipe_CB,
5873 IN BYTE *pPipe_Data,
5875 IN DWORD ResultBufferLength,
5876 IN OUT AFSCommResult **ResultCB)
5878 AFSPipeIOResultCB *pResultCB;
5879 cm_scache_t *dscp = NULL;
5884 RDR_InitReq(&req, bWow64);
5886 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5892 sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5894 pResultCB = (AFSPipeIOResultCB *)(*ResultCB)->ResultData;
5896 code = RDR_Pipe_Write( pPipe_CB->RequestId, pPipe_CB->BufferLength, pPipe_Data, &req, userp);
5898 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5899 (*ResultCB)->ResultStatus = status;
5903 pResultCB->BytesProcessed = pPipe_CB->BufferLength;
5904 (*ResultCB)->ResultBufferLength = sizeof( AFSPipeIOResultCB);
5909 RDR_PipeRead( IN cm_user_t *userp,
5910 IN AFSFileID ParentId,
5911 IN AFSPipeIORequestCB *pPipe_CB,
5913 IN DWORD ResultBufferLength,
5914 IN OUT AFSCommResult **ResultCB)
5917 cm_scache_t *dscp = NULL;
5922 RDR_InitReq(&req, bWow64);
5924 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
5930 sizeof( AFSCommResult));
5932 pPipe_Data = (BYTE *)(*ResultCB)->ResultData;
5934 code = RDR_Pipe_Read( pPipe_CB->RequestId, ResultBufferLength, pPipe_Data,
5935 &(*ResultCB)->ResultBufferLength, &req, userp);
5937 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
5938 (*ResultCB)->ResultStatus = status;
5945 RDR_PipeSetInfo( IN cm_user_t *userp,
5946 IN AFSFileID ParentId,
5947 IN AFSPipeInfoRequestCB *pPipeInfo_CB,
5948 IN BYTE *pPipe_Data,
5950 IN DWORD ResultBufferLength,
5951 IN OUT AFSCommResult **ResultCB)
5953 cm_scache_t *dscp = NULL;
5957 RDR_InitReq(&req, bWow64);
5959 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
5965 sizeof( AFSCommResult));
5967 status = RDR_Pipe_SetInfo( pPipeInfo_CB->RequestId, pPipeInfo_CB->InformationClass,
5968 pPipeInfo_CB->BufferLength, pPipe_Data, &req, userp);
5970 (*ResultCB)->ResultStatus = status;
5975 RDR_PipeQueryInfo( IN cm_user_t *userp,
5976 IN AFSFileID ParentId,
5977 IN AFSPipeInfoRequestCB *pPipeInfo_CB,
5979 IN DWORD ResultBufferLength,
5980 IN OUT AFSCommResult **ResultCB)
5983 cm_scache_t *dscp = NULL;
5987 RDR_InitReq(&req, bWow64);
5989 *ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
5995 sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
5997 pPipe_Data = (BYTE *)(*ResultCB)->ResultData;
5999 status = RDR_Pipe_QueryInfo( pPipeInfo_CB->RequestId, pPipeInfo_CB->InformationClass,
6000 ResultBufferLength, pPipe_Data,
6001 &(*ResultCB)->ResultBufferLength, &req, userp);
6003 (*ResultCB)->ResultStatus = status;
6007 RDR_PipeTransceive( IN cm_user_t *userp,
6008 IN AFSFileID ParentId,
6009 IN AFSPipeIORequestCB *pPipe_CB,
6010 IN BYTE *pPipe_InData,
6012 IN DWORD ResultBufferLength,
6013 IN OUT AFSCommResult **ResultCB)
6016 * This function processes a Pipe Service request
6017 * that would normally be sent to a LAN Manager server
6018 * across an authenticated SMB-PIPE/MSRPC/SVC request
6019 * stack. The request is being sent here because the
6020 * application (e.g., Explorer Shell or Common Control File
6021 * dialog) believes that because the UNC path it is
6022 * processing has specified a server name that is not
6023 * "." and that the Server is remote and that the Share
6024 * list cannot be obtained using the Network Provider
6027 * The file system driver is faking the Bind-Ack response
6028 * to the MSRPC Bind request but cannot decode the NDR
6029 * encoded Pipe Service requests. For that we will use
6030 * the service's MSRPC module. However, unlike the SMB
6031 * server usage we must fake the MSRPC Bind exchange and
6032 * map the PipeName to an interface instead of using the
6033 * GUID specified in the MSRPC Bind request.
6035 * None of the requests that are being processed by the
6036 * service require authentication. As a result the userp
6037 * parameter will be ignored.
6039 * Although there are dozens of Pipe Services, the only
6040 * ones that we are implementing are WKSSVC and SRVSVC.
6041 * These support NetShareEnum, NetShareGetInfo,
6042 * NetServerGetInfo, and NetWorkstaGetInfo which are
6043 * commonly queried by NET VIEW, the Explorer Shell,
6044 * and the Common Control File dialog.
6046 BYTE *pPipe_OutData;
6047 cm_scache_t *dscp = NULL;
6051 DWORD Length = ResultBufferLength + sizeof( AFSCommResult);
6053 RDR_InitReq(&req, bWow64);
6055 *ResultCB = (AFSCommResult *)malloc( Length);
6058 memset( *ResultCB, '\0', Length );
6060 code = RDR_Pipe_Write( pPipe_CB->RequestId, pPipe_CB->BufferLength, pPipe_InData, &req, userp);
6062 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
6063 osi_Log2( afsd_logp, "RDR_Pipe_Transceive Write FAILURE code=0x%x status=0x%x",
6065 (*ResultCB)->ResultStatus = status;
6069 pPipe_OutData = (BYTE *)(*ResultCB)->ResultData;
6070 code = RDR_Pipe_Read( pPipe_CB->RequestId, ResultBufferLength, pPipe_OutData,
6071 &(*ResultCB)->ResultBufferLength, &req, userp);
6073 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
6074 osi_Log2( afsd_logp, "RDR_Pipe_Transceive Read FAILURE code=0x%x status=0x%x",
6076 (*ResultCB)->ResultStatus = status;
6080 (*ResultCB)->ResultStatus = 0;
6081 osi_Log0(afsd_logp, "RDR_Pipe_Transceive SUCCESS");