+++ /dev/null
-/* copyright (c) 2005
- * the regents of the university of michigan
- * all rights reserved
- *
- * permission is granted to use, copy, create derivative works and
- * redistribute this software and such derivative works for any purpose,
- * so long as the name of the university of michigan is not used in
- * any advertising or publicity pertaining to the use or distribution
- * of this software without specific, written prior authorization. if
- * the above copyright notice or any other identification of the
- * university of michigan is included in any copy of any portion of
- * this software, then the disclaimer below must also be included.
- *
- * this software is provided as is, without representation from the
- * university of michigan as to its fitness for any purpose, and without
- * warranty by the university of michigan of any kind, either express
- * or implied, including without limitation the implied warranties of
- * merchantability and fitness for a particular purpose. the regents
- * of the university of michigan shall not be liable for any damages,
- * including special, indirect, incidental, or consequential damages,
- * with respect to any claim arising out or in connection with the use
- * of the software, even if it has been or is hereafter advised of the
- * possibility of such damages.
- */
-
-/* versioning history
- *
- * 03-jun 2005 (eric williams) entered into versioning
- */
-
-/* developer: eric williams,
- * center for information technology integration,
- * university of michigan, ann arbor
- *
- * comments: nativeafs@citi.umich.edu
- */
-
-#define IRPMJFUNCDESC /* pull in text strings of the names of irp codes */
-#define RPC_SRV /* which half of the rpc library to use */
-
-#include <ntifs.h>
-#include <ntdddisk.h>
-#include <strsafe.h>
-#include <ksdebug.h>
-#include "ifs_rpc.h"
-#include "afsrdr.h"
-#include "kif.h"
-
-
-/*** notes ***/
-/* flag pooltag Io(sp)(sp) to check queryinfo requests for buffer overrun */
-
-NTKERNELAPI
-NTSTATUS
-IoAllocateDriverObjectExtension(
- IN PDRIVER_OBJECT DriverObject,
- IN PVOID ClientIdentificationAddress,
- IN ULONG DriverObjectExtensionSize,
- OUT PVOID *DriverObjectExtension
- );
-
-/*** local structs ***/
-/* represents a specific file */
-struct afs_fcb
-{
- FSRTL_COMMON_FCB_HEADER; /* needed to interface with cache manager, etc. */
- SECTION_OBJECT_POINTERS sectionPtrs;
- ERESOURCE _resource; /* pointed to by fcb_header->Resource */
- ERESOURCE _pagingIoResource;
- unsigned long fid; /* a courtesy from the userland daemon (a good hash function) */
- UCHAR delPending;
- struct afs_ccb *ccb_list; /* list of open instances */
- SHARE_ACCESS share_access; /* common access control */
- PFILE_LOCK lock;
-};
-typedef struct afs_fcb afs_fcb_t;
-
-/* represents an open instance of a file */
-struct afs_ccb
-{
- struct afs_ccb *next; /* these are chained as siblings, non-circularly */
- ULONG access; /* how this instance is opened */
- wchar_t *name; /* ptr to name buffer */
- UNICODE_STRING str; /* full name struct, for notification fns */
- FILE_OBJECT *fo; /* can get parent fcb from this */
- LARGE_INTEGER cookie; /* on enum ops, where we are */
- wchar_t *filter; /* on enum ops, what we are filtering on */
- PACCESS_TOKEN token; /* security data of opening app */
- ULONG attribs; /* is dir, etc. */
-};
-typedef struct afs_ccb afs_ccb_t;
-
-
-/*** globals ***/
-/* use wisely -- should be set by each thread in an arbitrary context */
-/* here mostly as a development convenience */
-DEVICE_OBJECT *RdrDevice, *ComDevice;
-struct AfsRdrExtension *rdrExt;
-struct ComExtension *comExt;
-
-
-/*** error and return handling ***/
-/* current code is stable without, but these should wrap all operations */
-/*#define TRY try{
-#define EXCEPT(x, y) } except(EXCEPTION_EXECUTE_HANDLER) \
- { \
- KdBreakPoint(); \
- rpt4(("exception", "occurred")); \
- Irp->IoStatus.Status = x; \
- Irp->IoStatus.Information = y; \
- }*/
-#define TRY
-#define EXCEPT(x, y)
-
-#define STATUS(st, in) Irp->IoStatus.Information = (in), Irp->IoStatus.Status = (st)
-#define SYNC_FAIL(st) \
- { \
- STATUS(st, 0); \
- COMPLETE_NO_BOOST; \
- return st; \
- }
-#define SYNC_FAIL2(st, in) \
- { \
- STATUS(st, in); \
- COMPLETE_NO_BOOST; \
- return st; \
- }
-#define SYNC_RET(st) \
- { \
- STATUS(st, 0); \
- COMPLETE; \
- return st; \
- }
-#define SYNC_RET2(st, in) \
- { \
- STATUS(st, in); \
- COMPLETE; \
- return st; \
- }
-#define SYNC_FAIL_RPC_TIMEOUT SYNC_FAIL(STATUS_NETWORK_BUSY)
-
-#define LOCK_FCB_LIST FsRtlEnterFileSystem(); ExAcquireFastMutex(&rdrExt->fcbLock);
-#define UNLOCK_FCB_LIST ExReleaseFastMutex(&rdrExt->fcbLock); FsRtlExitFileSystem();
-
-#define LOCK_FCB ExAcquireResourceExclusiveLite(fcb->Resource, TRUE)
-#define SLOCK_FCB ExAcquireResourceSharedLite(fcb->Resource, TRUE)
-#define UNLOCK_FCB if (fcb) ExReleaseResourceLite(fcb->Resource)
-
-#define LOCK_PAGING_FCB ExAcquireResourceExclusiveLite(fcb->PagingIoResource, TRUE)
-#define SLOCK_PAGING_FCB ExAcquireResourceSharedLite(fcb->PagingIoResource, TRUE)
-#define UNLOCK_PAGING_FCB if (fcb) ExReleaseResourceLite(fcb->PagingIoResource)
-
-/*** constants ***/
-#define AFS_RDR_TAG (0x73666440)//@dfs//0x482ac230//0x3029a4f2
-#define MAX_PATH 700
-#define AFS_FS_NAME L"Andrew File System"
-
-#define COMM_IOCTL (void*)0x01
-#define COMM_DOWNCALL (void*)0x02
-#define COMM_UPCALLHOOK (void*)0x03
-
-/* flag to use caching kernel service. needs to handle cache invalidation in more places. */
-#define EXPLICIT_CACHING
-
-/* dates from afs are time_t style -- seconds since 1970 */ /* 11644505691.6384 */
-#define AfsTimeToWindowsTime(x) (((x)+11644505692L)*10000000L) /*(1970L-1601L)*365.242199*24L*3600L)*/
-#define WindowsTimeToAfsTime(x) ((x)/10000000L-11644505692L) /*(1970L-1601L)*365.242199*24L*3600L)*/
-#define IsDeviceFile(fo) (!fo->FsContext)
-
-
-/*** auxiliary functions ***/
-#define COMPLETE_NO_BOOST IoCompleteRequest(Irp, IO_NO_INCREMENT)
-#define COMPLETE IoCompleteRequest(Irp, IO_NETWORK_INCREMENT)
-
-afs_fcb_t *FindFcb(FILE_OBJECT *fo)
-{
- if (fo)
- return fo->FsContext;
- return NULL;
-}
-
-void *AfsFindBuffer(IRP *Irp)
-{
- void *outPtr;
- if (Irp->MdlAddress)
- {
- outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
- if (outPtr)
- return outPtr;
- }
- outPtr = Irp->AssociatedIrp.SystemBuffer;
- return outPtr;
-}
-
-/* we do Resource locking because we don't want to figure out when to pull MainResource */
-BOOLEAN lazyWriteLock(PVOID context, BOOLEAN wait)
-{
- afs_fcb_t *fcb = context;
- ASSERT(fcb);
- return ExAcquireResourceExclusiveLite(fcb->Resource, wait);
-}
-
-void lazyWriteUnlock(PVOID context)
-{
- afs_fcb_t *fcb = context;
- ASSERT(fcb);
- ExReleaseResourceLite(fcb->Resource);
-}
-
-BOOLEAN readAheadLock(PVOID context, BOOLEAN wait)
-{
- afs_fcb_t *fcb = context;
- ASSERT(fcb);
- return ExAcquireResourceSharedLite(fcb->Resource, wait);
-}
-
-void readAheadUnlock(PVOID context)
-{
- afs_fcb_t *fcb = context;
- ASSERT(fcb);
- ExReleaseResourceLite(fcb->Resource);
-}
-
-afs_fcb_t *find_fcb(ULONG fid)
-{
- afs_fcb_t compare, *compare_ptr, **fcbp;
-
- compare.fid = fid;
- compare_ptr = &compare;
- fcbp = RtlLookupElementGenericTable(&rdrExt->fcbTable, (void*)&compare_ptr);
-
- if (fcbp)
- return (*fcbp);
- return NULL;
-}
-
-
-/**********************************************************
- * AfsRdrCreate
- * - handle open and create requests
- * - on success
- * - FsContext of file object points to FCB
- * - FsContext2 of file object is usermode handle of file instance
- * - beginning failure codes and conditions came from ifstest
- **********************************************************/
-NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *_fcb)
-{
- afs_fcb_t *pfcb, *fcb, **fcbp;
- afs_ccb_t *ccb, *pccb, *curr_ccb;
- ULONG len;
- LONG x, y;
- wchar_t *str, *ptr;
- ULONG fid, access, granted, disp;
- LARGE_INTEGER size, creation, accesst, change, written, zero, wait;
- ULONG attribs;
- ULONG share;
- CC_FILE_SIZES sizes;
- NTSTATUS status;
- char created;
- PACCESS_TOKEN acc_token;
-
- /* set rpc security context for current thread */
- acc_token = SeQuerySubjectContextToken(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
- ASSERT(acc_token);
-
- wait.QuadPart = -1000;
- while (rpc_set_context(acc_token) != 0) /* if there are no open thread spots... */
- KeDelayExecutionThread(KernelMode, FALSE, &wait); /* ...wait */
-
- /* attempt to open afs volume directly */
- if (IrpSp->FileObject->FileName.Length == 0)
- SYNC_FAIL(STATUS_SHARING_VIOLATION);
-
- if (IrpSp->FileObject->FileName.Length > MAX_PATH*sizeof(wchar_t))
- SYNC_FAIL(STATUS_OBJECT_NAME_INVALID);
-
- if (IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_TEMPORARY &&
- IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE)
- SYNC_FAIL(STATUS_INVALID_PARAMETER);
-
- /* relative opens cannot start with \ */
- if (IrpSp->FileObject->RelatedFileObject &&
- IrpSp->FileObject->FileName.Length &&
- IrpSp->FileObject->FileName.Buffer[0] == L'\\')
- SYNC_FAIL(STATUS_INVALID_PARAMETER);/*STATUS_OBJECT_PATH_SYNTAX_BAD);*/
-
- /* a create request can be relative to a prior file. build filename here */
- pccb = NULL;
- if (IrpSp->FileObject->RelatedFileObject)
- pccb = IrpSp->FileObject->RelatedFileObject->FsContext2;
- len = IrpSp->FileObject->FileName.Length + (pccb?wcslen(pccb->name):0)*sizeof(wchar_t) + 6;
- str = ExAllocatePoolWithTag(NonPagedPool, len, AFS_RDR_TAG);
- RtlZeroMemory(str, len);
- if (pccb)
- {
- StringCbCatN(str, len, IrpSp->FileObject->RelatedFileObject->FileName.Buffer, IrpSp->FileObject->RelatedFileObject->FileName.Length);
- StringCbCat(str, len, L"\\");
- }
- StringCbCatN(str, len, IrpSp->FileObject->FileName.Buffer, IrpSp->FileObject->FileName.Length);
-
- /* request to open hierarchical parent of specified path */
- /* remove last path component */
- if (IrpSp->Flags & SL_OPEN_TARGET_DIRECTORY)
- {
- y = x = wcslen(str);
- if (x)
- x--, y--;
- for (x; x >= 0; x--)
- {
- if (str[x] == L'\\')
- {
- if (y == x && x != 0)
- str[x] = L'\0';
- else if (x != 0)
- {
- str[x] = L'\0';
- break;
- }
- else
- {
- str[x+1] = L'\0';
- break;
- }
- }
- }
- }
-
- /* first two characters are \%01d . %d is number of path components immediately
- * following that should not be returned in file name queries.
- * EX: \3\mount\path\start\fname.ext is mapped to <driveletter>:\fname.ext
- */
- if (wcslen(str) <= 2)
- {
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_OBJECT_NAME_INVALID);
- }
-
- fid = 0;
- disp = (unsigned char)((IrpSp->Parameters.Create.Options >> 24) & 0xff);
- access = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
- share = IrpSp->Parameters.Create.ShareAccess;
- size.QuadPart = 0;
- created = 0;
-
- open:
- /* check for file existance. we jump to creating it if needed */
- if (disp == FILE_OPEN || disp == FILE_OPEN_IF || disp == FILE_OVERWRITE ||
- disp == FILE_OVERWRITE_IF || disp == FILE_SUPERSEDE)
- {
- /* chop our internal mount flagging from the beginning */
- status = uc_namei(str+2, &fid);
- if (status == IFSL_DOES_NOT_EXIST &&
- (disp == FILE_OPEN_IF ||
- disp == FILE_OVERWRITE_IF ||
- disp == FILE_SUPERSEDE))
- goto create;
-
- if (status != IFSL_SUCCESS)
- {
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- switch (status)
- {
- case IFSL_RPC_TIMEOUT: SYNC_FAIL_RPC_TIMEOUT;
- case IFSL_NO_ACCESS: SYNC_FAIL(STATUS_ACCESS_DENIED);
- case IFSL_BAD_INPUT: SYNC_FAIL(STATUS_INVALID_PARAMETER);
- case IFSL_DOES_NOT_EXIST: SYNC_FAIL2(STATUS_OBJECT_NAME_NOT_FOUND, FILE_DOES_NOT_EXIST);
- case IFSL_PATH_DOES_NOT_EXIST: SYNC_FAIL2(STATUS_OBJECT_PATH_NOT_FOUND, FILE_DOES_NOT_EXIST);
- default: SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- }
-
- /* make upcall to get ACL in afs. we specify our requested level to
- * keep it from hitting the network on a public volume.
- */
- status = uc_check_access(fid, access, &granted);
- if (status != IFSL_SUCCESS)
- {
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- switch (status)
- {
- case IFSL_RPC_TIMEOUT: SYNC_FAIL_RPC_TIMEOUT;
- case IFSL_BAD_INPUT: SYNC_FAIL(STATUS_INVALID_PARAMETER);
- default: SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- }
-
- /* make sure daemon approved access */
- if ((access & granted) != access)
- {
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_ACCESS_DENIED);
- }
-
- /* we depend on this information for caching, etc. */
- status = uc_stat(fid, &attribs, &size, &creation, &accesst, &change, &written);
- if (status != IFSL_SUCCESS)
- {
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- switch (status)
- {
- case IFSL_RPC_TIMEOUT: SYNC_FAIL_RPC_TIMEOUT;
- case IFSL_BAD_INPUT: SYNC_FAIL(STATUS_INVALID_PARAMETER);
- default: SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- }
-
- /* afsd does not maintain instance-specific data, so we adjust here */
- if (granted & FILE_READ_DATA && !(granted & FILE_WRITE_DATA))
- attribs |= FILE_ATTRIBUTE_READONLY;
-
- if (IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE &&
- !(attribs & FILE_ATTRIBUTE_DIRECTORY))
- {
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_NOT_A_DIRECTORY);
- }
- if (IrpSp->Parameters.Create.Options & FILE_NON_DIRECTORY_FILE &&
- attribs & FILE_ATTRIBUTE_DIRECTORY)
- {
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_FILE_IS_A_DIRECTORY);
- }
-
- /* check for previous open instance(s) of file. it will be in the fcb chain.
- * when we have this locked, we cannot make upcalls -- running at APC_LEVEL.
- * lock here (not later) to prevent possible truncation races.
- */
- LOCK_FCB_LIST;
- fcb = find_fcb(fid);
- if (fcb)
- {
- LOCK_PAGING_FCB;
- LOCK_FCB;
- }
-
- /* if we found it, check to make sure open disposition and sharing
- * are not in conflict with previous opens. then, make new file
- * instance entry and, if necessary, file entry.
- */
- if (fcb)
- {
- /* file contents cannot be cached for a successful delete */
- if (access & FILE_WRITE_DATA)
- if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForWrite))
- {
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_SHARING_VIOLATION);
- }
- if (access & DELETE)
- if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForWrite))//Delete))
- {
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_SHARING_VIOLATION);
- }
-
- /* check common sharing flags, but do not change */
- if (IoCheckShareAccess(access, share, IrpSp->FileObject, &fcb->share_access, FALSE) != STATUS_SUCCESS)
- {
- rpt0(("create", "sharing violation for %ws", str));
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_SHARING_VIOLATION);
- }
-
- zero.QuadPart = 0;
- if (access & DELETE)
- if (!MmCanFileBeTruncated(&(fcb->sectionPtrs), &zero))
- {
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_SHARING_VIOLATION);
- }
- }
-
- /* do overwrite/supersede tasks */
- if (disp == FILE_OVERWRITE ||
- disp == FILE_OVERWRITE_IF ||
- disp == FILE_SUPERSEDE)
- {
- zero.QuadPart = 0;
- if (fcb && !MmCanFileBeTruncated(&(fcb->sectionPtrs), &zero))
- {
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_SHARING_VIOLATION);
- }
- if (size.QuadPart != 0)
- {
- size.QuadPart = 0;
- status = uc_trunc(fid, size);
- if (status != IFSL_SUCCESS)
- {
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_ACCESS_DENIED);
- }
- if (fcb)
- {
- fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
- curr_ccb = fcb->ccb_list;
- while (curr_ccb && curr_ccb->fo)
- {
- if (CcIsFileCached(curr_ccb->fo))
- {
- CcSetFileSizes(curr_ccb->fo, (CC_FILE_SIZES*)&fcb->AllocationSize);
- break;
- }
- curr_ccb = curr_ccb->next;
- }
- }
- }
- if (Irp->Overlay.AllocationSize.QuadPart)
- {
- status = uc_trunc(fid, Irp->Overlay.AllocationSize);
- size = Irp->Overlay.AllocationSize;
- if (status != IFSL_SUCCESS)
- {
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_DISK_FULL);
- }
- if (fcb)
- {
- fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
- curr_ccb = fcb->ccb_list;
- while (curr_ccb && curr_ccb->fo)
- {
- if (CcIsFileCached(curr_ccb->fo))
- {
- CcSetFileSizes(curr_ccb->fo, (CC_FILE_SIZES*)&fcb->AllocationSize);
- break;
- }
- curr_ccb = curr_ccb->next;
- }
- }
- }
- }
-
- if (fcb)
- {
- /* make actual change in common sharing flags */
- IoUpdateShareAccess(IrpSp->FileObject, &fcb->share_access);
- goto makeccb;
- }
-
- goto makefcb;
- }
-
-
- /* if disposition was to create the file, or its non-existance necessitates this */
- create:
- if (disp == FILE_CREATE ||
- status == IFSL_DOES_NOT_EXIST && (disp == FILE_OPEN_IF || disp == FILE_OVERWRITE_IF || disp == FILE_SUPERSEDE))
- {
- attribs = IrpSp->Parameters.Create.FileAttributes;
- if (IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE)
- attribs |= FILE_ATTRIBUTE_DIRECTORY;
- if (IrpSp->Parameters.Create.Options & FILE_NON_DIRECTORY_FILE)
- attribs &= ~FILE_ATTRIBUTE_DIRECTORY;
- status = uc_create(str+2, attribs, Irp->Overlay.AllocationSize, access, &granted, &fid);
- if (status != IFSL_SUCCESS)
- {
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- switch (status)
- {
- case IFSL_RPC_TIMEOUT: SYNC_FAIL_RPC_TIMEOUT;
- case IFSL_NO_ACCESS: SYNC_FAIL(STATUS_ACCESS_DENIED);
- case IFSL_BAD_INPUT: SYNC_FAIL(STATUS_INVALID_PARAMETER);
- case IFSL_PATH_DOES_NOT_EXIST: SYNC_FAIL2(STATUS_OBJECT_PATH_NOT_FOUND, FILE_DOES_NOT_EXIST);
- case IFSL_OPEN_EXISTS: SYNC_FAIL2(STATUS_OBJECT_NAME_COLLISION, FILE_EXISTS);
- case IFSL_OVERQUOTA: SYNC_FAIL(STATUS_DISK_FULL);//STATUS_QUOTA_EXCEEDED);
- default: SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- }
-
- /* lock list like above. check again just to make sure it isn't in the list.
- * if it is, we should process like above. depending on how we follow symlinks
- * (same fid for multiple files), we cannot expect serialized create requests.
- */
- LOCK_FCB_LIST;
- fcb = find_fcb(fid);
- if (fcb) /* none of these should happen */
- if (disp == FILE_CREATE)
- {
- UNLOCK_FCB_LIST;
- SYNC_FAIL2(STATUS_OBJECT_NAME_COLLISION, FILE_EXISTS);
- }
- else
- {
- fcb = NULL;
- UNLOCK_FCB_LIST;
- goto open;
- }
-
- if (size.QuadPart != 0)
- {
- size.QuadPart = 0;
- uc_trunc(fid, size);
- if (status != IFSL_SUCCESS)
- {
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_DISK_FULL);
- }
- }
- if (Irp->Overlay.AllocationSize.QuadPart)
- {
- uc_trunc(fid, Irp->Overlay.AllocationSize);
- size = Irp->Overlay.AllocationSize;
- if (status != IFSL_SUCCESS)
- {
- UNLOCK_FCB_LIST;
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_ACCESS_DENIED);
- }
- }
-
- created = 1;
- goto makefcb;
- }
-
- /* OS passed unexpected disposition */
- ExFreePoolWithTag(str, AFS_RDR_TAG);
- SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
-
-
- /* allocate nonpaged struct to track this file and all open instances */
- makefcb:
- fcb = ExAllocateFromNPagedLookasideList(&rdrExt->fcbMemList);
- ASSERT(fcb);
- RtlZeroMemory(fcb, sizeof(afs_fcb_t));
-
- fcb->fid = fid;
- /*fcb->refs = 0;*/
- fcb->ccb_list = NULL;
- fcb->IsFastIoPossible = FastIoIsPossible;
-
- ExInitializeResourceLite(&fcb->_resource);
- ExInitializeResourceLite(&fcb->_pagingIoResource);
- fcb->Resource = &fcb->_resource;
- fcb->PagingIoResource = &fcb->_pagingIoResource;
- LOCK_PAGING_FCB;
- LOCK_FCB;
-
- fcb->sectionPtrs.DataSectionObject = NULL;
- fcb->sectionPtrs.SharedCacheMap = NULL;
- fcb->sectionPtrs.ImageSectionObject = NULL;
- fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
-
- IoSetShareAccess(access, share, IrpSp->FileObject, &fcb->share_access);
- fcb->lock = NULL;
-
- /* we store a pointer to the fcb. the table would want to store a copy otherwise. */
- fcbp = &fcb;
- RtlInsertElementGenericTable(&rdrExt->fcbTable, fcbp, sizeof(fcbp), NULL);
-
- sizes.AllocationSize = sizes.FileSize = sizes.ValidDataLength = size;
- rpt1(("create", "created size %d name %ws", size.LowPart, str));
-
- /* allocate nonpaged struct tracking information specific to (file, open instance) pair,
- * and link from parent. is put at head of parent's list.
- */
- makeccb:
- /* there are two different types of pending deletes. we return different
- * errors in places depending on a) delete specified on call to open,
- * or b) file specifically deleted
- */
- /* need to check for DELETE perms too? */
- if (IrpSp->Parameters.Create.Options & FILE_DELETE_ON_CLOSE)
- fcb->delPending = 2;
-
- ccb = ExAllocateFromNPagedLookasideList(&rdrExt->ccbMemList);
- ccb->name = str;
- ccb->access = granted;
- ccb->fo = IrpSp->FileObject;
- ccb->cookie.QuadPart = 0;
- ccb->filter = NULL;
- ccb->attribs = attribs;
-
- /* save security context information. we never change this ccb attribute. */
- ObReferenceObjectByPointer(acc_token, TOKEN_QUERY, NULL, KernelMode);
- ccb->token = acc_token;
- /*ObOpenObjectByPointer(acc_token, OBJ_KERNEL_HANDLE, NULL, TOKEN_QUERY, NULL, KernelMode, &ccb->token);*/
-
- if (!fcb->ccb_list)
- {
- ccb->next = NULL;
- fcb->ccb_list = ccb;
- }
- else
- {
- ccb->next = fcb->ccb_list;
- fcb->ccb_list = ccb;
- }
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
-
- /* how we pack (what the cache manager needs): a) fscontext same for all open instances
- * of a file, b) fscontext2 unique among each instance, c) private cache map pointer set
- * by cache manager upon caching, d) so pointers are per-file, as in (a).
- */
- IrpSp->FileObject->FsContext = fcb;
- IrpSp->FileObject->FsContext2 = ccb;
- IrpSp->FileObject->PrivateCacheMap = NULL;
- IrpSp->FileObject->SectionObjectPointer = &(fcb->sectionPtrs);
-
- /* customize returns; semantics largely derived from output of ifstest.exe */
- switch (disp)
- {
- case FILE_OPEN:
- SYNC_FAIL2(STATUS_SUCCESS, FILE_OPENED);
-
- case FILE_OPEN_IF:
- if (created) {
- SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED);
- } else {
- SYNC_FAIL2(STATUS_SUCCESS, FILE_OPENED);
- }
- case FILE_OVERWRITE:
- SYNC_FAIL2(STATUS_SUCCESS, FILE_OVERWRITTEN);
-
- case FILE_OVERWRITE_IF:
- if (created) {
- SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED);
- } else {
- SYNC_FAIL2(STATUS_SUCCESS, FILE_OVERWRITTEN);
- }
- case FILE_SUPERSEDE:
- if (created) {
- SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED);
- } else {
- SYNC_FAIL2(STATUS_SUCCESS, FILE_SUPERSEDED);
- }
- case FILE_CREATE:
- SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED);
- }
- return 0;
-}
-
-
-/**********************************************************
- * AfsRdrRead
- * - handle reads
- **********************************************************/
-NTSTATUS AfsRdrRead(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- struct ReadKOut *p;
- void *ptr;
- LARGE_INTEGER offset, curroff;
- ULONG length, read;
- void *outPtr;
- NTSTATUS status;
- afs_ccb_t *ccb;
- MDL m;
- ULONG currpos, ttlread, toread;
-
- ccb = IrpSp->FileObject->FsContext2;
- if (IsDeviceFile(IrpSp->FileObject) || (ccb->attribs & FILE_ATTRIBUTE_DIRECTORY))
- SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
-
-/* the second line enables read ahead and disables write behind. since our data is
- * already cached in userland, and there are read-ahead parameters there, these are
- * not strictly necessary for decent performance. also, writes-behind may happen on
- * handles that do not have write access, because the i/o manager picks some handle,
- * not necessarily the same one that writing was originally done with. */
-#ifdef EXPLICIT_CACHING
- if (!IrpSp->FileObject->PrivateCacheMap)
- {
- CcInitializeCacheMap(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize, FALSE, &rdrExt->callbacks, IrpSp->FileObject->FsContext);//(PVOID)din->Context1);
- CcSetAdditionalCacheAttributes(IrpSp->FileObject, FALSE, TRUE);
- /* could do a call to CcSetReadAheadGranularity here */
- }
-#endif
-
- if (!(ccb->access & FILE_READ_DATA) && !(Irp->Flags & IRP_PAGING_IO))
- SYNC_FAIL(STATUS_ACCESS_DENIED);
-
- if (!IrpSp->Parameters.Read.Length)
- SYNC_FAIL(STATUS_SUCCESS);
-
- offset = IrpSp->Parameters.Read.ByteOffset;
- length = IrpSp->Parameters.Read.Length;
-
- FsRtlEnterFileSystem();
- SLOCK_FCB;
- if (!(Irp->Flags & IRP_PAGING_IO) && fcb->lock)
- {
- if (!FsRtlCheckLockForReadAccess(fcb->lock, Irp))
- {
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL(STATUS_FILE_LOCK_CONFLICT);
- }
- }
-
- /* fast out for reads starting beyond eof */
- if (offset.QuadPart > fcb->ValidDataLength.QuadPart)
- {
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL(STATUS_END_OF_FILE);
- }
-
- /* pre-truncate reads */
- if (offset.QuadPart + length > fcb->ValidDataLength.QuadPart)
- length = (ULONG)(fcb->ValidDataLength.QuadPart - offset.QuadPart);
- UNLOCK_FCB;
- FsRtlExitFileSystem();
-
- outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
- if (!outPtr)
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
-#ifdef EXPLICIT_CACHING
- /* this block is used only when a) caching functionality is compiled in,
- * b) this is not a paging i/o request, and c) this is not a no_cache req. */
- if (!(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO)))
- {
- FsRtlEnterFileSystem();
- SLOCK_PAGING_FCB;
- ttlread = 0;
- try
- {
- if (!CcCopyRead(IrpSp->FileObject, &offset, length, TRUE, outPtr, &Irp->IoStatus))
- {
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- ttlread = Irp->IoStatus.Information;
- }
- except (EXCEPTION_EXECUTE_HANDLER)
- {
- STATUS(STATUS_UNSUCCESSFUL, 0);
- }
- /* update byteoffset when this is not a paging or async request */
- if (Irp->IoStatus.Status != STATUS_UNSUCCESSFUL && IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
- IrpSp->FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + ttlread;
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- if (Irp->IoStatus.Status == STATUS_UNSUCCESSFUL)
- SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- else
-#endif
- {
- FsRtlEnterFileSystem();
- SLOCK_FCB;
- for (currpos = ttlread = 0; ttlread < length; )
- {
- toread = length - currpos;
- toread = (toread > TRANSFER_CHUNK_SIZE) ? TRANSFER_CHUNK_SIZE : toread;
- curroff.QuadPart = offset.QuadPart + currpos;
- status = uc_read(fcb->fid, curroff, toread, &read, outPtr);
-
- if (status == 0)
- {
- ttlread += read;
- currpos += read;
- if (read < toread)
- goto end;
- continue;
- }
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- switch (status)
- {
- case IFSL_RPC_TIMEOUT: SYNC_FAIL_RPC_TIMEOUT;
- case IFSL_IS_A_DIR: SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
- case IFSL_BAD_INPUT: SYNC_FAIL(STATUS_INVALID_PARAMETER);
- default: SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- }
- end:
- /* update byteoffset when this is not a paging or async request */
- if (IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
- IrpSp->FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + ttlread;
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- }
-
- if (ttlread == 0) {
- SYNC_FAIL2(STATUS_END_OF_FILE, ttlread);
- } else {
- SYNC_FAIL2(STATUS_SUCCESS, ttlread);
- }
-}
-
-
-
-/**********************************************************
- * AfsRdrWrite
- * - handle writes
- **********************************************************/
-NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- struct WriteKOut *p;
- void *ptr, *outPtr;
- ULONG length, written;
- LARGE_INTEGER offset, end;
- NTSTATUS status;
- afs_ccb_t *ccb;
- CC_FILE_SIZES sizes, oldSizes;
- ULONG towrite, ttlwritten, currpos;
- LARGE_INTEGER curroff;
- BOOLEAN change, paging_lock;
-
- ccb = IrpSp->FileObject->FsContext2;
- if (IsDeviceFile(IrpSp->FileObject) || (ccb->attribs & FILE_ATTRIBUTE_DIRECTORY))
- SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
-
- /* since we will be performing io on this instance, start caching (see above). */
-#ifdef EXPLICIT_CACHING
- if (!IrpSp->FileObject->PrivateCacheMap)
- {
- CcInitializeCacheMap(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize, FALSE, &rdrExt->callbacks, IrpSp->FileObject->FsContext);//(PVOID)din->Context1);
- CcSetAdditionalCacheAttributes(IrpSp->FileObject, FALSE, TRUE);
- }
-#endif
-
- if (!(ccb->access & FILE_WRITE_DATA) && !(Irp->Flags & IRP_PAGING_IO))
- SYNC_FAIL(STATUS_ACCESS_DENIED);
-
- /* fast-out for zero-length i/o */
- if (!IrpSp->Parameters.Write.Length)
- SYNC_FAIL(STATUS_SUCCESS);
-
- if (!(outPtr = AfsFindBuffer(Irp)))
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
- FsRtlEnterFileSystem();
- SLOCK_FCB;
-
- if (!(Irp->Flags & IRP_PAGING_IO) && fcb->lock)
- {
- if (!FsRtlCheckLockForWriteAccess(fcb->lock, Irp))
- {
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL(STATUS_FILE_LOCK_CONFLICT);
- }
- }
-
- if (IrpSp->Parameters.Write.ByteOffset.HighPart == 0xffffffff &&
- IrpSp->Parameters.Write.ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE)
- offset.QuadPart = fcb->FileSize.QuadPart;
- else
- offset = IrpSp->Parameters.Write.ByteOffset;
- length = IrpSp->Parameters.Write.Length;
- UNLOCK_FCB;
-
-#ifdef EXPLICIT_CACHING
- if (!(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO)))
- {
- /* extend file for cached writes */
- LOCK_PAGING_FCB;
- if (offset.QuadPart + length > fcb->FileSize.QuadPart)
- {
- end.QuadPart = offset.QuadPart + length;
- fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = end;
- LOCK_FCB;
- CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
- UNLOCK_FCB;
- /*ret = *//*CcZeroData(IrpSp->FileObject, &oldSizes.FileSize, &end, FALSE);*/ /* should wait? */
- }
- try
- {
- if (!CcCopyWrite(IrpSp->FileObject, &offset, length, TRUE, outPtr))
- {
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- }
- except (EXCEPTION_EXECUTE_HANDLER)
- {
- STATUS(STATUS_UNSUCCESSFUL, 0);
- }
-
- ttlwritten = written = length;
- if (Irp->IoStatus.Status != STATUS_UNSUCCESSFUL && IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
- IrpSp->FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + ttlwritten;
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- if (Irp->IoStatus.Status == STATUS_UNSUCCESSFUL)
- SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- else
-#endif
- {
- while (1)
- {
- if (offset.QuadPart + length > fcb->FileSize.QuadPart)
- change = 1;
- else
- change = 0;
- if (change && !(Irp->Flags & IRP_PAGING_IO))
- paging_lock = 1;
- else
- paging_lock = 0;
- if (paging_lock)
- LOCK_PAGING_FCB;
- LOCK_FCB;
- if (change)
- {
- if (Irp->Flags & IRP_PAGING_IO)
- {
- /* the input buffer and length is for a full page. ignore this. */
- if (offset.QuadPart > fcb->FileSize.QuadPart)
- {
- /* paging lock cannot be held here, so no need to release */
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL2(STATUS_SUCCESS, length);
- }
- length = (ULONG)(fcb->FileSize.QuadPart - offset.QuadPart);
- break;
- }
- else
- {
- if (!change)
- {
- /* paging lock cannot be held here, so no need to release */
- UNLOCK_FCB;
- continue;
- }
- end.QuadPart = offset.QuadPart + length;
- fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = end;
- CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
- if (paging_lock)
- UNLOCK_PAGING_FCB;
- break;
- }
- }
- else
- {
- if (paging_lock)
- UNLOCK_PAGING_FCB;
- break;
- }
- }
-
- for (currpos = ttlwritten = 0; ttlwritten < length; )
- {
- towrite = length - currpos;
- towrite = (towrite > TRANSFER_CHUNK_SIZE) ? TRANSFER_CHUNK_SIZE : towrite;
- curroff.QuadPart = offset.QuadPart + currpos;
- status = uc_write(fcb->fid, curroff, towrite, &written, outPtr);
- if (status == 0)
- {
- ttlwritten += written;
- currpos += written;
- if (written < towrite)
- goto end;
- continue;
- }
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- switch (status)
- {
- case IFSL_RPC_TIMEOUT: SYNC_FAIL_RPC_TIMEOUT;
- case IFSL_BAD_INPUT: SYNC_FAIL(STATUS_INVALID_PARAMETER);
- case IFSL_OVERQUOTA: SYNC_FAIL(STATUS_DISK_FULL);
- default: SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- }
- end:
- if (IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
- IrpSp->FileObject->CurrentByteOffset.QuadPart = offset.QuadPart + ttlwritten;
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- }
-
- /* if we failed a write, we would not be here. so, we must
- * tell the vmm that all data was written. */
- if (Irp->Flags & IRP_PAGING_IO)
- SYNC_FAIL2(STATUS_SUCCESS, IrpSp->Parameters.Write.Length);
- SYNC_FAIL2(STATUS_SUCCESS, ttlwritten);
-}
-
-
-static wchar_t *SEARCH_MATCH_ALL = L"**";
-
-/**********************************************************
- * AfsRdrDirCtrl
- * - handle directory notification callbacks
- * - handle directory enumeration
- *
- * TOD: This code must performing globbing - it does not currently do so.
- **********************************************************/
-NTSTATUS AfsRdrDirCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- struct EnumDirKOut *p;
- LARGE_INTEGER size, creation, access, change, written;
- ULONG attribs, count;
- char buf[2048];
- afs_ccb_t *ccb;
- void *outPtr, *info, *pre_adj_info;
- FILE_BOTH_DIR_INFORMATION *info_both, *info_both_prev;
- FILE_DIRECTORY_INFORMATION *info_dir, *info_dir_prev;
- FILE_NAMES_INFORMATION *info_names, *info_names_prev;
- int info_size;
- readdir_data_t *ii;
- ULONG x, buf_size;
- LARGE_INTEGER last_cookie;
- BOOLEAN overflow;
- NTSTATUS status;
- FILE_NOTIFY_INFORMATION *notify;
-
- if (IsDeviceFile(IrpSp->FileObject))
- SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
-
- if (IrpSp->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
- {
- ccb = IrpSp->FileObject->FsContext2;
- ccb->str.Length = wcslen(ccb->name)*sizeof(wchar_t);
- ccb->str.MaximumLength = ccb->str.Length + sizeof(wchar_t);
- ccb->str.Buffer = ccb->name;
-
- FsRtlEnterFileSystem();
- LOCK_FCB;
- FsRtlNotifyFullChangeDirectory(rdrExt->notifyList, &rdrExt->listHead,
- ccb,
- (STRING*)&ccb->str,
- IrpSp->Flags & SL_WATCH_TREE,
- FALSE,
- /*FILE_NOTIFY_CHANGE_FILE_NAME,*/IrpSp->Parameters.NotifyDirectory.CompletionFilter,
- Irp, NULL, NULL);
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- /* do NOT complete request; that will be done by fsrtlnotify functions */
- return STATUS_PENDING;
- }
-
- if (IrpSp->MinorFunction != IRP_MN_QUERY_DIRECTORY)
- SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
-
- if ( IrpSp->Parameters.QueryDirectory.FileInformationClass != FileBothDirectoryInformation &&
- IrpSp->Parameters.QueryDirectory.FileInformationClass != FileDirectoryInformation &&
- IrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation)
- {
- rpt0(("enum", "enum class %d not supported", IrpSp->Parameters.QueryDirectory.FileInformationClass));
- SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
- }
-
- ccb = IrpSp->FileObject->FsContext2;
-
- if (!(outPtr = AfsFindBuffer(Irp)))
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
- if (IrpSp->Flags & SL_INDEX_SPECIFIED)
- {
- /* we were told where to start our search; afsd should scrub this input */
- ccb->cookie.QuadPart = IrpSp->Parameters.QueryDirectory.FileIndex;
- if (ccb->filter && ccb->filter != SEARCH_MATCH_ALL)
- ExFreePoolWithTag(ccb->filter, AFS_RDR_TAG);
- ccb->filter = SEARCH_MATCH_ALL;
- }
- else if (IrpSp->Flags & SL_RESTART_SCAN ||
- ((IrpSp->Flags & SL_RETURN_SINGLE_ENTRY) && ccb->cookie.QuadPart == 0))
- {
- /* copy new filter string into nonpaged memory */
- ccb->cookie.QuadPart = 0;
- if (ccb->filter && ccb->filter != SEARCH_MATCH_ALL)
- ExFreePoolWithTag(ccb->filter, AFS_RDR_TAG);
- if (IrpSp->Parameters.QueryDirectory.FileName)
- {
- buf_size = IrpSp->Parameters.QueryDirectory.FileName->Length+6;
- ccb->filter = ExAllocatePoolWithTag(NonPagedPool, buf_size, AFS_RDR_TAG);
- RtlCopyMemory(ccb->filter, IrpSp->Parameters.QueryDirectory.FileName->Buffer, buf_size);
- ccb->filter[IrpSp->Parameters.QueryDirectory.FileName->Length / sizeof(WCHAR)] = L'\0';
- }
- else
- ccb->filter = SEARCH_MATCH_ALL;
- }
-
- if (IrpSp->Flags & SL_RETURN_SINGLE_ENTRY)
- count = 1;
- buf_size = 2040;
-
- status = uc_readdir(fcb->fid, ccb->cookie, ccb->filter, &count, buf, &buf_size);
-
- switch (status)
- {
- case IFSL_RPC_TIMEOUT: SYNC_FAIL_RPC_TIMEOUT;
- case IFSL_BAD_INPUT: SYNC_FAIL(STATUS_INVALID_PARAMETER);
- default: SYNC_FAIL(STATUS_UNSUCCESSFUL);
- case 0: break;
- }
-
- switch (IrpSp->Parameters.QueryDirectory.FileInformationClass)
- {
- case FileBothDirectoryInformation:
- info_size = sizeof(FILE_BOTH_DIR_INFORMATION);
- break;
- case FileDirectoryInformation:
- info_size = sizeof(FILE_DIRECTORY_INFORMATION);
- break;
- case FileNamesInformation:
- info_size = sizeof(FILE_NAMES_INFORMATION);
- break;
- default:
- SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
- }
-
- info = (FILE_BOTH_DIR_INFORMATION *)outPtr;
- ii = (readdir_data_t *)buf;
- Irp->IoStatus.Information = 0;
- if (!count)
- {
- if (IrpSp->Flags & SL_RETURN_SINGLE_ENTRY && ccb->cookie.QuadPart == 0)
- SYNC_FAIL(STATUS_NO_SUCH_FILE);
- SYNC_FAIL(STATUS_NO_MORE_FILES);
- }
-
- info_both_prev = NULL;
- info_dir_prev = NULL;
- info_names_prev = NULL;
- if (IrpSp->Flags & SL_RETURN_SINGLE_ENTRY)
- count = 1;
-
- for (x = 0; x < count; x++)
- {
- pre_adj_info = info;
-
- /* must explicitly align second and subsequent entries on 8-byte boundaries */
- if (((ULONG)info & 0x7) && x)
- info = (void*)(((ULONG)info) + (8-((ULONG)info & 0x7)));
-
- overflow = ((long)info + info_size + (long)ii->name_length >
- (long)outPtr + (long)IrpSp->Parameters.QueryDirectory.Length);
- if (overflow && x != 0)
- {
- ccb->cookie = ii->cookie;
- SYNC_FAIL2(STATUS_SUCCESS, (long)pre_adj_info - (long)outPtr);
- }
-
- memset(info, 0, info_size);
- switch (IrpSp->Parameters.QueryDirectory.FileInformationClass)
- {
- case FileBothDirectoryInformation:
- info_both = info;
- if (info_both_prev)
- info_both_prev->NextEntryOffset = (char*)info_both - (char*)info_both_prev;
-
- info_both->NextEntryOffset = 0;
- info_both->FileIndex = (ULONG)ii->cookie.QuadPart;
- info_both->CreationTime.QuadPart = AfsTimeToWindowsTime(ii->creation.QuadPart);
- info_both->LastAccessTime.QuadPart = AfsTimeToWindowsTime(ii->access.QuadPart);
- info_both->LastWriteTime.QuadPart = AfsTimeToWindowsTime(ii->write.QuadPart);
- info_both->ChangeTime.QuadPart = AfsTimeToWindowsTime(ii->change.QuadPart);
- info_both->EndOfFile = info_both->AllocationSize = ii->size;
- info_both->FileAttributes = ii->attribs;/*| FILE_ATTRIBUTE_READONLY*/;
- info_both->EaSize = 0;
- info_both->ShortNameLength = ii->short_name_length;
- info_both->FileNameLength = ii->name_length;
- RtlCopyMemory(info_both->ShortName, ii->short_name, ii->short_name_length*sizeof(WCHAR));
-
- if (overflow)
- {
- Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
- info_both->FileNameLength = 0;
- info_both->FileName[0] = L'\0';
- goto done;
- }
-
- RtlCopyMemory(info_both->FileName, ii->name, ii->name_length*sizeof(WCHAR));
- info_both_prev = info_both;
- break;
-
- case FileDirectoryInformation:
- info_dir = info;
- if (info_dir_prev)
- info_dir_prev->NextEntryOffset = (char*)info_dir - (char*)info_dir_prev;
-
- info_dir->NextEntryOffset = 0;
- info_dir->FileIndex = (ULONG)ii->cookie.QuadPart;
- info_dir->CreationTime.QuadPart = AfsTimeToWindowsTime(ii->creation.QuadPart);
- info_dir->LastAccessTime.QuadPart = AfsTimeToWindowsTime(ii->access.QuadPart);
- info_dir->LastWriteTime.QuadPart = AfsTimeToWindowsTime(ii->write.QuadPart);
- info_dir->ChangeTime.QuadPart = AfsTimeToWindowsTime(ii->change.QuadPart);
- info_dir->EndOfFile = info_dir->AllocationSize = ii->size;
- info_dir->FileAttributes = ii->attribs /*| FILE_ATTRIBUTE_READONLY*/;
- info_dir->FileNameLength = ii->name_length;
-
- if (overflow)
- {
- Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
- info_dir->FileNameLength = 0;
- info_dir->FileName[0] = L'\0';
- goto done;
- }
-
- RtlCopyMemory(info_dir->FileName, ii->name, ii->name_length*sizeof(WCHAR));
- info_dir_prev = info_dir;
- break;
-
- case FileNamesInformation:
- info_names = info;
- if (info_names_prev)
- info_names_prev->NextEntryOffset = (char*)info_names - (char*)info_names_prev;
-
- info_names->NextEntryOffset = 0;
- info_names->FileIndex = (ULONG)ii->cookie.QuadPart;
- info_names->FileNameLength = ii->name_length;
-
- if (overflow)
- {
- Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
- info_names->FileNameLength = 0;
- info_names->FileName[0] = L'\0';
- goto done;
- }
-
- RtlCopyMemory(info_names->FileName, ii->name, ii->name_length*sizeof(WCHAR));
- info_names_prev = info_names;
- break;
- }
-
- info = (void*)(((ULONG)info) + info_size + (ULONG)ii->name_length*sizeof(WCHAR));
- ii = (readdir_data_t *)(((unsigned char *)ii) + sizeof(readdir_data_t) + ii->name_length);
- last_cookie = ii->cookie;
- }
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- done:
- ccb->cookie = last_cookie;
-
- SYNC_FAIL2(Irp->IoStatus.Status, (long)info - (long)outPtr);
-}
-
-
-
-
-/**********************************************************
- * AfsRdrQueryInfo
- * - handle stat calls
- **********************************************************/
-NTSTATUS AfsRdrQueryInfo(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- FILE_BASIC_INFORMATION *infoBasic;
- FILE_NAME_INFORMATION *infoName;
- FILE_STANDARD_INFORMATION *infoStandard;
- FILE_POSITION_INFORMATION *infoPosition;
- FILE_ALL_INFORMATION *infoAll;
- FILE_INTERNAL_INFORMATION *infoInternal;
- LARGE_INTEGER size, creation, access, change, written;
- ULONG attribs;
- long count;
- afs_ccb_t *ccb;
- char *outPtr;
- NTSTATUS status;
- wchar_t *start;
-
- if (IsDeviceFile(IrpSp->FileObject))
- SYNC_FAIL(STATUS_UNSUCCESSFUL); // what should happen?
-
- if (!(outPtr = AfsFindBuffer(Irp)))
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
- ccb = IrpSp->FileObject->FsContext2;
-
- status = uc_stat(fcb->fid, &attribs, &size, &creation, &access, &change, &written);
- switch (status)
- {
- case IFSL_RPC_TIMEOUT: SYNC_FAIL_RPC_TIMEOUT;
- case IFSL_BAD_INPUT: SYNC_FAIL(STATUS_INVALID_PARAMETER);
- default: SYNC_FAIL(STATUS_UNSUCCESSFUL);
- case 0: break;
- }
-
- /* afsd does not maintain instance-specific data, so we adjust here */
- if (ccb->access & FILE_READ_DATA && !(ccb->access & FILE_WRITE_DATA))
- attribs |= FILE_ATTRIBUTE_READONLY;
-
- (void*)infoBasic = (void*)infoName = (void*)infoPosition = (void*)infoStandard = (void*)infoInternal = NULL;
- switch (IrpSp->Parameters.QueryFile.FileInformationClass)
- {
- case FileBasicInformation:
- infoBasic = (FILE_BASIC_INFORMATION*)outPtr;
- break;
- case FileNameInformation:
- infoName = (FILE_NAME_INFORMATION*)outPtr;
- break;
- case FileStandardInformation:
- infoStandard = (FILE_STANDARD_INFORMATION*)outPtr;
- break;
- case FilePositionInformation:
- infoPosition = (FILE_POSITION_INFORMATION*)outPtr;
- break;
- case FileAllInformation:
- infoAll = (FILE_ALL_INFORMATION*)outPtr;
- infoBasic = &infoAll->BasicInformation;
- infoName = &infoAll->NameInformation;
- infoStandard = &infoAll->StandardInformation;
- infoPosition = &infoAll->PositionInformation;
- break;
- case FileInternalInformation:
- infoInternal = (FILE_INTERNAL_INFORMATION*)outPtr;
- break;
- default:
- STATUS(STATUS_NOT_IMPLEMENTED, 0);
- break;
- }
-
- if (infoBasic)
- {
- memset(infoBasic, 0, sizeof(FILE_BASIC_INFORMATION));
- infoBasic->FileAttributes = attribs;
- infoBasic->CreationTime.QuadPart = AfsTimeToWindowsTime(creation.QuadPart);
- infoBasic->LastAccessTime.QuadPart = AfsTimeToWindowsTime(access.QuadPart);
- infoBasic->LastWriteTime.QuadPart = AfsTimeToWindowsTime(written.QuadPart);
- infoBasic->ChangeTime.QuadPart = AfsTimeToWindowsTime(change.QuadPart);
- STATUS(STATUS_SUCCESS, sizeof(FILE_BASIC_INFORMATION));
- //KdPrint(("query basicinfo %d,%d %x,%I64d,%I64d\n", fcb->fid, (ULONG)IrpSp->FileObject->FsContext2, infoBasic->FileAttributes, infoBasic->CreationTime.QuadPart, infoBasic->ChangeTime.QuadPart));
- }
-
- if (infoName)
- {
- memset(infoName, 0, sizeof(FILE_NAME_INFORMATION));
- start = ccb->name;
- count = (long)(*(start+1) - L'0');
- if (count > 9 || count < 0)
- SYNC_FAIL(STATUS_OBJECT_NAME_INVALID);
- if (count || *start == L'0')
- {
- for ( ; count >= 0 && start; count--)
- start = wcschr(start+1, L'\\');
- if (!start)
- SYNC_FAIL(STATUS_OBJECT_NAME_INVALID);
- }
- infoName->FileNameLength = wcslen(start)*sizeof(WCHAR);
- if (((IrpSp->Parameters.QueryFile.FileInformationClass == FileAllInformation) ? sizeof(*infoAll) : sizeof(*infoName)) +
- infoName->FileNameLength > IrpSp->Parameters.QueryFile.Length)
- {
- infoName->FileNameLength = 0;
- infoName->FileName[0] = L'\0';
- STATUS(STATUS_BUFFER_OVERFLOW, sizeof(FILE_NAME_INFORMATION));
- //KdPrint(("query overflowing buffer %d\n", IrpSp->Parameters.QueryFile.Length));
- }
- else
- { //TODO:check filename is correct/correct format
- StringCbCopy(infoName->FileName, IrpSp->Parameters.QueryFile.Length - sizeof(*infoName), start);
- STATUS(STATUS_SUCCESS, sizeof(FILE_NAME_INFORMATION) + (infoName->FileNameLength - sizeof(WCHAR)));
- }
- //KdPrint(("query nameinfo %ws from %ws\n", infoName->FileName, ccb->name));
- }
-
- if (infoStandard)
- {
- memset(infoStandard, 0, sizeof(FILE_STANDARD_INFORMATION));
- infoStandard->AllocationSize.QuadPart = size.QuadPart;
- infoStandard->EndOfFile.QuadPart = size.QuadPart;
- infoStandard->NumberOfLinks = 1;
- infoStandard->DeletePending = (fcb->delPending == 1);
- infoStandard->Directory = (attribs & FILE_ATTRIBUTE_DIRECTORY)?TRUE:FALSE; //TODO:check if flag is valid at this point
- STATUS(STATUS_SUCCESS, sizeof(FILE_STANDARD_INFORMATION));
- //KdPrint(("query stdinfo %d,%d %I64d,%s\n", fcb->fid, (ULONG)IrpSp->FileObject->FsContext2, infoStandard->EndOfFile.QuadPart, infoStandard->Directory?"dir":"file"));
- }
-
- if (infoPosition)
- {
- infoPosition->CurrentByteOffset = IrpSp->FileObject->CurrentByteOffset;
- STATUS(STATUS_SUCCESS, sizeof(FILE_POSITION_INFORMATION));
- //KdPrint(("query position %d,%d %I64d\n", fcb, (ULONG)IrpSp->FileObject->FsContext2, infoPosition->CurrentByteOffset.QuadPart));
- }
-
- if (IrpSp->Parameters.QueryFile.FileInformationClass == FileAllInformation)
- {
- if (!infoName->FileNameLength)
- STATUS(STATUS_BUFFER_OVERFLOW, sizeof(FILE_ALL_INFORMATION));
- else
- STATUS(STATUS_SUCCESS, sizeof(FILE_ALL_INFORMATION) + (infoName->FileNameLength - sizeof(WCHAR)));
- }
-
- if (infoInternal)
- {
- infoInternal->IndexNumber.QuadPart = fcb->fid;
- STATUS(STATUS_SUCCESS, sizeof(FILE_INTERNAL_INFORMATION));
- }
-
- status = Irp->IoStatus.Status;
- COMPLETE;
- return status;
-}
-
-
-
-
-/**********************************************************
- * AfsRdrSetInfo
- * - handle setting mod time
- * - handle deleting
- * - handle truncation/extension
- * - handle renaming
- **********************************************************/
-NTSTATUS AfsRdrSetInfo(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- struct SetInfoKOut *p;
- afs_fcb_t *fcbt;
- afs_ccb_t *ccb;
- FILE_DISPOSITION_INFORMATION *infoDisp;
- FILE_BASIC_INFORMATION *infoBasic;
- FILE_END_OF_FILE_INFORMATION *infoLength;
- FILE_RENAME_INFORMATION *infoRename;
- FILE_POSITION_INFORMATION *infoPosition;
- NTSTATUS ret;
- wchar_t *buf, *part, *ptr;
- ULONG size, new_fid;
- NTSTATUS status;
-
- if ( IrpSp->FileObject->FileName.Length == 0)
- SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
-
- ccb = IrpSp->FileObject->FsContext2;
-
- switch (IrpSp->Parameters.SetFile.FileInformationClass)
- {
- /* delete disposition */
- case FileDispositionInformation:
- infoDisp = Irp->AssociatedIrp.SystemBuffer;
-
- FsRtlEnterFileSystem();
- LOCK_FCB;
-
- if (infoDisp->DeleteFile)
- {
- if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForDelete))
- {
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL(STATUS_ACCESS_DENIED);
- }
- fcb->delPending |= 0x1;
- }
- else
- fcb->delPending &= ~0x1;
- UNLOCK_FCB;
- FsRtlExitFileSystem();
- SYNC_RET(STATUS_SUCCESS);
-
- /*case FileAllocationInformation:*/
- case FileEndOfFileInformation:
- /* ignore extensions caused by paging requests*/
- if (Irp->Flags & IRP_PAGING_IO)
- SYNC_FAIL(STATUS_SUCCESS);
-
- infoLength = Irp->AssociatedIrp.SystemBuffer;
-
- FsRtlEnterFileSystem();
- LOCK_PAGING_FCB;
- LOCK_FCB;
- if (IrpSp->Parameters.SetFile.AdvanceOnly && (infoLength->EndOfFile.QuadPart > fcb->FileSize.QuadPart) ||
- !IrpSp->Parameters.SetFile.AdvanceOnly && (infoLength->EndOfFile.QuadPart < fcb->FileSize.QuadPart))
- {
- status = uc_trunc(fcb->fid, infoLength->EndOfFile);
- /* because it is not written to the server immediately, this error will not always happen */
- if (status == IFSL_OVERQUOTA)
- {
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL(STATUS_DISK_FULL);
- }
- }
- fcb->FileSize = fcb->AllocationSize = fcb->ValidDataLength = infoLength->EndOfFile;
- CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
- //CcPurgeCacheSection(IrpSp->FileObject->SectionObjectPointer, &fcb->AllocationSize, 0, FALSE);
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- SYNC_FAIL(STATUS_SUCCESS);
-
- case FileBasicInformation:
- infoBasic = Irp->AssociatedIrp.SystemBuffer;
- status = uc_setinfo(fcb->fid, infoBasic->FileAttributes, infoBasic->CreationTime, infoBasic->LastAccessTime, infoBasic->ChangeTime, infoBasic->LastWriteTime);
- SYNC_FAIL(STATUS_SUCCESS);
-
- case FileRenameInformation:
- //KdPrint(("set rename %d\n", fcb->fid));
- infoRename = Irp->AssociatedIrp.SystemBuffer;
- new_fid = fcb->fid;
- //rpt1(("setinfo", "rename %d,%d %d,%ws", ExtractFid(fcb), (ULONG)IrpSp->FileObject->FsContext2, infoRename->ReplaceIfExists, infoRename->FileName));
-
- if (IrpSp->Parameters.SetFile.FileObject)
- fcbt = FindFcb(IrpSp->Parameters.SetFile.FileObject);
-
- //null-terminate all strings into uc_rename?
-
- if (IrpSp->Parameters.SetFile.FileObject == NULL &&
- infoRename->RootDirectory == NULL)
- {
- WCHAR fname[MAX_PATH];
- StringCchCopyNW(fname, MAX_PATH-1, infoRename->FileName, infoRename->FileNameLength/sizeof(WCHAR));
- uc_rename(fcb->fid, ccb->name+2, NULL, fname, &new_fid);
- fcb->fid = new_fid;
- }
- else if (IrpSp->Parameters.SetFile.FileObject != NULL &&
- infoRename->RootDirectory == NULL)
- {
- WCHAR fname[300];
- StringCchCopyNW(fname, 300-1, infoRename->FileName, infoRename->FileNameLength/sizeof(WCHAR));
- uc_rename(fcb->fid, ccb->name+2, fcbt->ccb_list->name+2, fname, &new_fid);
- fcb->fid = new_fid;
- }
- else
- {
- /* FIXFIX: implement this case, although we have never seen it called */
- SYNC_RET(STATUS_UNSUCCESSFUL);
-
- /*fcbt = FindFcb(IrpSp->Parameters.SetFile.FileObject);
- p->CurrNameOff = 0;
- StringCbCopyW(buf, size, fcb->name);
- p->NewNameOff = wcslen(buf)+1;
- StringCbCopyNW(buf + p->NewNameOff,
- size - p->NewNameOff,
- infoRename->FileName,
- infoRename->FileNameLength*sizeof(wchar_t));
- buf[p->NewNameOff+infoRename->FileNameLength] = L'\0';
- p->NewDirOff = p->NewNameOff + wcslen(buf + p->NewNameOff)+1;
- StringCbCopyW(buf + p->NewDirOff,
- size - p->NewDirOff,
- fcbt->name);*/
- }
- SYNC_RET(STATUS_SUCCESS);
- break;
-
- case FilePositionInformation:
- infoPosition = Irp->AssociatedIrp.SystemBuffer;
- IrpSp->FileObject->CurrentByteOffset = infoPosition->CurrentByteOffset;
- SYNC_FAIL(STATUS_SUCCESS);
-
- default:
- KdPrint(("set unsupp %d type %d\n", fcb->fid, IrpSp->Parameters.SetFile.FileInformationClass));
- SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
- }
-
- SYNC_FAIL(STATUS_UNSUCCESSFUL);
-}
-
-long
-dc_break_callback(ULONG fid)
-{
- afs_fcb_t *fcb;
- int pos;
- USHORT len;
- UNICODE_STRING *s;
-
- LOCK_FCB_LIST;
-
- fcb = find_fcb(fid);
- if (!fcb)
- {
- UNLOCK_FCB_LIST;
- return 1; /* we are done with this file */
- }
-
- ASSERT(fcb->ccb_list);
-
- len = (wcslen(fcb->ccb_list->name) + 10) * sizeof(wchar_t);
- s = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)+len+sizeof(wchar_t));
- s->Length = len;
- s->MaximumLength = len + sizeof(wchar_t);
- s->Buffer = (PWSTR)(s+1);
-
- /* we are making a bogus change notification for now, because
- * it does what we need.
- */
- StringCbCopyW((PWSTR)(s+1), len, fcb->ccb_list->name);
- if (s->Buffer[wcslen(s->Buffer) - 1] != L'\\')
- StringCbCatW(s->Buffer, len, L"\\");
- pos = wcslen(s->Buffer);
- StringCbCatW(s->Buffer, len, L"jj");
-
- KdPrint(("break callback on %d %ws %ws\n", fid, fcb->ccb_list->name, fcb->ccb_list->name+pos));
-
- FsRtlNotifyFullReportChange(rdrExt->notifyList, &rdrExt->listHead,
- (PSTRING)s, (USHORT)pos*sizeof(wchar_t), NULL, NULL,
- FILE_NOTIFY_CHANGE_FILE_NAME/*FILE_NOTIFY_VALID_MASK/*FILE_NOTIFY_CHANGE_FILE_NAME*/, FILE_ACTION_ADDED, NULL);
-
- ExFreePool(s);
- UNLOCK_FCB_LIST;
- return 0;
-}
-
-long
-dc_release_hooks(void)
-{
- KeSetEvent(&comExt->cancelEvent, 0, FALSE);
- return 0;
-}
-
-/**********************************************************
- * AfsRdrDeviceControl
- * - handle communication requests from fs, etc.
- * - handle ioctls
- **********************************************************/
-NTSTATUS AfsRdrDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- struct KOutEntry *entry;
- NTSTATUS ret;
- struct CbKIn *kin;
- USHORT offset;
- UNICODE_STRING nm;
- void *outPtr;
- ULONG key, code, length;
- LARGE_INTEGER wait;
-
- /* utility ioctls */
- if (DeviceObject == ComDevice &&
- IrpSp->FileObject->FsContext2 == COMM_IOCTL &&
- IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFSRDR_IOCTL)
- {
- outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
- if (!outPtr)
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
- wait.QuadPart = -1000;
- while (rpc_set_context(IrpSp->FileObject->FsContext) != 0) /* if there are no open thread spots... */
- KeDelayExecutionThread(KernelMode, FALSE, &wait); /* ...wait */
- code = uc_ioctl_write(IrpSp->Parameters.DeviceIoControl.InputBufferLength,
- Irp->AssociatedIrp.SystemBuffer,
- (ULONG*)&key);
- length = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
- if (!code)
- code = uc_ioctl_read(key, &length, outPtr);
- rpc_remove_context();
-
- switch (code)
- {
- case IFSL_SUCCESS:
- STATUS(STATUS_SUCCESS, length);
- break;
- default:
- STATUS(STATUS_UNSUCCESSFUL, 0);
- break;
- }
- }
- /* downcalls by afsd */
- else if (DeviceObject == ComDevice &&
- IrpSp->FileObject->FsContext2 == COMM_DOWNCALL &&
- IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFSRDR_DOWNCALL)
- {
- outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
- if (!outPtr)
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
- wait.QuadPart = -1000;
- while (rpc_set_context(IrpSp->FileObject->FsContext) != 0) /* if there are no open thread spots... */
- KeDelayExecutionThread(KernelMode, FALSE, &wait); /* ...wait */
- code = rpc_call(IrpSp->Parameters.DeviceIoControl.InputBufferLength,
- Irp->AssociatedIrp.SystemBuffer,
- IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
- outPtr,
- &length);
- rpc_remove_context();
- switch (code)
- {
- case IFSL_SUCCESS:
- STATUS(STATUS_SUCCESS, length);
- break;
- default:
- STATUS(STATUS_UNSUCCESSFUL, 0);
- break;
- }
- }
- /* ioctl to get full file afs path (used by pioctl) */
- else if (DeviceObject == RdrDevice &&
- IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFSRDR_GET_PATH)
- {
- outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
- if (!outPtr)
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
- StringCbCopyW(outPtr, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, fcb->ccb_list->name+2);
-
- STATUS(STATUS_SUCCESS, (wcslen(outPtr)+1)*sizeof(wchar_t));
- }
- else
- {
- rpt0(("devctl", "devctl %d rejected", IrpSp->Parameters.DeviceIoControl.IoControlCode));
- SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
- }
-
- ret = Irp->IoStatus.Status;
- COMPLETE; /* complete with priority boost */
- return ret;
-}
-
-
-
-/**********************************************************
- * AfsRdrCleanup
- * - called when usermode handle count reaches zero
- **********************************************************/
-NTSTATUS AfsRdrCleanup(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- NTSTATUS ret;
- struct AfsRdrExtension *ext;
-
-#if 0
- try {
-#endif
- if (IrpSp->FileObject->FileName.Length == 0)
- SYNC_FAIL(STATUS_SUCCESS);
-
- ext = ((struct AfsRdrExtension*)RdrDevice->DeviceExtension);
-
- LOCK_FCB_LIST;
- LOCK_PAGING_FCB;
- LOCK_FCB;
-
- FsRtlNotifyCleanup(ext->notifyList, &ext->listHead, IrpSp->FileObject->FsContext2);
-
- IoRemoveShareAccess(IrpSp->FileObject, &fcb->share_access);
-
- CcFlushCache(IrpSp->FileObject->SectionObjectPointer, NULL, 0, NULL);
-
- if (fcb->delPending)
- {
- if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForDelete))
- /* yes, moot at this point */
- STATUS(STATUS_ACCESS_DENIED, 0);
- }
- else
- {
- MmFlushImageSection(IrpSp->FileObject->SectionObjectPointer, MmFlushForWrite);
- STATUS(STATUS_SUCCESS, 0);
- }
-
- CcPurgeCacheSection(IrpSp->FileObject->SectionObjectPointer, NULL, 0, TRUE);
- CcUninitializeCacheMap(IrpSp->FileObject, NULL, NULL);
-
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- UNLOCK_FCB_LIST;
-
-#if 0
- } except(EXCEPTION_EXECUTE_HANDLER)
- {
- STATUS(STATUS_UNSUCCESSFUL, 0);
- ExReleaseResourceLite(&ext->fcbLock);
- FsRtlExitFileSystem();
- }
-#endif
-
- ret = Irp->IoStatus.Status;
- COMPLETE;
- return ret;
-}
-
-
-/**********************************************************
- * AfsRdrClose
- * - handle actual unlinking
- * - handle closing
- **********************************************************/
-NTSTATUS AfsRdrClose(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- ULONG length;
- wchar_t *name;
- char kill;
- KEVENT ev;
- LARGE_INTEGER timeout;
- afs_ccb_t *ccb, *curr;
-
- if (IrpSp->FileObject->FileName.Length == 0)
- SYNC_FAIL(STATUS_SUCCESS);
-
- ccb = IrpSp->FileObject->FsContext2;
- LOCK_FCB_LIST;
-
- ObDereferenceObject(ccb->token);
-
- curr = fcb->ccb_list;
- if (fcb->ccb_list == ccb)
- fcb->ccb_list = fcb->ccb_list->next;
- else
- while (curr->next)
- {
- if (curr->next == ccb)
- {
- curr->next = curr->next->next;
- break;
- }
- curr = curr->next;
- }
-
- if (!fcb->ccb_list)
- {
- uc_close(fcb->fid);
- if (fcb->delPending)
- {
- uc_unlink(ccb->name+2);
- }
- if (fcb->lock)
- FsRtlFreeFileLock(fcb->lock);
- ExDeleteResourceLite(&fcb->_resource);
- ExDeleteResourceLite(&fcb->_pagingIoResource);
- RtlDeleteElementGenericTable(&rdrExt->fcbTable, &fcb);
- ExFreeToNPagedLookasideList(&rdrExt->fcbMemList, fcb);
- }
-
- ExFreePoolWithTag(ccb->name, AFS_RDR_TAG);
- if (ccb->filter && ccb->filter != SEARCH_MATCH_ALL)
- ExFreePoolWithTag(ccb->filter, AFS_RDR_TAG);
- ExFreeToNPagedLookasideList(&rdrExt->ccbMemList, ccb);
-
- UNLOCK_FCB_LIST;
-
- SYNC_FAIL(STATUS_SUCCESS);
-}
-
-
-/**********************************************************
- * AfsRdrShutdown
- * - should flush all data
- **********************************************************/
-NTSTATUS AfsRdrShutdown(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp)
-{
- STATUS(STATUS_SUCCESS, 0);
- COMPLETE;
- return 0;
-}
-
-
-/**********************************************************
- * AfsRdrFlushFile
- * - flushes specified file to userspace and then disk
- **********************************************************/
-NTSTATUS AfsRdrFlushFile(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- NTSTATUS ret;
- afs_ccb_t *ccb;
-
- if (IsDeviceFile(IrpSp->FileObject))
- SYNC_RET(STATUS_INVALID_DEVICE_REQUEST);
-
- ccb = IrpSp->FileObject->FsContext2;
-
- CcFlushCache(&fcb->sectionPtrs, NULL, 0, &Irp->IoStatus);
- uc_flush(fcb->fid);
-
- ret = Irp->IoStatus.Status;
- COMPLETE;
- return ret;
-}
-
-
-/**********************************************************
- * AfsRdrLockCtrl
- * - should handle lock requests
- **********************************************************/
-NTSTATUS AfsRdrLockCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
-{
- NTSTATUS ret;
-
- /* complete lock on control device object without processing, as directed */
- if (IrpSp->FileObject->FileName.Length == 0)
- {
- rpt0(("lock", "lock granted on root device obj"));
- SYNC_FAIL(STATUS_SUCCESS);
- }
-
- switch (IrpSp->MinorFunction)
- {
- case IRP_MN_LOCK:
- case IRP_MN_UNLOCK_ALL:
- case IRP_MN_UNLOCK_ALL_BY_KEY:
- case IRP_MN_UNLOCK_SINGLE:
- FsRtlEnterFileSystem();
- LOCK_PAGING_FCB;
- LOCK_FCB;
- if (!fcb->lock)
- {
- fcb->lock = FsRtlAllocateFileLock(NULL, NULL);
- }
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- FsRtlProcessFileLock(fcb->lock, Irp, NULL);
- fcb->IsFastIoPossible = fcb->lock->FastIoIsQuestionable ? FastIoIsQuestionable : FastIoIsPossible;
- return STATUS_PENDING;
- default:
- SYNC_FAIL2(STATUS_NOT_IMPLEMENTED, 0);
- }
- SYNC_FAIL2(/*STATUS_LOCK_NOT_GRANTED*//*STATUS_NOT_IMPLEMENTED*/STATUS_SUCCESS, 0);
-
- /*EXCEPT(STATUS_UNSUCCESSFUL, 0);*/
-}
-
-
-/**********************************************************
- * AfsRdrQueryVol
- * - handle volume information requests
- **********************************************************/
-NTSTATUS AfsRdrQueryVol(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp)
-{
- FILE_FS_ATTRIBUTE_INFORMATION *infoAttr;
- FILE_FS_DEVICE_INFORMATION *infoDevice;
- FILE_FS_SIZE_INFORMATION * infoSize;
- FILE_FS_VOLUME_INFORMATION *infoVolume;
- NTSTATUS ret;
-
- TRY
-
- switch (IrpSp->Parameters.QueryVolume.FsInformationClass)
- {
- case FileFsAttributeInformation:
- infoAttr = (FILE_FS_ATTRIBUTE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
- memset(infoAttr, 0, sizeof(FILE_FS_ATTRIBUTE_INFORMATION));
- infoAttr->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_CASE_SENSITIVE_SEARCH; //TODOTODO:?
- infoAttr->MaximumComponentNameLength = 255; // should this be 255?
- ///RtlCopyMemory(infoAttr->FileSystemName, L"AFS", 2);
- ///infoAttr->FileSystemNameLength = 2;
- //StringCbCopyLen(infoAttr->FileSystemName, IrpSp->Parameters.QueryVolume.Length-sizeof(*infoAttr)-2, L"AFS", &infoAttr->FileSystemNameLength);
- //IrpSp->Parameters.QueryVolume.Length = 0;
- //Irp->IoStatus.Information = sizeof(*infoAttr) + (infoAttr->FileSystemNameLength - sizeof(WCHAR));
- if (sizeof(*infoAttr) + wcslen(AFS_FS_NAME)*sizeof(wchar_t) > IrpSp->Parameters.QueryVolume.Length)
- {
- infoAttr->FileSystemNameLength = 0;
- rpt0(("vol", "overflowing attr buffer %d", IrpSp->Parameters.QueryVolume.Length));
- SYNC_FAIL2(STATUS_BUFFER_OVERFLOW, sizeof(*infoAttr));
- }
- else
- {
- infoAttr->FileSystemNameLength = wcslen(AFS_FS_NAME)*sizeof(wchar_t);
- StringCbCopyW(infoAttr->FileSystemName, IrpSp->Parameters.QueryVolume.Length - sizeof(*infoAttr) + sizeof(WCHAR), AFS_FS_NAME);
- SYNC_FAIL2(STATUS_SUCCESS, sizeof(*infoAttr) + (infoAttr->FileSystemNameLength - sizeof(WCHAR)));
- }
- break;
-
- case FileFsDeviceInformation:
- infoDevice = (FILE_FS_DEVICE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
- memset(infoDevice, 0, sizeof(FILE_FS_DEVICE_INFORMATION));
- infoDevice->DeviceType = FILE_DEVICE_DISK;//DeviceObject->DeviceType;// FILE_DEVICE_NETWORK_FILE_SYSTEM;
- infoDevice->Characteristics = DeviceObject->Characteristics;//FILE_DEVICE_IS_MOUNTED /*| FILE_REMOTE_DEVICE*/; // remote device?
- IrpSp->Parameters.QueryVolume.Length = sizeof(*infoDevice);
- SYNC_FAIL2(STATUS_SUCCESS, IrpSp->Parameters.QueryVolume.Length);
- break;
-
- case FileFsSizeInformation:
- infoSize = (FILE_FS_SIZE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
- memset(infoSize, 0, sizeof(FILE_FS_SIZE_INFORMATION));
- /* this data needs to come from an upcall */
- infoSize->TotalAllocationUnits.QuadPart = 0x00000000F0000000;
- infoSize->AvailableAllocationUnits.QuadPart = 0x00000000E0000000;
- infoSize->SectorsPerAllocationUnit = 1;
- infoSize->BytesPerSector = 1;
- IrpSp->Parameters.QueryVolume.Length = sizeof(*infoSize);
- SYNC_FAIL2(STATUS_SUCCESS, IrpSp->Parameters.QueryVolume.Length);
- break;
-
- case FileFsVolumeInformation:
- infoVolume = (FILE_FS_VOLUME_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
- memset(infoVolume, 0, sizeof(FILE_FS_VOLUME_INFORMATION));
- /* this data needs to come from an upcall */
- infoVolume->VolumeCreationTime.QuadPart = AfsTimeToWindowsTime(1080000000);
- infoVolume->VolumeSerialNumber = 0x12345678;
- infoVolume->SupportsObjects = FALSE;
- //StringCbCopyLen(infoVolume->VolumeLabel, IrpSp->Parameters.QueryVolume.Length-sizeof(*infoVolume)-2, L"AfsRed", &infoVolume->VolumeLabelLength);
- //IrpSp->Parameters.QueryVolume.Length = 0;
- if (sizeof(*infoVolume) + 12 > IrpSp->Parameters.QueryVolume.Length)
- {
- infoVolume->VolumeLabelLength = 0;
- SYNC_FAIL2(STATUS_BUFFER_OVERFLOW, sizeof(*infoVolume));
- }
- else
- {
- infoVolume->VolumeLabelLength = 12;
- RtlCopyMemory(infoVolume->VolumeLabel, L"AfsRed", 12);
- SYNC_FAIL2(STATUS_SUCCESS, sizeof(*infoVolume) + (infoVolume->VolumeLabelLength - sizeof(WCHAR)));
- }
- break;
- }
-
- EXCEPT(STATUS_UNSUCCESSFUL, 0);
-
- rpt0(("vol", "vol class %d unknown", IrpSp->Parameters.QueryVolume.FsInformationClass));
- SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
-}
-
-VOID AfsRdrUnload(DRIVER_OBJECT *DriverObject)
-{
- UNICODE_STRING userModeName;
-
- FsRtlNotifyUninitializeSync(&rdrExt->notifyList);
-
- RtlInitUnicodeString(&userModeName, L"\\DosDevices\\afscom");
- IoDeleteSymbolicLink(&userModeName);
-
- /*RtlInitUnicodeString(&userModeName, L"\\DosDevices\\T:");
- IoDeleteSymbolicLink(&userModeName);*/
-
- ExDeleteNPagedLookasideList(&rdrExt->fcbMemList);
- ExDeleteNPagedLookasideList(&rdrExt->ccbMemList);
-
- rpc_shutdown();
-
- IoDeleteDevice(ComDevice);
- IoDeleteDevice(RdrDevice);
-
- KdPrint(("RdrUnload exiting.\n"));
-}
-
-
-// handles all non-handled irp's synchronously
-NTSTATUS AfsRdrNull(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp)
-{
- NTSTATUS ret;
-
- /*TRY
- rpt0(("kunhand", IrpMjFuncDesc[IrpSp->MajorFunction]));*/
-
- SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
-
- /*EXCEPT(STATUS_UNSUCCESSFUL, 0);
-
- ret = Irp->IoStatus.Status;
- COMPLETE_NO_BOOST;
- return ret;*/
-}
-
-NTSTATUS ComDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
-{
- IO_STACK_LOCATION *IrpSp, *IrpSpClient;
- NTSTATUS ret;
- struct ComExtension *ext;
- void *ptr, *ptr2;
- rpc_t find, *find_ptr;
- LARGE_INTEGER timeout;
- struct afsFcb *fcb;
- rpc_t *rpc, **rpcp;
- ULONG len;
- ULONG code, read;
- PACCESS_TOKEN acc_token;
- PVOID waitPair[2];
-
- ext = (struct ComExtension *)DeviceObject->DeviceExtension;
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- switch (IrpSp->MajorFunction)
- {
- case IRP_MJ_CREATE:
- IrpSp->FileObject->FsContext = 0;
- IrpSp->FileObject->FsContext2 = 0;
- if (IrpSp->FileObject->FileName.Length)
- {
- /* ioctls come from fs, vos, bos, etc. using a pre-existing interface */
- /* downcalls come from afsd, using a new interface */
- /* upcall hooks come from afsd */
- if (!wcscmp(IrpSp->FileObject->FileName.Buffer, L"\\ioctl"))
- IrpSp->FileObject->FsContext2 = COMM_IOCTL;
- else if (!wcscmp(IrpSp->FileObject->FileName.Buffer, L"\\downcall"))
- IrpSp->FileObject->FsContext2 = COMM_DOWNCALL;
- else if (!wcscmp(IrpSp->FileObject->FileName.Buffer, L"\\upcallhook"))
- IrpSp->FileObject->FsContext2 = COMM_UPCALLHOOK;
- }
- if (!IrpSp->FileObject->FsContext2)
- SYNC_FAIL2(STATUS_INVALID_DEVICE_REQUEST, 0);
-
- acc_token = SeQuerySubjectContextToken(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
- ASSERT(acc_token);
- /* SeQueryAuthenticationIdToken */
- IrpSp->FileObject->FsContext = acc_token;
- STATUS(STATUS_SUCCESS, FILE_OPENED);
- break;
-
- case IRP_MJ_CLEANUP:
- /* acc_token does not have to be released */
- case IRP_MJ_CLOSE:
- STATUS(STATUS_SUCCESS, 0);
- break;
-
- case IRP_MJ_WRITE:
- /* we only process MDL writes */
- if (!Irp->MdlAddress ||
- !(ptr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority))) /* should be LowPagePriority */
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
- if (!IrpSp->FileObject->FsContext ||
- !IrpSp->FileObject->FsContext2)
- SYNC_FAIL(STATUS_INVALID_HANDLE);
-
- if (IrpSp->FileObject->FsContext2 == COMM_UPCALLHOOK)
- {
- rpc_recv(ptr, IrpSp->Parameters.Write.Length);
- STATUS(STATUS_SUCCESS, IrpSp->Parameters.Write.Length);
- }
- else
- STATUS(STATUS_INVALID_DEVICE_REQUEST, 0);
- break;
- case IRP_MJ_READ:
- if (!Irp->MdlAddress || !(ptr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority))) // should be LowPagePriority
- SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
-
- if (IrpSp->FileObject->FsContext2 == COMM_UPCALLHOOK)
- {
- KeClearEvent(&comExt->cancelEvent);
-
- timeout.QuadPart = -100000000L;
- waitPair[0] = &comExt->outEvent;
- waitPair[1] = &comExt->cancelEvent;
- ret = KeWaitForMultipleObjects(2, waitPair, WaitAny, Executive, KernelMode, FALSE, &timeout, NULL);
-
- if (ret == STATUS_WAIT_1)
- SYNC_FAIL(STATUS_UNSUCCESSFUL);
-
- if (!rpc_send(ptr, IrpSp->Parameters.Read.Length, &read))
- {
- KeClearEvent(&comExt->outEvent);
- ret = KeWaitForMultipleObjects(2, waitPair, WaitAny, Executive, KernelMode, FALSE, &timeout, NULL);
- if (!rpc_send(ptr, IrpSp->Parameters.Read.Length, &read))
- {
- KeClearEvent(&comExt->outEvent);
- SYNC_FAIL(STATUS_UNSUCCESSFUL);
- }
- }
- SYNC_RET2(STATUS_SUCCESS, read); /* complete with priority boost */
- }
- else
- STATUS(STATUS_INVALID_DEVICE_REQUEST, 0);
- break;
- case IRP_MJ_DEVICE_CONTROL:
- return AfsRdrDeviceControl(DeviceObject, Irp, IrpSp, NULL);
- default:
- STATUS(STATUS_INVALID_DEVICE_REQUEST, 0);
- break;
- }
-
- ret = Irp->IoStatus.Status;
- COMPLETE; /* complete with priority boost */
- return ret;
-}
-
-
-/* handles all irp's for primary (fs) device */
-NTSTATUS Dispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
-{
- IO_STACK_LOCATION *IrpSp;
- NTSTATUS ret;
- afs_fcb_t *fcb;
- afs_ccb_t *ccb;
- LARGE_INTEGER wait;
-
- if (DeviceObject->DeviceType == FILE_DEVICE_DATALINK)
- return ComDispatch(DeviceObject, Irp);
-
- IrpSp = IoGetCurrentIrpStackLocation(Irp);
-
- rpt4(("irp", "%s min %d on %d (%ws) %x %x", IrpMjFuncDesc[IrpSp->MajorFunction], IrpSp->MinorFunction, 0/*ExtractFid(IrpSp->FileObject->FsContext)*/, IrpSp->FileObject->FileName.Buffer, IrpSp->Flags, IrpSp->Parameters.Create.Options));
-
- fcb = IrpSp->FileObject->FsContext;
- if (IrpSp->MajorFunction != IRP_MJ_CREATE)
- ASSERT(fcb);
-
- if (IrpSp->FileObject && IrpSp->FileObject->FsContext2)
- {
- ccb = IrpSp->FileObject->FsContext2;
- wait.QuadPart = -1000;
- while (rpc_set_context(ccb->token) != 0) /* if there are no open thread spots... */
- KeDelayExecutionThread(KernelMode, FALSE, &wait); /* ...wait */
- }
-
- switch (IrpSp->MajorFunction)
- {
- case IRP_MJ_CREATE:
- ret = AfsRdrCreate(DeviceObject, Irp, IrpSp, NULL);
- break;
- case IRP_MJ_DIRECTORY_CONTROL:
- ret = AfsRdrDirCtrl(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_READ:
- ret = AfsRdrRead(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_WRITE:
- ret = AfsRdrWrite(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_CLOSE:
- ret = AfsRdrClose(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_QUERY_INFORMATION:
- ret = AfsRdrQueryInfo(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_DEVICE_CONTROL:
- ret = AfsRdrDeviceControl(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_CLEANUP:
- ret = AfsRdrCleanup(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_LOCK_CONTROL:
- ret = AfsRdrLockCtrl(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_QUERY_VOLUME_INFORMATION:
- ret = AfsRdrQueryVol(DeviceObject, Irp, IrpSp);
- break;
- case IRP_MJ_SHUTDOWN:
- ret = AfsRdrShutdown(DeviceObject, Irp, IrpSp);
- break;
- case IRP_MJ_FILE_SYSTEM_CONTROL:
- if (IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST &&
- (IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_1 ||
- IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2 ||
- IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK ||
- IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK))
- STATUS(STATUS_OPLOCK_NOT_GRANTED, 0);
- else
- STATUS(STATUS_INVALID_DEVICE_REQUEST/*STATUS_NOT_IMPLEMENTED*//*STATUS_INVALID_PARAMETER*/, 0);
- ret = Irp->IoStatus.Status;
- goto complete;
- case IRP_MJ_SET_INFORMATION:
- ret = AfsRdrSetInfo(DeviceObject, Irp, IrpSp, fcb);
- break;
- case IRP_MJ_FLUSH_BUFFERS:
- ret = AfsRdrFlushFile(DeviceObject, Irp, IrpSp, fcb);
- break;
- default:
- ret = AfsRdrNull(DeviceObject, Irp, IrpSp);
- break;
- }
- rpc_remove_context();
- return ret;
-
- complete:
- rpc_remove_context();
- COMPLETE;
- return ret;
-}
-
-
-BOOLEAN
-fastIoCheck (
- IN struct _FILE_OBJECT *FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
- IN BOOLEAN CheckForReadOperation,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN struct _DEVICE_OBJECT *DeviceObject
- )
-{
-afs_fcb_t *fcb;
-LARGE_INTEGER temp;
-
-fcb = FileObject->FsContext;
-ASSERT(fcb);
-
-if (!fcb->lock)
- return TRUE;
-
-temp.QuadPart = Length;
-if (CheckForReadOperation)
- return FsRtlFastCheckLockForRead(fcb->lock, FileOffset, &temp, LockKey, FileObject, IoGetCurrentProcess());
-return FsRtlFastCheckLockForWrite(fcb->lock, FileOffset, &temp, LockKey, FileObject, IoGetCurrentProcess());
-}
-
-
-BOOLEAN
-fastIoRead (
- IN struct _FILE_OBJECT *FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
- OUT PVOID Buffer,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN struct _DEVICE_OBJECT *DeviceObject
- )
-{
- BOOLEAN ret;
- ULONG adj_len;
- afs_fcb_t *fcb;
- LARGE_INTEGER temp;
-
- fcb = FileObject->FsContext;
- ASSERT(fcb);
-
- FsRtlEnterFileSystem();
- LOCK_PAGING_FCB;
-
- if (fcb->lock)
- {
- temp.QuadPart = Length;
- if (!FsRtlFastCheckLockForRead(fcb->lock, FileOffset, &temp, LockKey, FileObject, IoGetCurrentProcess()))
- {
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- return FALSE;
- }
- }
-
- adj_len = Length;
- if (FileOffset->QuadPart > fcb->FileSize.QuadPart)
- {
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- IoStatus->Status = STATUS_END_OF_FILE;
- IoStatus->Information = 0;
- return TRUE;
- }
- if (FileOffset->QuadPart + Length > fcb->FileSize.QuadPart)
- adj_len = (ULONG)(fcb->FileSize.QuadPart - FileOffset->QuadPart);
-
- try
- {
- ret = CcCopyRead(FileObject, FileOffset, adj_len, Wait, Buffer, IoStatus);
-
- FileObject->CurrentByteOffset.QuadPart = FileOffset->QuadPart + IoStatus->Information;
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- }
- except (EXCEPTION_EXECUTE_HANDLER)
- {
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- return FALSE;
- }
- return ret;
-}
-
-BOOLEAN
-fastIoWrite (
- IN struct _FILE_OBJECT *FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
- OUT PVOID Buffer,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN struct _DEVICE_OBJECT *DeviceObject
- )
-{
- BOOLEAN ret;
- LARGE_INTEGER adj_end;
- afs_fcb_t *fcb;
- LARGE_INTEGER temp;
-
- fcb = FileObject->FsContext;
- ASSERT(fcb);
-
- FsRtlEnterFileSystem();
- LOCK_PAGING_FCB;
-
- if (fcb->lock)
- {
- temp.QuadPart = Length;
- if (!FsRtlFastCheckLockForWrite(fcb->lock, FileOffset, &temp, LockKey, FileObject, IoGetCurrentProcess()))
- {
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- return FALSE;
- }
- }
-
-
- if (FileOffset->QuadPart + Length > fcb->FileSize.QuadPart)
- {
- adj_end.QuadPart = FileOffset->QuadPart + Length;
- fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = adj_end;
- LOCK_FCB;
- try
- {
- CcSetFileSizes(FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
- }
- except (EXCEPTION_EXECUTE_HANDLER)
- {
- UNLOCK_FCB;
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- return FALSE;
- }
- UNLOCK_FCB;
- }
-
- try
- {
- ret = CcCopyWrite(FileObject, FileOffset, Length, Wait, Buffer);
- IoStatus->Status = ret?STATUS_SUCCESS:STATUS_UNSUCCESSFUL;
- IoStatus->Information = ret?Length:0;
-
- FileObject->CurrentByteOffset.QuadPart = FileOffset->QuadPart + IoStatus->Information;
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- }
- except (EXCEPTION_EXECUTE_HANDLER)
- {
- UNLOCK_PAGING_FCB;
- FsRtlExitFileSystem();
- return FALSE;
- }
- return ret;
-}
-
-RTL_GENERIC_COMPARE_RESULTS FcbCompareRoutine(struct _RTL_GENERIC_TABLE *Table, PVOID FirstStruct, PVOID SecondStruct)
-{
- afs_fcb_t *p1, *p2;
-
- p1 = (void*)*(afs_fcb_t**)FirstStruct; p2 = (void*)*(afs_fcb_t**)SecondStruct;
- if (p1->fid < p2->fid)
- return GenericLessThan;
- if (p1->fid > p2->fid)
- return GenericGreaterThan;
- return GenericEqual;
-}
-
-RTL_GENERIC_COMPARE_RESULTS ReqCompareRoutine(struct _RTL_GENERIC_TABLE *Table, PVOID FirstStruct, PVOID SecondStruct)
-{
- rpc_t *p1, *p2;
-
- p1 = *(rpc_t**)FirstStruct; p2 = *(rpc_t**)SecondStruct;
- if (p1->key < p2->key)
- return GenericLessThan;
- if (p1->key > p2->key)
- return GenericGreaterThan;
- return GenericEqual;
-}
-
-PVOID AllocateRoutine(struct _RTL_GENERIC_TABLE *Table, CLONG ByteSize)
-{
- PVOID ret;
- ret = ExAllocatePoolWithTag(NonPagedPool, ByteSize, AFS_RDR_TAG);
- ASSERT(ret);
- RtlZeroMemory(ret, ByteSize);
- return ret;
-}
-
-VOID FreeRoutine(struct _RTL_GENERIC_TABLE *Table, PVOID Buffer)
-{
- ExFreePoolWithTag(Buffer, AFS_RDR_TAG);
-}
-
-//KSPIN_LOCK rpc_lock;
-//KIRQL irql;
-FAST_MUTEX rpc_lock;
-
-void ifs_lock_rpcs()
-{
- ExAcquireFastMutex(&rpc_lock);
- //KeAcquireSpinLock(&rpc_lock, &irql);
-}
-
-void ifs_unlock_rpcs()
-{
- ExReleaseFastMutex(&rpc_lock);
- //KeReleaseSpinLock(&rpc_lock, irql);
-}
-
-NTSTATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
-{
- NTSTATUS err;
- UNICODE_STRING rdrName, comName, userModeName, userModeCom;
- int x;
- IO_STATUS_BLOCK status;
- FAST_IO_DISPATCH *fastIoDispatch;
-
- //try {
- RtlInitUnicodeString(&rdrName, L"\\Device\\afsrdr");
- RtlInitUnicodeString(&comName, L"\\Device\\afscom");
-
- rpt0(("init", "kern initializing"));
- //KeInitializeSpinLock(&rpc_lock);
- ExInitializeFastMutex(&rpc_lock);
-
- IoAllocateDriverObjectExtension(DriverObject, (void *)0x394389f7, sizeof(FAST_IO_DISPATCH), &fastIoDispatch);
- RtlZeroMemory(fastIoDispatch, sizeof(FAST_IO_DISPATCH));
- fastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
- fastIoDispatch->FastIoCheckIfPossible = fastIoCheck;
- fastIoDispatch->FastIoRead = /*FsRtlCopyRead;*/fastIoRead;
- fastIoDispatch->FastIoWrite = /*FsRtlCopyWrite;*/fastIoWrite;
- DriverObject->FastIoDispatch = fastIoDispatch;
-
- for (x = 0; x < IRP_MJ_MAXIMUM_FUNCTION; x++)
- DriverObject->MajorFunction[x] = Dispatch;
- DriverObject->DriverUnload = AfsRdrUnload;
-
- err = IoCreateDevice(DriverObject, sizeof(struct AfsRdrExtension)*2, &rdrName, FILE_DEVICE_NETWORK_FILE_SYSTEM, /*FILE_REMOTE_DEVICE*/0, FALSE, &RdrDevice);
- if (!NT_SUCCESS(STATUS_SUCCESS))
- return STATUS_UNSUCCESSFUL;
- err = IoCreateDevice(DriverObject, sizeof(struct ComExtension)*2, &comName, FILE_DEVICE_DATALINK, 0, FALSE, &ComDevice);
- if (!NT_SUCCESS(STATUS_SUCCESS))
- return STATUS_UNSUCCESSFUL;
-
- RdrDevice->Flags |= DO_DIRECT_IO;
- RdrDevice->StackSize = 5; /* could this be zero? */
- rdrExt = ((struct AfsRdrExtension*)RdrDevice->DeviceExtension);
- RtlZeroMemory(rdrExt, sizeof(struct AfsRdrExtension));
-
- /* could raise exception */
- FsRtlNotifyInitializeSync(&rdrExt->notifyList);
- InitializeListHead(&rdrExt->listHead);
-
- rdrExt->callbacks.AcquireForLazyWrite = lazyWriteLock;
- rdrExt->callbacks.ReleaseFromLazyWrite = lazyWriteUnlock;
- rdrExt->callbacks.AcquireForReadAhead = readAheadLock;
- rdrExt->callbacks.ReleaseFromReadAhead = readAheadUnlock;
- ExInitializeNPagedLookasideList(&rdrExt->fcbMemList, NULL, NULL, 0, sizeof(afs_fcb_t), AFS_RDR_TAG, 0);
- ExInitializeNPagedLookasideList(&rdrExt->ccbMemList, NULL, NULL, 0, sizeof(afs_ccb_t), AFS_RDR_TAG, 0);
- ExInitializeFastMutex(&rdrExt->fcbLock);
- RtlInitializeGenericTable(&rdrExt->fcbTable, FcbCompareRoutine, AllocateRoutine, FreeRoutine, NULL);
-
-
- ComDevice->Flags |= DO_DIRECT_IO;
- ComDevice->StackSize = 5; // ??
- comExt = ((struct ComExtension*)ComDevice->DeviceExtension);
- RtlZeroMemory(comExt, sizeof(struct ComExtension));
-
- InitializeListHead(&comExt->outReqList);
- KeInitializeSpinLock(&comExt->outLock);
- ExInitializeFastMutex(&comExt->inLock);
- KeInitializeEvent(&comExt->outEvent, SynchronizationEvent/*NotificationEvent*/, TRUE);
- KeInitializeEvent(&comExt->cancelEvent, NotificationEvent, TRUE);
-
- comExt->rdr = rdrExt;
- rdrExt->com = comExt;
-
- RtlInitUnicodeString(&userModeCom, L"\\DosDevices\\afscom");
- err = IoCreateSymbolicLink(&userModeCom, &comName);
-
- /*RtlInitUnicodeString(&rdrName, L"\\Device\\afsrdr\\1\\CITI.UMICH.EDU");
- RtlInitUnicodeString(&userModeName, L"\\DosDevices\\W:");
- err = IoCreateSymbolicLink(&userModeName, &rdrName);*/
-
- /*} except(EXCEPTION_EXECUTE_HANDLER)
- {
- return -1;
- }*/
-
- KdPrint(("DriverEntry exiting.\n"));
- return STATUS_SUCCESS;
-}
+++ /dev/null
-/* copyright (c) 2005
- * the regents of the university of michigan
- * all rights reserved
- *
- * permission is granted to use, copy, create derivative works and
- * redistribute this software and such derivative works for any purpose,
- * so long as the name of the university of michigan is not used in
- * any advertising or publicity pertaining to the use or distribution
- * of this software without specific, written prior authorization. if
- * the above copyright notice or any other identification of the
- * university of michigan is included in any copy of any portion of
- * this software, then the disclaimer below must also be included.
- *
- * this software is provided as is, without representation from the
- * university of michigan as to its fitness for any purpose, and without
- * warranty by the university of michigan of any kind, either express
- * or implied, including without limitation the implied warranties of
- * merchantability and fitness for a particular purpose. the regents
- * of the university of michigan shall not be liable for any damages,
- * including special, indirect, incidental, or consequential damages,
- * with respect to any claim arising out or in connection with the use
- * of the software, even if it has been or is hereafter advised of the
- * possibility of such damages.
- */
-
-/* versioning history
- *
- * 03-jun 2005 (eric williams) entered into versioning
- */
-
-#ifdef RPC_KERN
-#include <ntifs.h>
-#include "ifs_rpc.h"
-#include "afsrdr.h"
-#else
-#include "ifs_rpc.h"
-#endif
-#include "kif.h"
-
-/* general internal functions */
-rpc_t *rpc_create(int size_hint);
-void rpc_destroy(rpc_t *rpc);
-int rpc_marshal_long(rpc_t *rpc, ULONG data);
-int rpc_marshal_longlong(rpc_t *rpc, LARGE_INTEGER data);
-int rpc_marshal_wstr(rpc_t *rpc, WCHAR *str);
-int rpc_unmarshal_long(rpc_t *rpc, ULONG *data);
-int rpc_unmarshal_longlong(rpc_t *rpc, LARGE_INTEGER *data);
-int rpc_unmarshal_wstr(rpc_t *rpc, WCHAR *str);
-
-/* kernel-queue specific internal functions */
-#ifdef RPC_KERN
-int rpc_queue(rpc_t *rpc);
-rpc_queue_bulk(rpc_t *rpc, char *out_bulk, ULONG out_len, char *in_bulk, ULONG in_len);
-rpc_cancel(rpc_t *rpc);
-rpc_send_reg(rpc_t *rpc, char *out_buf);
-rpc_queue_bulk_mdl(rpc_t *rpc, MDL *mdl);
-rpc_t *rpc_find(int id);
-rpc_t *rpc_upgrade(rpc_t *rpc, int old_status, int new_status);
-rpc_wait(rpc_t *rpc, BOOLEAN long_op);
-rpc_send_mdl(rpc_t *rpc, char *out_buf);
-#endif
-
-
-/****** rpc security kernel functions ******/
-/* before making an upcall from kernel code, set the security context by
- * passing the access_token to rpc_set_context. remove the context after all
- * upcalls are done. the rpc library automatically checks and sets this
- * same context on the other end. */
-#ifdef RPC_KERN
-struct rpc_cred_map_entry
-{
- void *token;
- PETHREAD thread;
- int refs;
-};
-
-struct rpc_cred_map_entry cred_map[MAX_CRED_MAPS];
-rpc_t *rpc_list_head = NULL;
-long num_rpcs = 0;
-
-rpc_set_context(void *context)
-{
- int x, empty, ret;
- PETHREAD thd;
-
- thd = PsGetCurrentThread();
- empty = -1;
- ret = 0;
-
- ifs_lock_rpcs();
- for (x = 0; x < MAX_CRED_MAPS; x++)
- {
- if (cred_map[x].thread == NULL)
- empty = x;
- if (cred_map[x].thread == thd)
- {
- //////FIX///ASSERT(cred_map[x].token == context);
- cred_map[x].refs++;
- //cred_map[x].token = context;
- goto done;
- }
- }
- if (empty != -1)
- {
- cred_map[empty].thread = thd;
- cred_map[empty].token = context;
- cred_map[empty].refs = 1;
- }
- else
- ret = -1;
-
- done:
- ifs_unlock_rpcs();
- return ret;
-}
-
-void *rpc_get_context()
-{
- int x;
- PETHREAD thd;
-
- thd = PsGetCurrentThread();
-
- // no lock
- for (x = 0; x < MAX_CRED_MAPS; x++)
- if (cred_map[x].thread == thd)
- return cred_map[x].token;
- // no unlock
- return NULL;
-}
-
-rpc_remove_context()
-{
- int x;
- PETHREAD thd;
-
- thd = PsGetCurrentThread();
- ifs_lock_rpcs();
- for (x = 0; x < MAX_CRED_MAPS; x++)
- if (cred_map[x].thread == thd)
- {
- if (cred_map[x].refs > 1)
- {
- cred_map[x].refs--;
- }
- else
- {
- cred_map[x].token = NULL;
- cred_map[x].thread = NULL;
- }
- ifs_unlock_rpcs();
- return 0;
- }
-
- ifs_unlock_rpcs();
- return -1;
-}
-#endif
-
-
-/* rpc stubs in kernel */
-#ifdef RPC_KERN
-rpc_t *rpc_create(int size_hint)
-{
- ULONG size;
- rpc_t *rpc;
- SECURITY_SUBJECT_CONTEXT subj_context;
- PACCESS_TOKEN acc_token;
- LUID auth_id;
- LARGE_INTEGER user_id;
- NTSTATUS status;
- HANDLE token;
-
- /* get user's identification from auth token*/
- token = rpc_get_context();
- ASSERT(token);
- status = SeQueryAuthenticationIdToken(token, &auth_id);
-
- user_id.LowPart = auth_id.LowPart;
- user_id.HighPart = auth_id.HighPart;
-
- ifs_lock_rpcs();
-
- if (!(rpc = rpc_upgrade(NULL, 0, 1)))
- {
- size = sizeof(rpc_t) + 2*RPC_BUF_SIZE;
- rpc = ExAllocatePoolWithTag(NonPagedPool, size, 0x1234);
- if (!rpc)
- return NULL;
- num_rpcs++;
- memset(rpc, 0, size);
- rpc->next = rpc_list_head;
- rpc_list_head = rpc;
- rpc_upgrade(rpc, 0, 1);
- }
-
- rpc->out_buf = rpc->out_pos = (char*)(rpc+1);
- rpc->in_buf = rpc->in_pos = ((char*)(rpc+1))+RPC_BUF_SIZE;
-
- rpc->key = rand() + 10;
- rpc_marshal_long(rpc, rpc->key);
- rpc->bulk_out_len = (ULONG*)rpc->out_pos;
- rpc_marshal_long(rpc, 0);
-
-#if 0
- /* another way of obtaining credentials, with different effects */
- SeCaptureSubjectContext(&subj_context);
- acc_token = SeQuerySubjectContextToken(&subj_context);
- status = SeQueryAuthenticationIdToken(acc_token, &auth_id);
-
- user_id.LowPart = auth_id.LowPart;
- user_id.HighPart = auth_id.HighPart;
- SeReleaseSubjectContext(&subj_context);
-#endif
-
- rpc_marshal_longlong(rpc, user_id);
-
- ifs_unlock_rpcs();
-
- return rpc;
-}
-
-void rpc_destroy(rpc_t *rpc)
-{
- rpc_t *curr;
- int count;
-
- ifs_lock_rpcs();
-
- if (rpc_upgrade(rpc, -1, 0))
- ;
-
- ifs_unlock_rpcs();
-}
-#endif
-
-
-/* rpc internal functions for usermode */
-#ifndef RPC_KERN
-rpc_t *rpc_create(int size_hint)
-{
- ULONG size;
- rpc_t *rpc;
-
- size = sizeof(rpc_t) + 2*RPC_BUF_SIZE;
- rpc = malloc(size);
- if (!rpc)
- osi_panic("ifs_rpc: alloc buffer", __FILE__, __LINE__);
- memset(rpc, 0, size);
-
- rpc->out_buf = rpc->out_pos = (char*)(rpc+1);
- rpc->in_buf = rpc->in_pos = ((char*)(rpc+1)) + RPC_BUF_SIZE;
-
- rpc->key = rand() + 10;
- rpc_marshal_long(rpc, rpc->key);
-
- return rpc;
-}
-
-void rpc_destroy(rpc_t *rpc)
-{
- if (!rpc)
- return;
-
- free(rpc);
-}
-
-rpc_transact(rpc_t *rpc)
-{
- ULONG header_len;
- DWORD read = 0;
-
- if (!rpc)
- return IFSL_GENERIC_FAILURE;
-
- header_len = rpc->out_pos - rpc->out_buf;
-
- read = RPC_BUF_SIZE;
- return ifs_TransactRpc(rpc->out_buf, header_len, rpc->in_buf, &read);
-}
-#endif
-
-
-/* upcall stubs */
-#ifdef RPC_KERN
-long
-uc_namei(WCHAR *name, ULONG *fid)
-{
- rpc_t *rpc;
- ULONG status;
- MDL *mdl;
-
- /* consider putting namei cache here */
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_NAMEI);
- rpc_marshal_long(rpc, wcslen(name));
-
- rpc_queue_bulk(rpc, (void*)name, (wcslen(name)+1)*sizeof(wchar_t), NULL, 0);
-
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel namei"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, fid);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_check_access(ULONG fid, ULONG access, ULONG *granted)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_CHECK_ACCESS);
- rpc_marshal_long(rpc, fid);
- rpc_marshal_long(rpc, access);
-
- rpc_queue(rpc);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel access"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, granted);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_create(WCHAR *name, ULONG attribs, LARGE_INTEGER alloc, ULONG access, ULONG *granted, ULONG *fid)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_CREATE);
- rpc_marshal_long(rpc, attribs);
- rpc_marshal_longlong(rpc, alloc);
- rpc_marshal_long(rpc, access);
-
- rpc_queue_bulk(rpc, (void*)name, (wcslen(name)+1)*sizeof(wchar_t), NULL, 0);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel create"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, granted);
- rpc_unmarshal_long(rpc, fid);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_stat(ULONG fid, ULONG *attribs, LARGE_INTEGER *size, LARGE_INTEGER *creation, LARGE_INTEGER *access, LARGE_INTEGER *change, LARGE_INTEGER *written)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_STAT);
- rpc_marshal_long(rpc, fid);
-
- rpc_queue(rpc);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel stat"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, attribs);
- rpc_unmarshal_longlong(rpc, size);
- rpc_unmarshal_longlong(rpc, creation);
- rpc_unmarshal_longlong(rpc, access);
- rpc_unmarshal_longlong(rpc, change);
- rpc_unmarshal_longlong(rpc, written);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_setinfo(ULONG fid, ULONG attribs, LARGE_INTEGER creation, LARGE_INTEGER access, LARGE_INTEGER change, LARGE_INTEGER written)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_SETINFO);
- rpc_marshal_long(rpc, fid);
- rpc_marshal_long(rpc, attribs);
- rpc_marshal_longlong(rpc, creation);
- rpc_marshal_longlong(rpc, access);
- rpc_marshal_longlong(rpc, change);
- rpc_marshal_longlong(rpc, written);
-
-
- rpc_queue(rpc);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel setinfo"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_trunc(ULONG fid, LARGE_INTEGER size)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_TRUNC);
- rpc_marshal_long(rpc, fid);
- rpc_marshal_longlong(rpc, size);
-
- rpc_queue(rpc);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel trunc"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_read(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *read, char *data)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_READ);
- rpc_marshal_long(rpc, fid);
- rpc_marshal_longlong(rpc, offset);
- rpc_marshal_long(rpc, length);
-
- rpc_queue_bulk(rpc, NULL, 0, data, length);
- if (!rpc_wait(rpc, RPC_TIMEOUT_LONG))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel read"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, read);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_write(ULONG fid, LARGE_INTEGER offset, ULONG length, ULONG *written, char *data)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_WRITE);
- rpc_marshal_long(rpc, fid);
- rpc_marshal_longlong(rpc, offset);
- rpc_marshal_long(rpc, length);
-
- rpc_queue_bulk(rpc, data, length, NULL, 0);
- if (!rpc_wait(rpc, RPC_TIMEOUT_LONG))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel write"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, written);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_readdir(ULONG fid, LARGE_INTEGER cookie_in, WCHAR *filter, ULONG *count, char *data, ULONG *len)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_READDIR);
- rpc_marshal_long(rpc, fid);
- rpc_marshal_longlong(rpc, cookie_in);
- rpc_marshal_wstr(rpc, filter);
- rpc_marshal_long(rpc, *len);
-
- rpc_queue_bulk(rpc, NULL, 0, data, *len);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel readdir"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, count);
- rpc_unmarshal_long(rpc, len);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_close(ULONG fid)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_CLOSE);
- rpc_marshal_long(rpc, fid);
-
- rpc_queue(rpc);
- if (!rpc_wait(rpc, RPC_TIMEOUT_LONG))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel close"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_unlink(WCHAR *name)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_UNLINK);
- rpc_marshal_wstr(rpc, name);
-
- rpc_queue(rpc);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel unlink"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_ioctl_write(ULONG length, char *data, ULONG *key)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_IOCTL_WRITE);
- rpc_marshal_long(rpc, length);
-
- rpc_queue_bulk(rpc, data, length, NULL, 0);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel ioctl write"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, key);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_ioctl_read(ULONG key, ULONG *length, char *data)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_IOCTL_READ);
- rpc_marshal_long(rpc, key);
-
- rpc_queue_bulk(rpc, NULL, 0, data, *length);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel ioctl read"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, length);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_rename(ULONG fid, WCHAR *curr, WCHAR *new_dir, WCHAR *new_name, ULONG *new_fid)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_RENAME);
- rpc_marshal_long(rpc, fid);
- rpc_marshal_wstr(rpc, curr);
- rpc_marshal_wstr(rpc, new_dir);
- rpc_marshal_wstr(rpc, new_name);
-
- rpc_queue(rpc);
- if (!rpc_wait(rpc, RPC_TIMEOUT_SHORT))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel rename"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
- rpc_unmarshal_long(rpc, new_fid);
-
- rpc_destroy(rpc);
- return status;
-}
-
-long
-uc_flush(ULONG fid)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_FLUSH);
- rpc_marshal_long(rpc, fid);
-
- rpc_queue(rpc);
- if (!rpc_wait(rpc, RPC_TIMEOUT_LONG))
- {
- rpc_cancel(rpc);
- rpt0(("cancel", "cancel flush"));
- return IFSL_RPC_TIMEOUT;
- }
-
- rpc_unmarshal_long(rpc, &status);
-
- rpc_destroy(rpc);
- return status;
-}
-#endif
-
-
-/* downcall stubs */
-#ifndef RPC_KERN
-long dc_break_callback(ULONG fid)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_BREAK_CALLBACK);
- rpc_marshal_long(rpc, fid);
- if (!rpc_transact(rpc))
- {
- rpc_destroy(rpc);
- return IFSL_GENERIC_FAILURE;
- }
- rpc_unmarshal_long(rpc, &status);
- rpc_destroy(rpc);
- return status;
-}
-
-long dc_release_hooks(void)
-{
- rpc_t *rpc;
- ULONG status;
-
- rpc = rpc_create(0);
- if (!rpc)
- return IFSL_MEMORY;
-
- rpc_marshal_long(rpc, RPC_RELEASE_HOOKS);
- if (!rpc_transact(rpc))
- {
- rpc_destroy(rpc);
- return IFSL_GENERIC_FAILURE;
- }
- rpc_unmarshal_long(rpc, &status);
- rpc_destroy(rpc);
- return status;
-}
-#endif
-
-
-/* rpc packing function */
-rpc_marshal_long(rpc_t *rpc, ULONG data)
-{
- memcpy(rpc->out_pos, &data, sizeof(ULONG));
- rpc->out_pos += sizeof(ULONG);
- return 0;
-}
-
-rpc_marshal_longlong(rpc_t *rpc, LARGE_INTEGER data)
-{
- memcpy(rpc->out_pos, &data, sizeof(LARGE_INTEGER));
- rpc->out_pos += sizeof(LARGE_INTEGER);
- return 0;
-}
-
-rpc_marshal_wstr(rpc_t *rpc, WCHAR *str)
-{
- long len;
- len = wcslen(str);
- rpc_marshal_long(rpc, len);
- memcpy(rpc->out_pos, str, len*sizeof(WCHAR));
- rpc->out_pos += len*sizeof(WCHAR);
- return 0;
-}
-
-
-rpc_unmarshal_long(rpc_t *rpc, ULONG *data)
-{
- memcpy(data, rpc->in_pos, sizeof(ULONG));
- rpc->in_pos += sizeof(ULONG);
- return 0;
-}
-
-rpc_unmarshal_longlong(rpc_t *rpc, LARGE_INTEGER *data)
-{
- memcpy(data, rpc->in_pos, sizeof(LARGE_INTEGER));
- rpc->in_pos += sizeof(LARGE_INTEGER);
- return 0;
-}
-
-rpc_unmarshal_wstr(rpc_t *rpc, WCHAR *str)//, int len)
-{
- long len;
- rpc_unmarshal_long(rpc, &len);
- memcpy(str, rpc->in_pos, len*sizeof(WCHAR));
- rpc->in_pos += len*sizeof(WCHAR);
- str[len] = L'\0';
- return 0;
-}
-
-
-/* kernel-queue management functions */
-#ifdef RPC_KERN
-rpc_t *rpc_find(int id)
-{
- rpc_t *curr;
-
- curr = rpc_list_head;
- while (curr)
- {
- /* dead rpc structs should not be returned */
- if (curr->key == id && curr->status != 0)
- return curr;
- curr = curr->next;
- }
- return NULL;
-}
-
-rpc_t *rpc_upgrade(rpc_t *rpc, int old_status, int new_status)
-{
- rpc_t *curr;
-
- if (rpc)
- {
- ASSERT(!old_status || rpc_find(rpc->key));
- if (old_status != -1 && rpc->status != old_status)
- return NULL;
- curr = rpc;
- }
- else
- {
- curr = rpc_list_head;
- while (curr)
- {
- if (old_status == -1 || curr->status == old_status)
- break;
- curr = curr->next;
- }
- }
-
- if (!curr)
- return NULL;
-
- ASSERT(old_status == -1 || curr->status == old_status);
- curr->status = new_status;
-
- return curr;
-}
-
-rpc_queue(rpc_t *rpc)
-{
- int ret;
-
- ifs_lock_rpcs();
-
- KeInitializeEvent(&rpc->ev, NotificationEvent, FALSE);
- ret = (rpc_upgrade(rpc, 1, 2) != NULL);
- KeSetEvent(&comExt->outEvent, 0, FALSE);
-
- ifs_unlock_rpcs();
-
- return ret;
-}
-
-rpc_cancel(rpc_t *rpc)
-{
- rpc_destroy(rpc);
-}
-
-rpc_shutdown()
-{
- rpc_t *curr, *next;
-
- ifs_lock_rpcs();
-
- curr = rpc_list_head;
- while (curr)
- {
- next = curr->next;
- ExFreePoolWithTag(curr, 0x1234);
- num_rpcs--;
- curr = next;
- }
- rpc_list_head = NULL;
-
- ifs_unlock_rpcs();
-}
-
-rpc_wait(rpc_t *rpc, BOOLEAN long_op)
-{
- NTSTATUS ret;
- LARGE_INTEGER timeout;
-
- if (long_op)
- timeout.QuadPart = -600000000L; /* 60 seconds 60L*10000000L */
- else
- timeout.QuadPart = -200000000L; /* 20 seconds 20L*10000000L */
-
- do
- ret = KeWaitForSingleObject(&rpc->ev, Executive, KernelMode, FALSE, &timeout);
- while (ret != STATUS_SUCCESS && ret != STATUS_TIMEOUT);
-
- ifs_lock_rpcs();
- if (rpc->status == 2 || /* still queued */
- rpc->status == 5) /* send cancelled by library */
- {
- ifs_unlock_rpcs();
- return 0;
- }
-
- ifs_unlock_rpcs();
- if (ret == STATUS_SUCCESS)
- return 1;
- return 0;
-}
-
-rpc_queue_bulk(rpc_t *rpc, char *out_bulk, ULONG out_len, char *in_bulk, ULONG in_len)
-{
- rpc->bulk_out = out_bulk;
- *rpc->bulk_out_len = out_len;
- rpc->bulk_in = in_bulk;
- rpc->bulk_in_max = in_len;
- return rpc_queue(rpc);
-}
-
-rpc_get_len(rpc_t *rpc)
-{
- if (*rpc->bulk_out_len != 0xFFFFFFFC)
- return rpc->out_pos - rpc->out_buf + *rpc->bulk_out_len + sizeof(ULONG);
- else
- return rpc->out_pos - rpc->out_buf + sizeof(ULONG);
-}
-
-rpc_send(char *out_buf, int out_len, int *out_written)
-{
- rpc_t *rpc;
- int ret, mdl;
- ULONG header_len;
-
- restart:
-
- ifs_lock_rpcs();
- rpc = rpc_upgrade(NULL, 2, 3);
-
- if (!rpc)
- {
- ifs_unlock_rpcs();
- return 0;
- }
-
- if (rpc_get_len(rpc) > out_len)
- {
- ifs_unlock_rpcs();
- rpt0(("cancel", "cancel on send"));
- rpc_upgrade(rpc, -1, 5);
- KeSetEvent(&rpc->ev, IO_NETWORK_INCREMENT, FALSE);
- goto restart;
- }
-
- header_len = rpc->out_pos - rpc->out_buf;
- RtlCopyMemory(out_buf, rpc->out_buf, header_len);
-
- if (*rpc->bulk_out_len && rpc->bulk_out)
- RtlCopyMemory(out_buf + header_len, rpc->bulk_out, *rpc->bulk_out_len);
- *out_written = header_len + *rpc->bulk_out_len;
-
- ifs_unlock_rpcs();
- return (*out_written != 0);
-}
-#endif
-
-
-/* rpc library api */
-#ifdef RPC_KERN
-rpc_recv(char *in_buf, ULONG len)
-{
- ULONG key, header_size;
- char *alloc;
- rpc_t *rpc;
-
- ifs_lock_rpcs();
-
- rpc = rpc_find(*(ULONG*)in_buf);
- if (!rpc) /* rpc was cancelled while waiting */
- {
- ifs_unlock_rpcs();
- return -1;
- }
-
- alloc = rpc->in_buf;
- rpc->in_buf = rpc->in_pos = in_buf;
- rpc_unmarshal_long(rpc, &key);
- ASSERT(key == rpc->key);
- rpc_unmarshal_long(rpc, &rpc->bulk_in_len);
-
- rpc->in_buf = rpc->in_pos = alloc;
- header_size = len - rpc->bulk_in_len;
- ASSERT(header_size < RPC_BUF_SIZE);
-
- RtlCopyMemory(rpc->in_buf, in_buf + 2*sizeof(ULONG), header_size - 2*sizeof(ULONG));
- if (rpc->bulk_in_len && rpc->bulk_in)
- {
- ASSERT(rpc->bulk_in_len <= rpc->bulk_in_max);
- RtlCopyMemory(rpc->bulk_in, in_buf + header_size, rpc->bulk_in_len);
- }
-
- KeSetEvent(&rpc->ev, IO_NETWORK_INCREMENT, FALSE); /* priority boost for waiting thread */
- ifs_unlock_rpcs();
- return 0;
-}
-
-rpc_call(ULONG in_len, char *in_buf, ULONG out_max, char *out_buf, ULONG *out_len)
-{
- long rpc_code;
- ULONG status;
- WCHAR name[1024];
- ULONG key, fid;
- LARGE_INTEGER user_id;
- rpc_t rpc;
-
- rpc.in_buf = rpc.in_pos = in_buf;
- rpc.out_buf = rpc.out_pos = out_buf;
-
- rpc_unmarshal_long(&rpc, &key);
- rpc_unmarshal_long(&rpc, &rpc_code);
-
- switch (rpc_code)
- {
- case RPC_BREAK_CALLBACK:
- rpc_unmarshal_long(&rpc, &fid);
- status = dc_break_callback(fid);
- rpc_marshal_long(&rpc, status);
- break;
- case RPC_RELEASE_HOOKS:
- status = dc_release_hooks();
- break;
- }
- *out_len = rpc.out_pos - rpc.out_buf;
- return 0;
-}
-#endif
-
-#ifndef RPC_KERN
-rpc_parse(rpc_t *rpc)
-{
- long rpc_code;
- ULONG status;
- WCHAR name[1024];
- ULONG key;
- LARGE_INTEGER user_id;
-
- rpc_unmarshal_long(rpc, &key);
- rpc_unmarshal_long(rpc, &rpc->bulk_in_len);
- rpc_unmarshal_longlong(rpc, &user_id);
- rpc_unmarshal_long(rpc, &rpc_code);
-
- ifs_ImpersonateClient(user_id);
-
- rpc_marshal_long(rpc, key);
- rpc->bulk_out_len = (ULONG*)rpc->out_pos;
- rpc_marshal_long(rpc, 0);
-
- switch (rpc_code)
- {
- case RPC_NAMEI:
- {
- ULONG fid, length;
- char *data;
- //rpc_unmarshal_wstr(rpc, name);
- rpc_unmarshal_long(rpc, &length);
- //data = *((char**)rpc->in_pos);
- data = rpc->in_pos;
- status = uc_namei((WCHAR*)data, &fid);
- //status = uc_namei(name, &fid);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, fid);
- }
- break;
- case RPC_CHECK_ACCESS:
- {
- ULONG fid, access, granted;
- rpc_unmarshal_long(rpc, &fid);
- rpc_unmarshal_long(rpc, &access);
- status = uc_check_access(fid, access, &granted);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, granted);
- }
- break;
- case RPC_CREATE:
- {
- LARGE_INTEGER alloc;
- ULONG access, granted, fid, attribs;
- char *data;
-
- rpc_unmarshal_long(rpc, &attribs);
- rpc_unmarshal_longlong(rpc, &alloc);
- rpc_unmarshal_long(rpc, &access);
- //rpc_unmarshal_wstr(rpc, name);
- data = rpc->in_pos;
- status = uc_create((WCHAR*)data, attribs, alloc, access, &granted, &fid);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, granted);
- rpc_marshal_long(rpc, fid);
- }
- break;
- case RPC_STAT:
- {
- ULONG fid, attribs;
- LARGE_INTEGER size, creation, access, change, written;
- rpc_unmarshal_long(rpc, &fid);
- status = uc_stat(fid, &attribs, &size, &creation, &access, &change, &written);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, attribs);
- rpc_marshal_longlong(rpc, size);
- rpc_marshal_longlong(rpc, creation);
- rpc_marshal_longlong(rpc, access);
- rpc_marshal_longlong(rpc, change);
- rpc_marshal_longlong(rpc, written);
- }
- break;
- case RPC_READ:
- {
- ULONG fid, length, read;
- LARGE_INTEGER offset;
- char *data, *save;
- rpc_unmarshal_long(rpc, &fid);
- rpc_unmarshal_longlong(rpc, &offset);
- rpc_unmarshal_long(rpc, &length);
- save = rpc->out_pos;
- rpc_marshal_long(rpc, 0);
- rpc_marshal_long(rpc, 0);
- data = rpc->out_pos;
- rpc->out_pos = save;
- status = uc_read(fid, offset, length, &read, data);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, read);
- rpc->out_pos += read;
- *rpc->bulk_out_len = read;
- }
- break;
- case RPC_WRITE:
- {
- ULONG fid, length, written;
- LARGE_INTEGER offset;
- char *data;
- rpc_unmarshal_long(rpc, &fid);
- rpc_unmarshal_longlong(rpc, &offset);
- rpc_unmarshal_long(rpc, &length);
- data = rpc->in_pos;
- status = uc_write(fid, offset, length, &written, data);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, written);
- }
- break;
- case RPC_TRUNC:
- {
- ULONG fid;
- LARGE_INTEGER size;
- rpc_unmarshal_long(rpc, &fid);
- rpc_unmarshal_longlong(rpc, &size);
- status = uc_trunc(fid, size);
- rpc_marshal_long(rpc, status);
- }
- break;
- case RPC_SETINFO:
- {
- ULONG fid, attribs;
- LARGE_INTEGER creation, access, change, written;
- rpc_unmarshal_long(rpc, &fid);
- rpc_unmarshal_long(rpc, &attribs);
- rpc_unmarshal_longlong(rpc, &creation);
- rpc_unmarshal_longlong(rpc, &access);
- rpc_unmarshal_longlong(rpc, &change);
- rpc_unmarshal_longlong(rpc, &written);
- status = uc_setinfo(fid, attribs, creation, access, change, written);
- rpc_marshal_long(rpc, status);
- }
- break;
- case RPC_READDIR:
- {
- ULONG fid, count, len;
- LARGE_INTEGER cookie_in;
- char *data, *save;
- rpc_unmarshal_long(rpc, &fid);
- rpc_unmarshal_longlong(rpc, &cookie_in);
- rpc_unmarshal_wstr(rpc, name);
- rpc_unmarshal_long(rpc, &len);
- save = rpc->out_pos;
- rpc_marshal_long(rpc, 0);
- rpc_marshal_long(rpc, 0);
- rpc_marshal_long(rpc, 0);
- data = rpc->out_pos;
- rpc->out_pos = save;
- status = uc_readdir(fid, cookie_in, name, &count, data, &len);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, count);
- rpc_marshal_long(rpc, len);
- rpc->out_pos += len;
- *rpc->bulk_out_len = len;
- }
- break;
- case RPC_CLOSE:
- {
- ULONG fid;
- rpc_unmarshal_long(rpc, &fid);
- status = uc_close(fid);
- rpc_marshal_long(rpc, status);
- }
- break;
- case RPC_UNLINK:
- {
- rpc_unmarshal_wstr(rpc, name);
- status = uc_unlink(name);
- rpc_marshal_long(rpc, status);
- }
- break;
- case RPC_IOCTL_WRITE:
- {
- ULONG length, key;
- rpc_unmarshal_long(rpc, &length);
- status = uc_ioctl_write(length, rpc->in_pos, &key);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, key);
- }
- break;
- case RPC_IOCTL_READ:
- {
- ULONG key, length;
- char *save, *data;
- rpc_unmarshal_long(rpc, &key);
- save = rpc->out_pos;
- rpc_marshal_long(rpc, 0);
- rpc_marshal_long(rpc, 0);
- data = rpc->out_pos;
- rpc->out_pos = save;
- status = uc_ioctl_read(key, &length, data);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, length);
- rpc->out_pos += length;
- *rpc->bulk_out_len = length;
- }
- break;
- case RPC_RENAME:
- {
- ULONG fid, new_fid;
- WCHAR curr[1024], new_dir[1024], new_name[1024];
- rpc_unmarshal_long(rpc, &fid);
- rpc_unmarshal_wstr(rpc, curr);
- rpc_unmarshal_wstr(rpc, new_dir);
- rpc_unmarshal_wstr(rpc, new_name);
- status = uc_rename(fid, curr, new_dir, new_name, &new_fid);
- rpc_marshal_long(rpc, status);
- rpc_marshal_long(rpc, new_fid);
- }
- break;
- case RPC_FLUSH:
- {
- ULONG fid;
- rpc_unmarshal_long(rpc, &fid);
- status = uc_flush(fid);
- rpc_marshal_long(rpc, status);
- }
- break;
- }
-}
-#endif