afsifs-20050615
[openafs.git] / src / WINNT / afsrdr / afsrdr.c
1 /* copyright (c) 2005
2  * the regents of the university of michigan
3  * all rights reserved
4  * 
5  * permission is granted to use, copy, create derivative works and
6  * redistribute this software and such derivative works for any purpose,
7  * so long as the name of the university of michigan is not used in
8  * any advertising or publicity pertaining to the use or distribution
9  * of this software without specific, written prior authorization.  if
10  * the above copyright notice or any other identification of the
11  * university of michigan is included in any copy of any portion of
12  * this software, then the disclaimer below must also be included.
13  * 
14  * this software is provided as is, without representation from the
15  * university of michigan as to its fitness for any purpose, and without
16  * warranty by the university of michigan of any kind, either express 
17  * or implied, including without limitation the implied warranties of
18  * merchantability and fitness for a particular purpose.  the regents
19  * of the university of michigan shall not be liable for any damages,   
20  * including special, indirect, incidental, or consequential damages, 
21  * with respect to any claim arising out or in connection with the use
22  * of the software, even if it has been or is hereafter advised of the
23  * possibility of such damages.
24  */
25
26 /* versioning history
27  * 
28  * 03-jun 2005 (eric williams) entered into versioning
29  */
30
31 /* developer: eric williams,
32  *  center for information technology integration,
33  *  university of michigan, ann arbor
34  *
35  * comments: nativeafs@citi.umich.edu
36  */
37
38 #define IRPMJFUNCDESC           /* pull in text strings of the names of irp codes */
39 #define RPC_SRV                         /* which half of the rpc library to use */
40
41 #include <ntifs.h>
42 #include <ntdddisk.h>
43 #include <strsafe.h>
44 #include <ksdebug.h>
45 #include "ifs_rpc.h"
46 #include "afsrdr.h"
47 #include "kif.h"
48
49
50 /*** notes ***/
51 /* flag pooltag Io(sp)(sp) to check queryinfo requests for buffer overrun */
52
53 NTKERNELAPI
54 NTSTATUS
55 IoAllocateDriverObjectExtension(
56     IN PDRIVER_OBJECT DriverObject,
57     IN PVOID ClientIdentificationAddress,
58     IN ULONG DriverObjectExtensionSize,
59     OUT PVOID *DriverObjectExtension
60     );
61
62 /*** local structs ***/
63 /* represents a specific file */
64 struct afs_fcb
65         {
66         FSRTL_COMMON_FCB_HEADER;                /* needed to interface with cache manager, etc. */
67         SECTION_OBJECT_POINTERS sectionPtrs;
68         ERESOURCE _resource;                    /* pointed to by fcb_header->Resource */
69         ERESOURCE _pagingIoResource;
70         unsigned long fid;                              /* a courtesy from the userland daemon (a good hash function) */
71         UCHAR delPending;                               /* 3 types: FIX */
72         struct afs_ccb *ccb_list;               /* list of open instances */
73         SHARE_ACCESS share_access;              /* common access control */
74         };
75 typedef struct afs_fcb afs_fcb_t;
76
77 /* represents an open instance of a file */
78 struct afs_ccb
79         {
80         struct afs_ccb *next;           /* these are chained as siblings, non-circularly */
81         ULONG access;                           /* how this instance is opened */
82         wchar_t *name;                          /* ptr to name buffer */
83         UNICODE_STRING str;                     /* full name struct, for notification fns */
84         FILE_OBJECT *fo;                        /* can get parent fcb from this */
85         LARGE_INTEGER cookie;           /* on enum ops, where we are */
86         wchar_t *filter;                        /* on enum ops, what we are filtering on */
87         PACCESS_TOKEN token;            /* security data of opening app */
88         ULONG attribs;                          /* is dir, etc. */
89         };
90 typedef struct afs_ccb afs_ccb_t;
91
92
93 /*** globals ***/
94 /* use wisely -- should be set by each thread in an arbitrary context */
95 /* here mostly as a development convenience */
96 DEVICE_OBJECT *RdrDevice, *ComDevice;
97 struct AfsRdrExtension *rdrExt;
98 struct ComExtension *comExt;
99
100
101 /*** error and return handling ***/
102 /* current code is stable without, but these should wrap all operations */
103 /*#define TRY                                   try{
104 #define EXCEPT(x, y)            } except(EXCEPTION_EXECUTE_HANDLER) \
105                                                         { \
106                                                         KdBreakPoint(); \
107                                                         rpt4(("exception", "occurred")); \
108                                                         Irp->IoStatus.Status = x; \
109                                                         Irp->IoStatus.Information = y; \
110                                                         }*/
111 #define TRY
112 #define EXCEPT(x, y)
113
114 #define STATUS(st, in)                  Irp->IoStatus.Information = (in), Irp->IoStatus.Status = (st)
115 #define SYNC_FAIL(st)  \
116                 {       \
117                 STATUS(st, 0); \
118                 COMPLETE_NO_BOOST; \
119                 return st; \
120                 }
121 #define SYNC_FAIL2(st, in)  \
122                 {       \
123                 STATUS(st, in); \
124                 COMPLETE_NO_BOOST; \
125                 return st; \
126                 }
127 #define SYNC_RET(st)  \
128                 {       \
129                 STATUS(st, 0); \
130                 COMPLETE; \
131                 return st; \
132                 }
133 #define SYNC_RET2(st, in)  \
134                 {       \
135                 STATUS(st, in); \
136                 COMPLETE; \
137                 return st; \
138                 }
139 #define SYNC_FAIL_RPC_TIMEOUT   SYNC_FAIL(STATUS_NETWORK_BUSY)
140
141 #define LOCK_FCB_LIST                   FsRtlEnterFileSystem(); ExAcquireFastMutex(&rdrExt->fcbLock);
142 #define UNLOCK_FCB_LIST                 ExReleaseFastMutex(&rdrExt->fcbLock); FsRtlExitFileSystem();
143
144 #define LOCK_FCB                                ExAcquireResourceExclusiveLite(fcb->Resource, TRUE)
145 #define SLOCK_FCB                               ExAcquireResourceSharedLite(fcb->Resource, TRUE)
146 #define UNLOCK_FCB                              if (fcb) ExReleaseResourceLite(fcb->Resource)
147
148 #define LOCK_PAGING_FCB                 ExAcquireResourceExclusiveLite(fcb->PagingIoResource, TRUE)
149 #define SLOCK_PAGING_FCB                ExAcquireResourceSharedLite(fcb->PagingIoResource, TRUE)
150 #define UNLOCK_PAGING_FCB               if (fcb) ExReleaseResourceLite(fcb->PagingIoResource)
151
152 /*** constants ***/
153 #define AFS_RDR_TAG                             (0x73666440)//@dfs//0x482ac230//0x3029a4f2
154 #define MAX_PATH                                700
155 #define AFS_FS_NAME                             L"Andrew File System"
156
157 #define COMM_IOCTL                              (void*)0x01
158 #define COMM_DOWNCALL                   (void*)0x02
159 #define COMM_UPCALLHOOK                 (void*)0x03
160
161 /*#define ACC_READ                              (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_LIST_DIRECTORY
162 #define ACC_WRITE                               (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA)*
163
164
165 /* dates from afs are time_t style -- seconds since 1970 */                     /* 11644505691.6384 */
166 #define AfsTimeToWindowsTime(x)         (((x)+11644505692L)*10000000L)  /*(1970L-1601L)*365.242199*24L*3600L)*/
167 #define WindowsTimeToAfsTime(x)         ((x)/10000000L-11644505692L)    /*(1970L-1601L)*365.242199*24L*3600L)*/
168 #define IsDeviceFile(fo)                        (!fo->FsContext)
169
170
171 /*** auxiliary functions ***/
172 #define COMPLETE_NO_BOOST               IoCompleteRequest(Irp, IO_NO_INCREMENT)
173 #define COMPLETE                                IoCompleteRequest(Irp, IO_NETWORK_INCREMENT)
174
175 afs_fcb_t *FindFcb(FILE_OBJECT *fo)
176         {
177         if (fo)
178                 return fo->FsContext;
179         return NULL;
180         }
181
182 void *AfsFindBuffer(IRP *Irp)
183         {
184         void *outPtr;
185         if (Irp->MdlAddress)
186                 {
187                 outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
188                 if (outPtr)
189                         return outPtr;
190                 }
191         outPtr = Irp->AssociatedIrp.SystemBuffer;
192         return outPtr;
193         }
194
195 /* we do Resource locking because we don't want to figure out when to pull MainResource */
196 BOOLEAN lazyWriteLock(PVOID context, BOOLEAN wait)
197 {
198 afs_fcb_t *fcb = context;
199 ASSERT(fcb);
200 return ExAcquireResourceExclusiveLite(fcb->Resource, wait);
201 }
202         
203 void lazyWriteUnlock(PVOID context)
204 {
205 afs_fcb_t *fcb = context;
206 ASSERT(fcb);
207 ExReleaseResourceLite(fcb->Resource);
208 }
209
210 BOOLEAN readAheadLock(PVOID context, BOOLEAN wait)
211 {
212 afs_fcb_t *fcb = context;
213 ASSERT(fcb);
214 return ExAcquireResourceSharedLite(fcb->Resource, wait);
215 }
216
217 void readAheadUnlock(PVOID context)
218 {
219 afs_fcb_t *fcb = context;
220 ASSERT(fcb);
221 ExReleaseResourceLite(fcb->Resource);
222 }
223
224 afs_fcb_t *find_fcb(ULONG fid)
225 {
226 afs_fcb_t compare, *compare_ptr, **fcbp;
227
228 compare.fid = fid;
229 compare_ptr = &compare;
230 fcbp = RtlLookupElementGenericTable(&rdrExt->fcbTable, (void*)&compare_ptr);
231
232 if (fcbp)
233         return (*fcbp);
234 return NULL;
235 }
236
237
238 /**********************************************************
239  * AfsRdrCreate
240  * - handle open and create requests
241  * - on success
242  *  - FsContext of file object points to FCB
243  *  - FsContext2 of file object is usermode handle of file instance
244  * - beginning failure codes and conditions came from ifstest
245  **********************************************************/
246 NTSTATUS AfsRdrCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *_fcb)
247 {
248 afs_fcb_t *pfcb, *fcb, **fcbp;
249 afs_ccb_t *ccb, *pccb;
250 ULONG len, x, y;
251 wchar_t *str, *ptr;
252 ULONG fid, access, granted, disp;
253 LARGE_INTEGER size, creation, accesst, change, written, zero;
254 ULONG attribs;
255 ULONG share;
256 CC_FILE_SIZES sizes;
257 NTSTATUS status;
258 char created;
259 PACCESS_TOKEN acc_token;
260
261 /* set rpc security context for current thread */
262 acc_token = SeQuerySubjectContextToken(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
263 ASSERT(acc_token);
264 rpc_set_context(acc_token);
265
266 /* attempt to open afs volume directly */
267 if (IrpSp->FileObject->FileName.Length == 0)
268         SYNC_FAIL(STATUS_SHARING_VIOLATION);
269
270 if (IrpSp->FileObject->FileName.Length > MAX_PATH*sizeof(wchar_t))
271         SYNC_FAIL(STATUS_OBJECT_NAME_INVALID);
272
273 if (IrpSp->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_TEMPORARY &&
274         IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE)
275         SYNC_FAIL(STATUS_INVALID_PARAMETER);
276
277 /* relative opens cannot start with \ */
278 if (IrpSp->FileObject->RelatedFileObject &&
279         IrpSp->FileObject->FileName.Length &&
280         IrpSp->FileObject->FileName.Buffer[0] == L'\\')
281         SYNC_FAIL(STATUS_INVALID_PARAMETER);/*STATUS_OBJECT_PATH_SYNTAX_BAD);*/
282
283 /* a create request can be relative to a prior file.  build filename here */
284 pccb = NULL;
285 if (IrpSp->FileObject->RelatedFileObject)
286         pccb = IrpSp->FileObject->RelatedFileObject->FsContext2;
287 len = IrpSp->FileObject->FileName.Length + (pccb?wcslen(pccb->name):0)*sizeof(wchar_t) + 6;
288 str = ExAllocatePoolWithTag(NonPagedPool, len, AFS_RDR_TAG);
289 RtlZeroMemory(str, len);
290 if (pccb)
291         {
292         StringCbCatN(str, len, IrpSp->FileObject->RelatedFileObject->FileName.Buffer, IrpSp->FileObject->RelatedFileObject->FileName.Length);
293         StringCbCat(str, len, L"\\");
294         }
295 StringCbCatN(str, len, IrpSp->FileObject->FileName.Buffer, IrpSp->FileObject->FileName.Length);
296
297 /* request to open heirarchical parent of specified path */
298 /* remove last path component */
299 if (IrpSp->Flags & SL_OPEN_TARGET_DIRECTORY)
300         {
301         y = x = wcslen(str);
302         if (x)
303                 x--, y--;
304         for (x; x >= 0; x--)
305                 {
306                 if (str[x] == L'\\')
307                         {
308                         if (y == x && x != 0)
309                                 str[x] = L'\0';
310                         else if (x != 0)
311                                 {
312                                 str[x] = L'\0';
313                                 break;
314                                 }
315                         else
316                                 {
317                                 str[x+1] = L'\0';
318                                 break;
319                                 }
320                         }
321                 }
322         }
323
324 /* first two characters are \%01d . %d is number of path components immediately
325    following that should not be returned in file name queries.
326    EX: \3\mount\path\start\fname.ext is mapped to <driveletter>:\fname.ext */
327 if (wcslen(str) <= 2)
328         {
329         ExFreePoolWithTag(str, AFS_RDR_TAG);
330         SYNC_FAIL(STATUS_OBJECT_NAME_INVALID);
331         }
332
333 fid = 0;
334 disp = (unsigned char)((IrpSp->Parameters.Create.Options >> 24) & 0xff);
335 access = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
336 share = IrpSp->Parameters.Create.ShareAccess;
337 size.QuadPart = 0;
338 created = 0;
339
340 /* check for file existance.  we jump to creating it if needed */ 
341 if (disp == FILE_OPEN || disp == FILE_OPEN_IF || disp == FILE_OVERWRITE ||
342         disp == FILE_OVERWRITE_IF || disp == FILE_SUPERSEDE)
343         {
344         /* chop our internal mount flagging from the beginning */
345         status = uc_namei(str+2, &fid);
346         if (status == IFSL_DOES_NOT_EXIST &&
347                 (disp == FILE_OPEN_IF ||
348                  disp == FILE_OVERWRITE_IF ||
349                  disp == FILE_SUPERSEDE))
350                 goto create;
351
352         if (status != IFSL_SUCCESS)
353                 {
354                 ExFreePoolWithTag(str, AFS_RDR_TAG);
355                 switch (status)
356                         {
357                         case IFSL_RPC_TIMEOUT:                  SYNC_FAIL_RPC_TIMEOUT;
358                         case IFSL_NO_ACCESS:                    SYNC_FAIL(STATUS_ACCESS_DENIED);
359                         case IFSL_BAD_INPUT:                    SYNC_FAIL(STATUS_INVALID_PARAMETER);
360                         case IFSL_DOES_NOT_EXIST:               SYNC_FAIL2(STATUS_OBJECT_NAME_NOT_FOUND, FILE_DOES_NOT_EXIST);
361                         case IFSL_PATH_DOES_NOT_EXIST:  SYNC_FAIL2(STATUS_OBJECT_PATH_NOT_FOUND, FILE_DOES_NOT_EXIST);
362                         default:                                                SYNC_FAIL(STATUS_UNSUCCESSFUL);
363                         }
364                 }
365
366         /* make upcall to get ACL in afs.  we specify our requested level to 
367            keep it from hitting the network on a public volume. */
368         status = uc_check_access(fid, access, &granted);
369         if (status != IFSL_SUCCESS)
370                 {
371                 ExFreePoolWithTag(str, AFS_RDR_TAG);
372                 switch (status)
373                         {
374                         case IFSL_RPC_TIMEOUT:          SYNC_FAIL_RPC_TIMEOUT;
375                         case IFSL_BAD_INPUT:            SYNC_FAIL(STATUS_INVALID_PARAMETER);
376                         default:                                        SYNC_FAIL(STATUS_UNSUCCESSFUL);
377                         }
378                 }
379
380         /* make sure daemon approved access */
381         if ((access & granted) != access)
382                 {
383                 ExFreePoolWithTag(str, AFS_RDR_TAG);
384                 SYNC_FAIL(STATUS_ACCESS_DENIED);
385                 }
386
387         /* we depend on this information for caching, etc. */
388         status = uc_stat(fid, &attribs, &size, &creation, &accesst, &change, &written);
389         if (status != IFSL_SUCCESS)
390                 {
391                 ExFreePoolWithTag(str, AFS_RDR_TAG);
392                 switch (status)
393                         {
394                         case IFSL_RPC_TIMEOUT:          SYNC_FAIL_RPC_TIMEOUT;
395                         case IFSL_BAD_INPUT:            SYNC_FAIL(STATUS_INVALID_PARAMETER);
396                         default:                                        SYNC_FAIL(STATUS_UNSUCCESSFUL);
397                         }
398                 }
399
400         /* afsd does not maintain instance-specific data, so we adjust here */
401         if (granted & FILE_READ_DATA && !(granted & FILE_WRITE_DATA))
402                 attribs |= FILE_ATTRIBUTE_READONLY;
403
404         if (IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE &&
405                 !(attribs & FILE_ATTRIBUTE_DIRECTORY))
406                 {
407                 ExFreePoolWithTag(str, AFS_RDR_TAG);
408                 SYNC_FAIL(STATUS_NOT_A_DIRECTORY);
409                 }
410         if (IrpSp->Parameters.Create.Options & FILE_NON_DIRECTORY_FILE &&
411                 attribs & FILE_ATTRIBUTE_DIRECTORY)
412                 {
413                 ExFreePoolWithTag(str, AFS_RDR_TAG);
414                 SYNC_FAIL(STATUS_FILE_IS_A_DIRECTORY);
415                 }
416
417         /* check for previous open instance(s) of file.  it will be in the fcb chain.
418            when we have this locked, we cannot make upcalls -- running at APC_LEVEL.
419            lock here (not later) to prevent possible truncation races. */
420         LOCK_FCB_LIST;
421         fcb = find_fcb(fid);
422         if (fcb)
423                 {
424                 LOCK_PAGING_FCB;
425                 LOCK_FCB;
426                 }
427
428         /* if we found it, check to make sure open disposition and sharing
429            are not in conflict with previous opens.  then, make new file
430            instance entry and, if necessary, file entry. */
431         if (fcb)
432                 {
433                 /* file contents cannot be cached for a successful delete */
434                 if (access & FILE_WRITE_DATA)
435                         if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForWrite))
436                                 {
437                                 UNLOCK_FCB;
438                                 UNLOCK_PAGING_FCB;
439                                 UNLOCK_FCB_LIST;
440                                 ExFreePoolWithTag(str, AFS_RDR_TAG);
441                                 SYNC_FAIL(STATUS_SHARING_VIOLATION);
442                                 }
443                 if (access & DELETE)
444                         if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForWrite))//Delete))
445                                 {
446                                 UNLOCK_FCB;
447                                 UNLOCK_PAGING_FCB;
448                                 UNLOCK_FCB_LIST;
449                                 ExFreePoolWithTag(str, AFS_RDR_TAG);
450                                 SYNC_FAIL(STATUS_SHARING_VIOLATION);
451                                 }
452
453                 /* check common sharing flags, but do not change */
454                 if (IoCheckShareAccess(access, share, IrpSp->FileObject, &fcb->share_access, FALSE) != STATUS_SUCCESS)
455                         {
456                         rpt0(("create", "sharing violation for %ws", str));
457                         UNLOCK_FCB;
458                         UNLOCK_PAGING_FCB;
459                         UNLOCK_FCB_LIST;
460                         ExFreePoolWithTag(str, AFS_RDR_TAG);
461                         SYNC_FAIL(STATUS_SHARING_VIOLATION);
462                         }
463                         
464                 zero.QuadPart = 0;
465                 if (access & DELETE)
466                         if (!MmCanFileBeTruncated(&(fcb->sectionPtrs), &zero))
467                                 {
468                                 UNLOCK_FCB;
469                                 UNLOCK_PAGING_FCB;
470                                 UNLOCK_FCB_LIST;
471                                 ExFreePoolWithTag(str, AFS_RDR_TAG);
472                                 SYNC_FAIL(STATUS_SHARING_VIOLATION);
473                                 }
474                 }
475
476         /* do overwrite/supersede tasks */
477         if (disp == FILE_OVERWRITE ||
478                 disp == FILE_OVERWRITE_IF ||
479                 disp == FILE_SUPERSEDE)
480                 {
481                 zero.QuadPart = 0;
482                 if (fcb && !MmCanFileBeTruncated(&(fcb->sectionPtrs), &zero))
483                         {
484                         UNLOCK_FCB;
485                         UNLOCK_PAGING_FCB;
486                         UNLOCK_FCB_LIST;
487                         ExFreePoolWithTag(str, AFS_RDR_TAG);
488                         SYNC_FAIL(STATUS_SHARING_VIOLATION);
489                         }
490                 if (size.QuadPart != 0)
491                         {
492                         size.QuadPart = 0;
493                         status = uc_trunc(fid, size);
494                         if (status != IFSL_SUCCESS)
495                                 {
496                                 UNLOCK_FCB;
497                                 UNLOCK_PAGING_FCB;
498                                 UNLOCK_FCB_LIST;
499                                 ExFreePoolWithTag(str, AFS_RDR_TAG);
500                                 SYNC_FAIL(STATUS_ACCESS_DENIED);
501                                 }
502                         if (fcb)
503                                 {
504                                 fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
505                                 CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
506                                 }
507                         }
508                 if (Irp->Overlay.AllocationSize.QuadPart)
509                         {
510                         status = uc_trunc(fid, Irp->Overlay.AllocationSize);
511                         size = Irp->Overlay.AllocationSize;
512                         if (status != IFSL_SUCCESS)
513                                 {
514                                 UNLOCK_FCB;
515                                 UNLOCK_PAGING_FCB;
516                                 UNLOCK_FCB_LIST;
517                                 ExFreePoolWithTag(str, AFS_RDR_TAG);
518                                 SYNC_FAIL(STATUS_DISK_FULL);
519                                 }
520                         if (fcb)
521                                 {
522                                 fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
523                                 CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
524                                 }
525                         }
526                 }
527
528         if (fcb)
529                 {
530                 /* make actual change in common sharing flags */
531                 IoUpdateShareAccess(IrpSp->FileObject, &fcb->share_access);
532                 goto makeccb;
533                 }
534
535         goto makefcb;
536         }
537
538
539 /* if disposition was to create the file, or its non-existance necessitates this */
540 create:
541 if (disp == FILE_CREATE ||
542         status == IFSL_DOES_NOT_EXIST && (disp == FILE_OPEN_IF || disp == FILE_OVERWRITE_IF || disp == FILE_SUPERSEDE))
543         {
544         attribs = IrpSp->Parameters.Create.FileAttributes;
545         if (IrpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE)
546                 attribs |= FILE_ATTRIBUTE_DIRECTORY;
547         if (IrpSp->Parameters.Create.Options & FILE_NON_DIRECTORY_FILE)
548                 attribs &= ~FILE_ATTRIBUTE_DIRECTORY;
549         status = uc_create(str+2, attribs, Irp->Overlay.AllocationSize, access, &granted, &fid);
550         if (status != IFSL_SUCCESS)
551                 {
552                 ExFreePoolWithTag(str, AFS_RDR_TAG);
553                 switch (status)
554                         {
555                         case IFSL_RPC_TIMEOUT:                  SYNC_FAIL_RPC_TIMEOUT;
556                         case IFSL_NO_ACCESS:                    SYNC_FAIL(STATUS_ACCESS_DENIED);
557                         case IFSL_BAD_INPUT:                    SYNC_FAIL(STATUS_INVALID_PARAMETER);
558                         case IFSL_PATH_DOES_NOT_EXIST:  SYNC_FAIL2(STATUS_OBJECT_PATH_NOT_FOUND, FILE_DOES_NOT_EXIST);
559                         case IFSL_OPEN_EXISTS:                  SYNC_FAIL2(STATUS_OBJECT_NAME_COLLISION, FILE_EXISTS);
560                         case IFSL_OVERQUOTA:                    SYNC_FAIL(STATUS_DISK_FULL);//STATUS_QUOTA_EXCEEDED);
561                         default:                                                SYNC_FAIL(STATUS_UNSUCCESSFUL);
562                         }
563                 }
564
565         /* lock list like above.  check again just to make sure it isn't in the list.
566            if it is, we should process like above.  depending on how we follow symlinks
567            (same fid for multiple files), we cannot expect serialized create requests. */
568         LOCK_FCB_LIST;
569         fcb = find_fcb(fid);
570         if (fcb)
571                 _asm int 3;
572
573         if (size.QuadPart != 0)
574                 {
575                 size.QuadPart = 0;
576                 uc_trunc(fid, size);
577                 if (status != IFSL_SUCCESS)
578                         {
579                         UNLOCK_FCB_LIST;
580                         ExFreePoolWithTag(str, AFS_RDR_TAG);
581                         SYNC_FAIL(STATUS_DISK_FULL);
582                         }
583                 }
584         if (Irp->Overlay.AllocationSize.QuadPart)
585                 {
586                 uc_trunc(fid, Irp->Overlay.AllocationSize);
587                 size = Irp->Overlay.AllocationSize;
588                 if (status != IFSL_SUCCESS)
589                         {
590                         UNLOCK_FCB_LIST;
591                         ExFreePoolWithTag(str, AFS_RDR_TAG);
592                         SYNC_FAIL(STATUS_ACCESS_DENIED);
593                         }
594                 }
595
596         created = 1;
597         goto makefcb;
598         }
599
600 /* OS passed unexpected disposition */
601 ExFreePoolWithTag(str, AFS_RDR_TAG);
602 SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
603 /*SYNC_FAIL2(STATUS_OBJECT_NAME_NOT_FOUND, FILE_DOES_NOT_EXIST);*/
604
605
606 /* allocate nonpaged struct to track this file and all open instances */
607 makefcb:
608         fcb = ExAllocateFromNPagedLookasideList(&rdrExt->fcbMemList);
609         ASSERT(fcb);
610         RtlZeroMemory(fcb, sizeof(afs_fcb_t));
611
612         fcb->fid = fid;
613         /*fcb->refs = 0;*/
614         fcb->ccb_list = NULL;
615         fcb->IsFastIoPossible = FastIoIsNotPossible;
616
617         ExInitializeResourceLite(&fcb->_resource);
618         ExInitializeResourceLite(&fcb->_pagingIoResource);
619         fcb->Resource = &fcb->_resource;
620         fcb->PagingIoResource = &fcb->_pagingIoResource;
621         LOCK_PAGING_FCB;
622         LOCK_FCB;
623
624         fcb->sectionPtrs.DataSectionObject = NULL;
625         fcb->sectionPtrs.SharedCacheMap = NULL;
626         fcb->sectionPtrs.ImageSectionObject = NULL;
627         fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = size;
628
629         IoSetShareAccess(access, share, IrpSp->FileObject, &fcb->share_access);
630
631         /* we store a pointer to the fcb.  the table would want to store a copy otherwise. */
632         fcbp = &fcb;
633         RtlInsertElementGenericTable(&rdrExt->fcbTable, fcbp, sizeof(fcbp), NULL);
634
635         sizes.AllocationSize = sizes.FileSize = sizes.ValidDataLength = size;
636         rpt1(("create", "created size %d name %ws", size.LowPart, str));
637
638 /* allocate nonpaged struct tracking information specific to (file, open instance) pair,
639    and link from parent.  is put at head of parent's list. */
640 makeccb:
641         /* there are two different types of pending deletes.  we return different
642            errors in places depending on a) delete specified on call to open,
643            or b) file specifically deleted */
644         /* need to check for DELETE perms too? */
645         if (IrpSp->Parameters.Create.Options & FILE_DELETE_ON_CLOSE)
646                 fcb->delPending = 2;
647
648         ccb = ExAllocateFromNPagedLookasideList(&rdrExt->ccbMemList);
649         ccb->name = str;
650         ccb->access = granted;
651         ccb->fo = IrpSp->FileObject;
652         ccb->cookie.QuadPart = 0;
653         ccb->filter = NULL;
654         ccb->attribs = attribs;
655
656         /* save security context information.  we never change this ccb attribute. */
657         ObReferenceObjectByPointer(acc_token, TOKEN_QUERY, NULL, KernelMode);
658         ccb->token = acc_token; 
659         /*ObOpenObjectByPointer(acc_token, OBJ_KERNEL_HANDLE, NULL, TOKEN_QUERY, NULL, KernelMode, &ccb->token);*/
660
661         /*fcb->refs++;*/
662         if (!fcb->ccb_list)
663                 {
664                 ccb->next = NULL;
665                 fcb->ccb_list = ccb;
666                 }
667         else
668                 {
669                 ccb->next = fcb->ccb_list;
670                 fcb->ccb_list = ccb;
671                 }
672         UNLOCK_FCB;
673         UNLOCK_PAGING_FCB;
674         UNLOCK_FCB_LIST;
675
676         /* how we pack (as it is expected): a) fscontext same for all open instances of a file,
677            b) fscontext2 unique among each instance, c) private cache map pointer set by cache
678            manager upon caching, d) so pointers are per-file, as in (a). */
679         IrpSp->FileObject->FsContext = fcb;
680         IrpSp->FileObject->FsContext2 = ccb;
681         IrpSp->FileObject->PrivateCacheMap = NULL;
682         IrpSp->FileObject->SectionObjectPointer = &(fcb->sectionPtrs);
683
684         /* explicitly start caching on a data file.  caching will still happen upon
685            paging i/o even if commented out below.  the other option is to cache upon
686            the first read/write operation.  that code is also in place. */
687         if (!(attribs & FILE_ATTRIBUTE_DIRECTORY))
688                 {
689                 /*CcInitializeCacheMap(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize, FALSE, &rdrExt->callbacks, IrpSp->FileObject->FsContext);//(PVOID)din->Context1);*/
690                 /*CcSetAdditionalCacheAttributes(IrpSp->FileObject, TRUE, TRUE);*/
691                 }
692
693         /* customize returns; semantics largely derived from output of ifstest.exe */
694         switch (disp)
695                 {
696                 case FILE_OPEN:
697                         SYNC_FAIL2(STATUS_SUCCESS, FILE_OPENED)
698
699                 case FILE_OPEN_IF:
700                         if (created)
701                                 SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED)
702                         else
703                                 SYNC_FAIL2(STATUS_SUCCESS, FILE_OPENED)
704
705                 case FILE_OVERWRITE:
706                         SYNC_FAIL2(STATUS_SUCCESS, FILE_OVERWRITTEN)    
707
708                 case FILE_OVERWRITE_IF:
709                         if (created)
710                                 SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED)
711                         else
712                                 SYNC_FAIL2(STATUS_SUCCESS, FILE_OVERWRITTEN)
713
714                 case FILE_SUPERSEDE:
715                         if (created)
716                                 SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED)
717                         else
718                                 SYNC_FAIL2(STATUS_SUCCESS, FILE_SUPERSEDED)
719
720                 case FILE_CREATE:
721                         SYNC_FAIL2(STATUS_SUCCESS, FILE_CREATED)
722                 }
723 _asm int 3;
724 return 0;
725 }
726
727 /* experimental; does not work.  need to handle filesizes
728    and cache invalidation in more places. */
729 #define EXPLICIT_CACHING
730
731 /**********************************************************
732  * AfsRdrRead
733  * - handle reads
734  **********************************************************/
735 NTSTATUS AfsRdrRead(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
736 {
737 struct ReadKOut *p;
738 void *ptr;
739 LARGE_INTEGER offset, curroff;
740 ULONG length, read;
741 void *outPtr;
742 NTSTATUS status;
743 afs_ccb_t *ccb;
744 MDL m;
745 ULONG currpos, ttlread, toread;
746
747 ccb = IrpSp->FileObject->FsContext2;
748 if (IsDeviceFile(IrpSp->FileObject) || (ccb->attribs & FILE_ATTRIBUTE_DIRECTORY))
749         SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
750
751 /* the second line disables read ahead and write behind.  since our data is
752    already cached in userland, and there are read-ahead parameters there,
753    we do not use this service. */
754 #ifdef EXPLICIT_CACHING
755 if (!IrpSp->FileObject->PrivateCacheMap)
756         {
757         CcInitializeCacheMap(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize, FALSE, &rdrExt->callbacks, IrpSp->FileObject->FsContext);//(PVOID)din->Context1);
758         CcSetAdditionalCacheAttributes(IrpSp->FileObject, FALSE, TRUE);
759         //CcSetReadAheadGranularity
760         }
761 #endif
762
763 if (!(ccb->access & FILE_READ_DATA) && !(Irp->Flags & IRP_PAGING_IO))
764         SYNC_FAIL(STATUS_ACCESS_DENIED);
765
766 if (!IrpSp->Parameters.Read.Length)
767         SYNC_FAIL(STATUS_SUCCESS);
768
769 offset = IrpSp->Parameters.Read.ByteOffset;
770 length = IrpSp->Parameters.Read.Length;
771
772 /* FIX: lock here, before finding end-of-file */
773
774 /* fast out for reads starting beyond eof */
775 if (offset.QuadPart > fcb->ValidDataLength.QuadPart)
776         SYNC_FAIL(STATUS_END_OF_FILE);
777 /* pre-truncate reads */
778 if (offset.QuadPart + length > fcb->ValidDataLength.QuadPart)
779         length = (ULONG)(fcb->ValidDataLength.QuadPart - offset.QuadPart);
780
781 outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
782 if (!outPtr)
783         SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
784
785 #ifdef EXPLICIT_CACHING
786 if (!(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO)))
787         {
788         FsRtlEnterFileSystem();
789         SLOCK_PAGING_FCB;
790         ttlread = 0;
791         try
792                 {
793                 if (!CcCopyRead(IrpSp->FileObject, &offset, length, TRUE, outPtr, &Irp->IoStatus))
794                         {
795                         UNLOCK_PAGING_FCB;
796                         FsRtlExitFileSystem();
797                         SYNC_FAIL(STATUS_UNSUCCESSFUL);
798                         }
799 //              KdPrint(("read  %x at %x cache done %x\n", length, (ULONG)offset.QuadPart, Irp->IoStatus.Information));
800                 ttlread = Irp->IoStatus.Information;
801                 }
802         except (EXCEPTION_EXECUTE_HANDLER)
803                 {
804                 STATUS(STATUS_UNSUCCESSFUL, 0);
805                 }
806         UNLOCK_PAGING_FCB;
807         FsRtlExitFileSystem();
808         if (Irp->IoStatus.Status == STATUS_UNSUCCESSFUL)
809                 SYNC_FAIL(STATUS_UNSUCCESSFUL);
810         }
811 else
812 #endif
813         {
814         FsRtlEnterFileSystem();
815         SLOCK_FCB;
816         for (currpos = ttlread = 0; ttlread < length; )
817                 {
818                 toread = length - currpos;
819                 toread = (toread > TRANSFER_CHUNK_SIZE) ? TRANSFER_CHUNK_SIZE : toread;
820                 curroff.QuadPart = offset.QuadPart + currpos;
821         status = uc_read(fcb->fid, curroff, toread, &read, outPtr);
822 //              KdPrint(("read  %x at %x done %x\n", length, (ULONG)offset.QuadPart, read));
823                 if (status == 0)
824                         {
825                         ttlread += read;
826                         currpos += read;
827                         if (read < toread)
828                                 goto end;
829                         continue;
830                         }
831                 UNLOCK_FCB;
832                 FsRtlExitFileSystem();
833                 switch (status)
834                         {
835                         case IFSL_RPC_TIMEOUT:          SYNC_FAIL_RPC_TIMEOUT;
836                         case IFSL_IS_A_DIR:                     SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
837                         case IFSL_BAD_INPUT:            SYNC_FAIL(STATUS_INVALID_PARAMETER);
838                         default:                                        SYNC_FAIL(STATUS_UNSUCCESSFUL);
839                         }
840                 }
841 end:    ;
842         UNLOCK_FCB;
843         FsRtlExitFileSystem();
844         }
845
846 /* update byteoffset when this is not a paging or async request */
847 if (IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
848         IrpSp->FileObject->CurrentByteOffset.QuadPart += ttlread;
849
850 if (ttlread == 0)//< length)
851         SYNC_FAIL2(STATUS_END_OF_FILE, ttlread)
852 else
853         SYNC_FAIL2(STATUS_SUCCESS, ttlread)
854 }
855
856
857
858 /**********************************************************
859  * AfsRdrWrite
860  * - handle writes
861  **********************************************************/
862 NTSTATUS AfsRdrWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
863 {
864 struct WriteKOut *p;
865 void *ptr, *outPtr;
866 ULONG length, written;
867 LARGE_INTEGER offset, end;
868 NTSTATUS status;
869 afs_ccb_t *ccb;
870 CC_FILE_SIZES sizes, oldSizes;
871 ULONG towrite, ttlwritten, currpos;
872 LARGE_INTEGER curroff;
873 BOOLEAN change, paging_lock;
874
875 ccb = IrpSp->FileObject->FsContext2;
876 if (IsDeviceFile(IrpSp->FileObject) || (ccb->attribs & FILE_ATTRIBUTE_DIRECTORY))
877         SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
878
879 /* since we will be performing io on this instance, start caching. */
880 #ifdef EXPLICIT_CACHING
881 if (!IrpSp->FileObject->PrivateCacheMap)
882         {
883         CcInitializeCacheMap(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize, FALSE, &rdrExt->callbacks, IrpSp->FileObject->FsContext);//(PVOID)din->Context1);
884         CcSetAdditionalCacheAttributes(IrpSp->FileObject, FALSE, TRUE);
885         }
886 #endif
887
888 if (!(ccb->access & FILE_WRITE_DATA) && !(Irp->Flags & IRP_PAGING_IO))
889         SYNC_FAIL(STATUS_ACCESS_DENIED);
890
891 /* fast-out for zero-length i/o */
892 if (!IrpSp->Parameters.Write.Length)
893         SYNC_FAIL(STATUS_SUCCESS);
894
895 if (IrpSp->Parameters.Write.ByteOffset.HighPart == 0xffffffff &&
896         IrpSp->Parameters.Write.ByteOffset.LowPart == FILE_WRITE_TO_END_OF_FILE)
897         offset.QuadPart = fcb->FileSize.QuadPart;
898 else
899         offset = IrpSp->Parameters.Write.ByteOffset;
900 length = IrpSp->Parameters.Write.Length;
901
902 if (!(outPtr = AfsFindBuffer(Irp)))
903         SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
904
905 #ifdef EXPLICIT_CACHING
906 if (!(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO)))
907         {
908         /* extend file for cached writes */
909         FsRtlEnterFileSystem();
910         LOCK_PAGING_FCB;
911         if (offset.QuadPart + length > fcb->FileSize.QuadPart)
912                 {
913                 end.QuadPart = offset.QuadPart + length;
914                 fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = end;
915                 LOCK_FCB;
916                 CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
917                 UNLOCK_FCB;
918                 /*ret = *//*CcZeroData(IrpSp->FileObject, &oldSizes.FileSize, &end, FALSE);*/ /* should wait? */
919                 }
920         try
921                 {
922                 if (!CcCopyWrite(IrpSp->FileObject, &offset, length, TRUE, outPtr))
923                         SYNC_FAIL(STATUS_UNSUCCESSFUL);
924                 }
925         except (EXCEPTION_EXECUTE_HANDLER)
926                 {
927                 STATUS(STATUS_UNSUCCESSFUL, 0);
928                 }
929 //      KdPrint(("write %x at %x cache done\n", length, (ULONG)offset.QuadPart));
930         UNLOCK_PAGING_FCB;
931         FsRtlExitFileSystem();
932         ttlwritten = written = length;
933         if (Irp->IoStatus.Status == STATUS_UNSUCCESSFUL)
934                 SYNC_FAIL(STATUS_UNSUCCESSFUL);
935         }
936 else
937 #endif
938         {
939         FsRtlEnterFileSystem();
940         while (1)
941                 {
942                 if (offset.QuadPart + length > fcb->FileSize.QuadPart)
943                         change = 1;
944                 else
945                         change = 0;
946                 if (change && !(Irp->Flags & IRP_PAGING_IO))
947                         paging_lock = 1;
948                 else
949                         paging_lock = 0;
950                 if (paging_lock)
951                         LOCK_PAGING_FCB;
952                 LOCK_FCB;
953                 if (offset.QuadPart + length > fcb->FileSize.QuadPart)
954                         {
955                         if (Irp->Flags & IRP_PAGING_IO)
956                                 {
957                                 /* the input buffer and length is for a full page.  ignore this. */
958                                 if (offset.QuadPart > fcb->FileSize.QuadPart)
959                                         {
960                                         if (paging_lock)
961                                                 {
962                                                 _asm int 3;
963                                                 UNLOCK_PAGING_FCB;
964                                                 }
965                                         UNLOCK_FCB;
966                                         FsRtlExitFileSystem();
967                                         SYNC_FAIL2(STATUS_SUCCESS, length);
968                                         }
969                                 length = (ULONG)(fcb->FileSize.QuadPart - offset.QuadPart);
970                                 if (paging_lock)
971                                         {
972                                         _asm int 3;
973                                         UNLOCK_PAGING_FCB;
974                                         }
975                                 break;
976                                 }
977                         else
978                                 {
979                                 if (!change)
980                                         {
981                                         if (paging_lock)
982                                                 {
983                                                 _asm int 3;
984                                                 UNLOCK_PAGING_FCB;
985                                                 }
986                                         UNLOCK_FCB;
987                                         continue;
988                                         }
989                                 end.QuadPart = offset.QuadPart + length;
990                                 fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = end;
991                                 CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
992                                 if (paging_lock)
993                                         UNLOCK_PAGING_FCB;
994                                 break;
995                                 }
996                         }
997                 else
998                         {
999                         //UNLOCK_FCB;
1000                         if (paging_lock)
1001                                 UNLOCK_PAGING_FCB;
1002                         break;
1003                         }
1004                 }
1005
1006         for (currpos = ttlwritten = 0; ttlwritten < length; )
1007                 {
1008                 towrite = length - currpos;
1009                 towrite = (towrite > TRANSFER_CHUNK_SIZE) ? TRANSFER_CHUNK_SIZE : towrite;
1010                 curroff.QuadPart = offset.QuadPart + currpos;
1011         status = uc_write(fcb->fid, curroff, towrite, &written, outPtr);
1012 //              KdPrint(("write %x at %x done\n", length, (ULONG)offset.QuadPart));
1013                 if (status == 0)
1014                         {
1015                         ttlwritten += written;
1016                         currpos += written;
1017                         if (written < towrite)
1018                                 goto end;
1019                         continue;
1020                         }
1021                 UNLOCK_FCB;
1022                 FsRtlExitFileSystem();
1023                 switch (status)
1024                         {
1025                         case IFSL_RPC_TIMEOUT:          SYNC_FAIL_RPC_TIMEOUT;
1026                         case IFSL_BAD_INPUT:            SYNC_FAIL(STATUS_INVALID_PARAMETER);
1027                         case IFSL_OVERQUOTA:            SYNC_FAIL(STATUS_DISK_FULL);
1028                         default:                                        SYNC_FAIL(STATUS_UNSUCCESSFUL);
1029                         }
1030                 }
1031 end:    ;
1032         UNLOCK_FCB;
1033         FsRtlExitFileSystem();
1034         }
1035
1036 if (IoIsOperationSynchronous(Irp) && !(Irp->Flags & IRP_PAGING_IO))
1037         IrpSp->FileObject->CurrentByteOffset.QuadPart += ttlwritten;
1038
1039 /* if we failed a write, we would not be here.  so, we must
1040    tell the vmm that all data was written. */
1041 if (Irp->Flags & IRP_PAGING_IO)
1042         SYNC_FAIL2(STATUS_SUCCESS, IrpSp->Parameters.Write.Length)
1043 SYNC_FAIL2(STATUS_SUCCESS, ttlwritten)
1044 }
1045
1046
1047 wchar_t *SEARCH_MATCH_ALL = L"**";
1048
1049 /**********************************************************
1050  * AfsRdrDirCtrl
1051  * - handle directory notification callbacks
1052  * - handle directory enumeration
1053  **********************************************************/
1054 NTSTATUS AfsRdrDirCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
1055 {
1056 struct EnumDirKOut *p;
1057 LARGE_INTEGER size, creation, access, change, written;
1058 ULONG attribs, count;
1059 char buf[2048];
1060 afs_ccb_t *ccb;
1061 void *outPtr, *info, *pre_adj_info;
1062 FILE_BOTH_DIR_INFORMATION *info_both, *info_both_prev;
1063 FILE_DIRECTORY_INFORMATION *info_dir, *info_dir_prev;
1064 FILE_NAMES_INFORMATION *info_names, *info_names_prev;
1065 int info_size;
1066 readdir_data_t *ii;
1067 ULONG x, buf_size;
1068 LARGE_INTEGER last_cookie;
1069 BOOLEAN overflow;
1070 NTSTATUS status;
1071 FILE_NOTIFY_INFORMATION *notify;
1072
1073 if (IsDeviceFile(IrpSp->FileObject))
1074         SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
1075
1076 if (IrpSp->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)
1077         {
1078         ccb = IrpSp->FileObject->FsContext2;
1079         ccb->str.Length =                       wcslen(ccb->name)*sizeof(wchar_t);
1080         ccb->str.MaximumLength =        ccb->str.Length + sizeof(wchar_t);
1081         ccb->str.Buffer =                       ccb->name;
1082
1083         FsRtlEnterFileSystem();
1084         LOCK_FCB;                               /* FIX: shared lock? */
1085         FsRtlNotifyFullChangeDirectory(rdrExt->notifyList, &rdrExt->listHead,
1086                                                                         ccb,
1087                                                                         (STRING*)&ccb->str,
1088                                                                         IrpSp->Flags & SL_WATCH_TREE,
1089                                                                         FALSE,
1090                                                                         /*FILE_NOTIFY_CHANGE_FILE_NAME,*/IrpSp->Parameters.NotifyDirectory.CompletionFilter,
1091                                                                         Irp, NULL, NULL);
1092         UNLOCK_FCB;
1093         FsRtlExitFileSystem();
1094         /* do NOT complete request; that will be done by fsrtlnotify functions */
1095         return STATUS_PENDING;
1096         }
1097
1098 if (IrpSp->MinorFunction != IRP_MN_QUERY_DIRECTORY)
1099         SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
1100
1101 if (IrpSp->Parameters.QueryDirectory.FileInformationClass != FileBothDirectoryInformation &&
1102         IrpSp->Parameters.QueryDirectory.FileInformationClass != FileDirectoryInformation &&
1103         IrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation)
1104         {
1105         _asm int 3;
1106         rpt0(("enum", "enum class %d not supported", IrpSp->Parameters.QueryDirectory.FileInformationClass));
1107         SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
1108         }
1109
1110 ccb = IrpSp->FileObject->FsContext2;
1111
1112 if (!(outPtr = AfsFindBuffer(Irp)))
1113         SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
1114
1115 if (IrpSp->Flags & SL_INDEX_SPECIFIED)
1116         {
1117         /* we were told where to start our search; afsd should scrub this input */
1118         ccb->cookie.QuadPart = IrpSp->Parameters.QueryDirectory.FileIndex;
1119         if (ccb->filter && ccb->filter != SEARCH_MATCH_ALL)
1120                 ExFreePoolWithTag(ccb->filter, AFS_RDR_TAG);
1121         ccb->filter = SEARCH_MATCH_ALL;
1122         }
1123 else if (IrpSp->Flags & SL_RESTART_SCAN ||
1124                  ((IrpSp->Flags & SL_RETURN_SINGLE_ENTRY) && ccb->cookie.QuadPart == 0))
1125         {
1126         /* copy new filter string into nonpaged memory */
1127         ccb->cookie.QuadPart = 0;
1128         if (ccb->filter && ccb->filter != SEARCH_MATCH_ALL)
1129                 ExFreePoolWithTag(ccb->filter, AFS_RDR_TAG);
1130         buf_size = IrpSp->Parameters.QueryDirectory.FileName->Length+6;
1131         ccb->filter = ExAllocatePoolWithTag(NonPagedPool, buf_size, AFS_RDR_TAG);
1132         RtlCopyMemory(ccb->filter, IrpSp->Parameters.QueryDirectory.FileName->Buffer, buf_size);
1133         ccb->filter[IrpSp->Parameters.QueryDirectory.FileName->Length / sizeof(WCHAR)] = L'\0';
1134         }
1135
1136 if (IrpSp->Flags & SL_RETURN_SINGLE_ENTRY)
1137         count = 1;
1138 buf_size = 2040;
1139
1140 status = uc_readdir(fcb->fid, ccb->cookie, ccb->filter, &count, buf, &buf_size);
1141
1142 switch (status)
1143         {
1144         case IFSL_RPC_TIMEOUT:          SYNC_FAIL_RPC_TIMEOUT;
1145         case IFSL_BAD_INPUT:            SYNC_FAIL(STATUS_INVALID_PARAMETER);
1146         default:                                        SYNC_FAIL(STATUS_UNSUCCESSFUL);
1147         case 0: break;
1148         }
1149
1150 switch (IrpSp->Parameters.QueryDirectory.FileInformationClass)
1151         {
1152         case FileBothDirectoryInformation:
1153                 info_size = sizeof(FILE_BOTH_DIR_INFORMATION);
1154                 break;
1155         case FileDirectoryInformation:
1156                 info_size = sizeof(FILE_DIRECTORY_INFORMATION);
1157                 break;
1158         case FileNamesInformation:
1159                 info_size = sizeof(FILE_NAMES_INFORMATION);
1160                 break;
1161         default:
1162                 KeBugCheckEx(0x12345, 0x98, 0x0, 0x0, 0x0);
1163         }
1164
1165 info = (FILE_BOTH_DIR_INFORMATION *)outPtr;
1166 ii = (readdir_data_t *)buf;
1167 Irp->IoStatus.Information = 0;
1168 if (!count)
1169         {
1170         if (IrpSp->Flags & SL_RETURN_SINGLE_ENTRY && ccb->cookie.QuadPart == 0)
1171                 SYNC_FAIL(STATUS_NO_SUCH_FILE);
1172         SYNC_FAIL(STATUS_NO_MORE_FILES);
1173         }
1174
1175 info_both_prev = NULL;
1176 info_dir_prev = NULL;
1177 info_names_prev = NULL;
1178 if (IrpSp->Flags & SL_RETURN_SINGLE_ENTRY)
1179         count = 1;
1180
1181 for (x = 0; x < count; x++)
1182         {
1183         pre_adj_info = info;
1184
1185         /* must explicitly align second and subsequent entries on 8-byte boundaries */
1186         if (((ULONG)info & 0x7) && x)
1187                 info = (void*)(((ULONG)info) + (8-((ULONG)info & 0x7)));
1188
1189         overflow = ((long)info + info_size + (long)ii->name_length >
1190                                 (long)outPtr + (long)IrpSp->Parameters.QueryDirectory.Length);
1191         if (overflow && x != 0)
1192                 {
1193                 ccb->cookie = ii->cookie;
1194                 SYNC_FAIL2(STATUS_SUCCESS, (long)pre_adj_info - (long)outPtr);
1195                 }
1196
1197         memset(info, 0, info_size);
1198         switch (IrpSp->Parameters.QueryDirectory.FileInformationClass)
1199                 {
1200                 case FileBothDirectoryInformation:
1201                         info_both = info;
1202                         if (info_both_prev)
1203                                 info_both_prev->NextEntryOffset = (char*)info_both - (char*)info_both_prev;
1204
1205                         info_both->NextEntryOffset = 0;
1206                         info_both->FileIndex = (ULONG)ii->cookie.QuadPart;
1207                         info_both->CreationTime.QuadPart = AfsTimeToWindowsTime(ii->creation.QuadPart);
1208                         info_both->LastAccessTime.QuadPart = AfsTimeToWindowsTime(ii->access.QuadPart);
1209                         info_both->LastWriteTime.QuadPart = AfsTimeToWindowsTime(ii->write.QuadPart);
1210                         info_both->ChangeTime.QuadPart = AfsTimeToWindowsTime(ii->change.QuadPart);
1211                         info_both->EndOfFile = info_both->AllocationSize = ii->size;
1212                         info_both->FileAttributes = ii->attribs;/*| FILE_ATTRIBUTE_READONLY*/;
1213                         info_both->EaSize = 0;
1214                         info_both->ShortNameLength = ii->short_name_length;
1215                         info_both->FileNameLength = ii->name_length;
1216                         RtlCopyMemory(info_both->ShortName, ii->short_name, ii->short_name_length*sizeof(WCHAR));
1217
1218                         if (overflow)
1219                                 {
1220                                 Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
1221                                 info_both->FileNameLength = 0;
1222                                 info_both->FileName[0] = L'\0';
1223                                 goto done;
1224                                 }
1225
1226                         RtlCopyMemory(info_both->FileName, ii->name, ii->name_length*sizeof(WCHAR));
1227                         info_both_prev = info_both;
1228                         break;
1229
1230                 case FileDirectoryInformation:
1231                         info_dir = info;
1232                         if (info_dir_prev)
1233                                 info_dir_prev->NextEntryOffset = (char*)info_dir - (char*)info_dir_prev;
1234
1235                         info_dir->NextEntryOffset = 0;
1236                         info_dir->FileIndex = (ULONG)ii->cookie.QuadPart;
1237                         info_dir->CreationTime.QuadPart = AfsTimeToWindowsTime(ii->creation.QuadPart);
1238                         info_dir->LastAccessTime.QuadPart = AfsTimeToWindowsTime(ii->access.QuadPart);
1239                         info_dir->LastWriteTime.QuadPart = AfsTimeToWindowsTime(ii->write.QuadPart);
1240                         info_dir->ChangeTime.QuadPart = AfsTimeToWindowsTime(ii->change.QuadPart);
1241                         info_dir->EndOfFile = info_dir->AllocationSize = ii->size;
1242                         info_dir->FileAttributes = ii->attribs /*| FILE_ATTRIBUTE_READONLY*/;
1243                         info_dir->FileNameLength = ii->name_length;
1244
1245                         if (overflow)
1246                                 {
1247                                 Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
1248                                 info_dir->FileNameLength = 0;
1249                                 info_dir->FileName[0] = L'\0';
1250                                 goto done;
1251                                 }
1252
1253                         RtlCopyMemory(info_dir->FileName, ii->name, ii->name_length*sizeof(WCHAR));
1254                         info_dir_prev = info_dir;
1255                         break;
1256
1257                 case FileNamesInformation:
1258                         info_names = info;
1259                         if (info_names_prev)
1260                                 info_names_prev->NextEntryOffset = (char*)info_names - (char*)info_names_prev;
1261
1262                         info_names->NextEntryOffset = 0;
1263                         info_names->FileIndex = (ULONG)ii->cookie.QuadPart;
1264                         info_names->FileNameLength = ii->name_length;
1265
1266                         if (overflow)
1267                                 {
1268                                 Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
1269                                 info_names->FileNameLength = 0;
1270                                 info_names->FileName[0] = L'\0';
1271                                 goto done;
1272                                 }
1273
1274                         RtlCopyMemory(info_names->FileName, ii->name, ii->name_length*sizeof(WCHAR));
1275                         info_names_prev = info_names;
1276                         break;
1277                 }
1278
1279         info = (void*)(((ULONG)info) + info_size + (ULONG)ii->name_length*sizeof(WCHAR));
1280         ii = (readdir_data_t *)(((unsigned char *)ii) + sizeof(readdir_data_t) + ii->name_length);
1281         last_cookie = ii->cookie;
1282         }
1283
1284 Irp->IoStatus.Status = STATUS_SUCCESS;
1285 done:
1286         ccb->cookie = last_cookie;
1287
1288 SYNC_FAIL2(Irp->IoStatus.Status, (long)info - (long)outPtr);
1289 }
1290
1291
1292
1293
1294 /**********************************************************
1295  * AfsRdrQueryInfo
1296  * - handle stat calls
1297  **********************************************************/
1298 NTSTATUS AfsRdrQueryInfo(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
1299 {
1300 FILE_BASIC_INFORMATION *infoBasic;
1301 FILE_NAME_INFORMATION *infoName;
1302 FILE_STANDARD_INFORMATION *infoStandard;
1303 FILE_POSITION_INFORMATION *infoPosition;
1304 FILE_ALL_INFORMATION *infoAll;
1305 FILE_INTERNAL_INFORMATION *infoInternal;
1306 LARGE_INTEGER size, creation, access, change, written;
1307 ULONG attribs;
1308 long count;
1309 afs_ccb_t *ccb;
1310 char *outPtr;
1311 NTSTATUS status;
1312 wchar_t *start;
1313
1314 if (IsDeviceFile(IrpSp->FileObject))
1315         SYNC_FAIL(STATUS_UNSUCCESSFUL);                         // what should happen?
1316
1317 if (!(outPtr = AfsFindBuffer(Irp)))
1318         SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
1319
1320 ccb = IrpSp->FileObject->FsContext2;
1321
1322 status = uc_stat(fcb->fid, &attribs, &size, &creation, &access, &change, &written);
1323 switch (status)
1324         {
1325         case IFSL_RPC_TIMEOUT:          SYNC_FAIL_RPC_TIMEOUT;
1326         case IFSL_BAD_INPUT:            SYNC_FAIL(STATUS_INVALID_PARAMETER);
1327         default:                                        SYNC_FAIL(STATUS_UNSUCCESSFUL);
1328         case 0: break;
1329         }
1330
1331 /* afsd does not maintain instance-specific data, so we adjust here */
1332 if (ccb->access & FILE_READ_DATA && !(ccb->access & FILE_WRITE_DATA))
1333         attribs |= FILE_ATTRIBUTE_READONLY;
1334
1335 (void*)infoBasic = (void*)infoName = (void*)infoPosition = (void*)infoStandard = (void*)infoInternal = NULL;
1336 switch (IrpSp->Parameters.QueryFile.FileInformationClass)
1337         {
1338         case FileBasicInformation:
1339                 infoBasic = (FILE_BASIC_INFORMATION*)outPtr;
1340                 break;
1341         case FileNameInformation:
1342                 infoName = (FILE_NAME_INFORMATION*)outPtr;
1343                 break;
1344         case FileStandardInformation:
1345                 infoStandard = (FILE_STANDARD_INFORMATION*)outPtr;
1346                 break;
1347         case FilePositionInformation:
1348                 infoPosition = (FILE_POSITION_INFORMATION*)outPtr;
1349                 break;
1350         case FileAllInformation:
1351                 infoAll = (FILE_ALL_INFORMATION*)outPtr;
1352                 infoBasic = &infoAll->BasicInformation;
1353                 infoName = &infoAll->NameInformation;
1354                 infoStandard = &infoAll->StandardInformation;
1355                 infoPosition = &infoAll->PositionInformation;
1356                 break;
1357         case FileInternalInformation:
1358                 infoInternal = (FILE_INTERNAL_INFORMATION*)outPtr;
1359                 break;
1360         default:
1361                 STATUS(STATUS_NOT_IMPLEMENTED, 0);
1362                 break;
1363         }
1364
1365 if (infoBasic)
1366         {
1367         memset(infoBasic, 0, sizeof(FILE_BASIC_INFORMATION));
1368         infoBasic->FileAttributes = attribs;
1369         infoBasic->CreationTime.QuadPart = AfsTimeToWindowsTime(creation.QuadPart);
1370         infoBasic->LastAccessTime.QuadPart = AfsTimeToWindowsTime(access.QuadPart);
1371         infoBasic->LastWriteTime.QuadPart = AfsTimeToWindowsTime(written.QuadPart);
1372         infoBasic->ChangeTime.QuadPart = AfsTimeToWindowsTime(change.QuadPart);
1373         STATUS(STATUS_SUCCESS, sizeof(FILE_BASIC_INFORMATION));
1374         //KdPrint(("query basicinfo %d,%d %x,%I64d,%I64d\n", fcb->fid, (ULONG)IrpSp->FileObject->FsContext2, infoBasic->FileAttributes, infoBasic->CreationTime.QuadPart, infoBasic->ChangeTime.QuadPart));
1375         }
1376
1377 if (infoName)
1378         {
1379         memset(infoName, 0, sizeof(FILE_NAME_INFORMATION));
1380         start = ccb->name;
1381         count = (long)(*(start+1) - L'0');
1382         if (count > 9 || count < 0)
1383                 SYNC_FAIL(STATUS_OBJECT_NAME_INVALID);
1384         if (count || *start == L'0')
1385                 {
1386                 for ( ; count >= 0 && start; count--)
1387                         start = wcschr(start+1, L'\\');
1388                 if (!start)
1389                         SYNC_FAIL(STATUS_OBJECT_NAME_INVALID);
1390                 }
1391         infoName->FileNameLength = wcslen(start)*sizeof(WCHAR);
1392         if (((IrpSp->Parameters.QueryFile.FileInformationClass == FileAllInformation) ? sizeof(*infoAll) : sizeof(*infoName)) +
1393                 infoName->FileNameLength > IrpSp->Parameters.QueryFile.Length)
1394                 {
1395                 infoName->FileNameLength = 0;
1396                 infoName->FileName[0] = L'\0';
1397                 STATUS(STATUS_BUFFER_OVERFLOW, sizeof(FILE_NAME_INFORMATION));
1398                 //KdPrint(("query overflowing buffer %d\n", IrpSp->Parameters.QueryFile.Length));
1399                 }
1400         else
1401                 {               //TODO:check filename is correct/correct format
1402                 StringCbCopy(infoName->FileName, IrpSp->Parameters.QueryFile.Length - sizeof(*infoName), start);
1403                 STATUS(STATUS_SUCCESS, sizeof(FILE_NAME_INFORMATION) + (infoName->FileNameLength - sizeof(WCHAR)));
1404                 }
1405         //KdPrint(("query nameinfo %ws from %ws\n", infoName->FileName, ccb->name));
1406         }
1407
1408 if (infoStandard)
1409         {
1410         memset(infoStandard, 0, sizeof(FILE_STANDARD_INFORMATION));
1411         infoStandard->AllocationSize.QuadPart = size.QuadPart;
1412         infoStandard->EndOfFile.QuadPart = size.QuadPart;
1413         infoStandard->NumberOfLinks = 1;
1414         infoStandard->DeletePending = (fcb->delPending == 1);
1415         infoStandard->Directory = (attribs & FILE_ATTRIBUTE_DIRECTORY)?TRUE:FALSE;      //TODO:check if flag is valid at this point
1416         STATUS(STATUS_SUCCESS, sizeof(FILE_STANDARD_INFORMATION));
1417         //KdPrint(("query stdinfo %d,%d %I64d,%s\n", fcb->fid, (ULONG)IrpSp->FileObject->FsContext2, infoStandard->EndOfFile.QuadPart, infoStandard->Directory?"dir":"file"));
1418         }
1419
1420 if (infoPosition)
1421         {
1422         infoPosition->CurrentByteOffset = IrpSp->FileObject->CurrentByteOffset;
1423         STATUS(STATUS_SUCCESS, sizeof(FILE_POSITION_INFORMATION));
1424         //KdPrint(("query position %d,%d %I64d\n", fcb, (ULONG)IrpSp->FileObject->FsContext2, infoPosition->CurrentByteOffset.QuadPart));
1425         }
1426
1427 if (IrpSp->Parameters.QueryFile.FileInformationClass == FileAllInformation)
1428         {
1429         if (!infoName->FileNameLength)
1430                 STATUS(STATUS_BUFFER_OVERFLOW, sizeof(FILE_ALL_INFORMATION));
1431         else
1432                 STATUS(STATUS_SUCCESS, sizeof(FILE_ALL_INFORMATION) + (infoName->FileNameLength - sizeof(WCHAR)));
1433         }
1434
1435 if (infoInternal)
1436         {
1437         infoInternal->IndexNumber.QuadPart = fcb->fid;
1438         STATUS(STATUS_SUCCESS, sizeof(FILE_INTERNAL_INFORMATION));
1439         }
1440
1441 status = Irp->IoStatus.Status;
1442 COMPLETE;
1443 return status;
1444 }
1445
1446
1447
1448
1449 /**********************************************************
1450  * AfsRdrSetInfo
1451  * - handle setting mod time
1452  * - handle deleting
1453  * - handle truncation/extension
1454  * - handle renaming
1455  **********************************************************/
1456 NTSTATUS AfsRdrSetInfo(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
1457 {
1458 struct SetInfoKOut *p;
1459 afs_fcb_t *fcbt;
1460 afs_ccb_t *ccb;
1461 FILE_DISPOSITION_INFORMATION *infoDisp;
1462 FILE_BASIC_INFORMATION *infoBasic;
1463 FILE_END_OF_FILE_INFORMATION *infoLength;
1464 FILE_RENAME_INFORMATION *infoRename;
1465 FILE_POSITION_INFORMATION *infoPosition;
1466 NTSTATUS ret;
1467 wchar_t *buf, *part, *ptr;
1468 ULONG size, new_fid;
1469 NTSTATUS status;
1470
1471 if (IrpSp->FileObject->FileName.Length == 0)
1472         SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
1473
1474 ccb = IrpSp->FileObject->FsContext2;
1475
1476 switch (IrpSp->Parameters.SetFile.FileInformationClass)
1477         {
1478         /* delete disposition */
1479         case FileDispositionInformation:
1480                 infoDisp = Irp->AssociatedIrp.SystemBuffer;
1481
1482                 FsRtlEnterFileSystem();
1483                 LOCK_FCB;
1484
1485                 if (infoDisp->DeleteFile)
1486                         {
1487                         if (!MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForDelete))
1488                                 SYNC_FAIL(STATUS_ACCESS_DENIED);
1489             fcb->delPending |= 0x1;
1490                         }
1491                 else
1492                         fcb->delPending &= ~0x1;
1493                 UNLOCK_FCB;
1494                 FsRtlExitFileSystem();
1495                 SYNC_RET(STATUS_SUCCESS);
1496
1497         /*case FileAllocationInformation:*/
1498         case FileEndOfFileInformation:
1499                 /* ignore extensions caused by paging requests*/
1500                 if (Irp->Flags & IRP_PAGING_IO)
1501                         SYNC_FAIL(STATUS_SUCCESS);
1502                 
1503                 infoLength = Irp->AssociatedIrp.SystemBuffer;
1504
1505                 FsRtlEnterFileSystem();
1506                 LOCK_PAGING_FCB;
1507                 LOCK_FCB;
1508                 if (IrpSp->Parameters.SetFile.AdvanceOnly && (infoLength->EndOfFile.QuadPart > fcb->FileSize.QuadPart) ||
1509                         !IrpSp->Parameters.SetFile.AdvanceOnly && (infoLength->EndOfFile.QuadPart < fcb->FileSize.QuadPart))
1510                         {
1511                         status = uc_trunc(fcb->fid, infoLength->EndOfFile);
1512                         /* because it is not written to the server immediately, this error will not always happen */
1513                         if (status == IFSL_OVERQUOTA)
1514                                 {
1515                                 UNLOCK_FCB;
1516                                 UNLOCK_PAGING_FCB;
1517                                 FsRtlExitFileSystem();
1518                                 SYNC_FAIL(STATUS_DISK_FULL);
1519                                 }
1520                         }
1521                 fcb->FileSize = fcb->AllocationSize = fcb->ValidDataLength = infoLength->EndOfFile;
1522                 CcSetFileSizes(IrpSp->FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
1523                 //CcPurgeCacheSection(IrpSp->FileObject->SectionObjectPointer, &fcb->AllocationSize, 0, FALSE);
1524                 UNLOCK_FCB;
1525                 UNLOCK_PAGING_FCB;
1526                 FsRtlExitFileSystem();
1527                 SYNC_FAIL(STATUS_SUCCESS);
1528
1529         case FileBasicInformation:
1530                 infoBasic = Irp->AssociatedIrp.SystemBuffer;
1531                 status = uc_setinfo(fcb->fid, infoBasic->FileAttributes, infoBasic->CreationTime, infoBasic->LastAccessTime, infoBasic->ChangeTime, infoBasic->LastWriteTime);
1532                 SYNC_FAIL(STATUS_SUCCESS);
1533
1534         case FileRenameInformation:
1535                 //KdPrint(("set rename %d\n", fcb->fid));
1536                 infoRename = Irp->AssociatedIrp.SystemBuffer;
1537                 new_fid = fcb->fid;
1538                 //rpt1(("setinfo", "rename %d,%d %d,%ws", ExtractFid(fcb), (ULONG)IrpSp->FileObject->FsContext2, infoRename->ReplaceIfExists, infoRename->FileName));
1539
1540                 if (IrpSp->Parameters.SetFile.FileObject)
1541                         fcbt = FindFcb(IrpSp->Parameters.SetFile.FileObject);                   
1542
1543                 //null-terminate all strings into uc_rename?
1544                 //FIX/one rename case not working
1545
1546                 if (IrpSp->Parameters.SetFile.FileObject == NULL &&
1547                         infoRename->RootDirectory == NULL)
1548                         {
1549                         WCHAR fname[300];                       /* FIX: uc_rename needs null-terminated string */
1550                         StringCchCopyNW(fname, 300-1, infoRename->FileName, infoRename->FileNameLength/sizeof(WCHAR));
1551                         uc_rename(fcb->fid, ccb->name+2, NULL, fname, &new_fid);
1552                         fcb->fid = new_fid;
1553                         }
1554                 else if (IrpSp->Parameters.SetFile.FileObject != NULL &&
1555                                  infoRename->RootDirectory == NULL)
1556                         {
1557                         WCHAR fname[300];
1558                         StringCchCopyNW(fname, 300-1, infoRename->FileName, infoRename->FileNameLength/sizeof(WCHAR));
1559                         uc_rename(fcb->fid, ccb->name+2, fcbt->ccb_list->name+2, fname, &new_fid);
1560                         fcb->fid = new_fid;
1561                         }
1562                 else
1563                         {
1564                         _asm int 3;
1565                         /*fcbt = FindFcb(IrpSp->Parameters.SetFile.FileObject);
1566
1567                         p->CurrNameOff = 0;
1568                         StringCbCopyW(buf, size, fcb->name);
1569                         p->NewNameOff = wcslen(buf)+1;
1570                         StringCbCopyNW(buf + p->NewNameOff,
1571                                                   size - p->NewNameOff,
1572                                                   infoRename->FileName,
1573                                                   infoRename->FileNameLength*sizeof(wchar_t));
1574                         buf[p->NewNameOff+infoRename->FileNameLength] = L'\0';
1575                         p->NewDirOff = p->NewNameOff + wcslen(buf + p->NewNameOff)+1;
1576                         StringCbCopyW(buf + p->NewDirOff,
1577                                                   size - p->NewDirOff,
1578                                                   fcbt->name);*/
1579                         }
1580                 SYNC_RET(STATUS_SUCCESS);
1581                 break;
1582
1583         case FilePositionInformation:
1584                 infoPosition = Irp->AssociatedIrp.SystemBuffer;
1585                 IrpSp->FileObject->CurrentByteOffset = infoPosition->CurrentByteOffset;
1586                 SYNC_FAIL(STATUS_SUCCESS);
1587
1588         default:
1589                 KdPrint(("set unsupp %d type %d\n", fcb->fid, IrpSp->Parameters.SetFile.FileInformationClass));
1590                 SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
1591         }
1592
1593 SYNC_FAIL(STATUS_UNSUCCESSFUL);
1594 }
1595
1596 dc_break_callback(ULONG fid)
1597 {
1598 afs_fcb_t *fcb;
1599 int pos;
1600 USHORT len;
1601 UNICODE_STRING *s;
1602
1603 LOCK_FCB_LIST;
1604
1605 fcb = find_fcb(fid);
1606 if (!fcb)
1607         {
1608         UNLOCK_FCB_LIST;
1609         return 1;                                       /* we are done with this file */
1610         }
1611
1612 ASSERT(fcb->ccb_list);
1613 /*pos = wcslen(fcb->ccb_list->name);
1614 if (fcb->ccb_list->name[pos-1] == L'\\')
1615         pos--;
1616 ASSERT(pos);
1617 while (pos > 0)
1618         {
1619         if (fcb->ccb_list->name[pos-1] == L'\\')
1620                 break;
1621         pos--;
1622         }*/
1623
1624 len = (wcslen(fcb->ccb_list->name) + 10) * sizeof(wchar_t);
1625 s = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)+len+sizeof(wchar_t));
1626 s->Length = len;
1627 s->MaximumLength = len + sizeof(wchar_t);
1628 s->Buffer = (PWSTR)(s+1);
1629
1630 StringCbCopyW((PWSTR)(s+1), len, fcb->ccb_list->name);
1631 if (s->Buffer[wcslen(s->Buffer) - 1] != L'\\')
1632         StringCbCatW(s->Buffer, len, L"\\");
1633 pos = wcslen(s->Buffer);
1634 StringCbCatW(s->Buffer, len, L"jj");                                    /* FIX: make bogus change notification */
1635
1636 KdPrint(("break callback on %d %ws %ws\n", fid, fcb->ccb_list->name, fcb->ccb_list->name+pos));
1637
1638 FsRtlNotifyFullReportChange(rdrExt->notifyList, &rdrExt->listHead,
1639                                                         (PSTRING)s, (USHORT)pos*sizeof(wchar_t), NULL, NULL,
1640                                                         FILE_NOTIFY_CHANGE_FILE_NAME/*FILE_NOTIFY_VALID_MASK/*FILE_NOTIFY_CHANGE_FILE_NAME*/, FILE_ACTION_ADDED, NULL);
1641
1642 ExFreePool(s);
1643 UNLOCK_FCB_LIST;
1644 return 0;
1645 }
1646
1647 /**********************************************************
1648  * AfsRdrDeviceControl
1649  * - handle communication requests from fs, etc.
1650  * - handle ioctls
1651  **********************************************************/
1652 NTSTATUS AfsRdrDeviceControl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
1653 {
1654 struct KOutEntry *entry;
1655 NTSTATUS ret;
1656 struct CbKIn *kin;
1657 USHORT offset;
1658 UNICODE_STRING nm;
1659 void *outPtr;
1660 ULONG key, code, length;
1661
1662 /* utility ioctls */
1663 if (DeviceObject == ComDevice &&
1664         IrpSp->FileObject->FsContext2 == COMM_IOCTL &&
1665         IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFSRDR_IOCTL)
1666         {
1667         outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
1668         if (!outPtr)
1669                 _asm int 3;
1670
1671         rpc_set_context(IrpSp->FileObject->FsContext);
1672         code = uc_ioctl_write(IrpSp->Parameters.DeviceIoControl.InputBufferLength,
1673                                                         Irp->AssociatedIrp.SystemBuffer,
1674                                                         (ULONG*)&key);
1675         length = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1676         if (!code)              
1677                 code = uc_ioctl_read(key, &length, outPtr);
1678         rpc_remove_context();
1679
1680         switch (code)
1681                 {
1682                 case IFSL_SUCCESS:
1683                         STATUS(STATUS_SUCCESS, length);
1684                         break;
1685                 default:
1686                         STATUS(STATUS_UNSUCCESSFUL, 0);
1687                         break;
1688                 }
1689         }
1690 /* downcalls by afsd */
1691 else if (DeviceObject == ComDevice &&
1692                  IrpSp->FileObject->FsContext2 == COMM_DOWNCALL &&
1693                  IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFSRDR_DOWNCALL)
1694         {
1695         outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
1696         if (!outPtr)
1697                 _asm int 3;
1698
1699         rpc_set_context(IrpSp->FileObject->FsContext);
1700         code = rpc_call(IrpSp->Parameters.DeviceIoControl.InputBufferLength,
1701                                         Irp->AssociatedIrp.SystemBuffer,
1702                                         IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
1703                                         outPtr,
1704                                         &length);
1705         rpc_remove_context();
1706         switch (code)
1707                 {
1708                 case IFSL_SUCCESS:
1709                         STATUS(STATUS_SUCCESS, length);
1710                         break;
1711                 default:
1712                         STATUS(STATUS_UNSUCCESSFUL, 0);
1713                         break;
1714                 }
1715         }
1716 else if (DeviceObject == RdrDevice &&
1717                  IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFSRDR_GET_PATH)
1718         {
1719         outPtr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
1720         if (!outPtr)
1721                 _asm int 3;
1722
1723         StringCbCopyW(outPtr, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, fcb->ccb_list->name+2);
1724
1725         STATUS(STATUS_SUCCESS, (wcslen(outPtr)+1)*sizeof(wchar_t));
1726         }
1727 else
1728         {
1729         rpt0(("devctl", "devctl %d rejected", IrpSp->Parameters.DeviceIoControl.IoControlCode));
1730         SYNC_FAIL(STATUS_INVALID_DEVICE_REQUEST);
1731         }
1732
1733 ret = Irp->IoStatus.Status;
1734 COMPLETE;
1735 return ret;
1736 }
1737
1738
1739
1740 /**********************************************************
1741  * AfsRdrCleanup
1742  * - called when usermode handle count reaches zero
1743  **********************************************************/
1744 NTSTATUS AfsRdrCleanup(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
1745 {
1746 NTSTATUS ret;
1747 struct AfsRdrExtension *ext;
1748
1749 //try {
1750 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1751
1752 if (IrpSp->FileObject->FileName.Length == 0)
1753         SYNC_FAIL(STATUS_SUCCESS);
1754
1755 ext = ((struct AfsRdrExtension*)RdrDevice->DeviceExtension);
1756
1757 LOCK_FCB_LIST;
1758 LOCK_PAGING_FCB;
1759 LOCK_FCB;
1760
1761 FsRtlNotifyCleanup(ext->notifyList, &ext->listHead, IrpSp->FileObject->FsContext2);
1762
1763 CcFlushCache(IrpSp->FileObject->SectionObjectPointer, NULL, 0, NULL);
1764
1765 if (fcb->delPending && !MmFlushImageSection(&(fcb->sectionPtrs), MmFlushForDelete))
1766         /* yes, moot at this point */
1767         STATUS(STATUS_ACCESS_DENIED, 0);
1768 else
1769         STATUS(STATUS_SUCCESS, 0);
1770
1771 MmFlushImageSection(IrpSp->FileObject->SectionObjectPointer, MmFlushForWrite);
1772 CcPurgeCacheSection(IrpSp->FileObject->SectionObjectPointer, NULL, 0, TRUE);
1773 CcUninitializeCacheMap(IrpSp->FileObject, NULL, NULL);
1774
1775 UNLOCK_FCB;
1776 UNLOCK_PAGING_FCB;
1777 UNLOCK_FCB_LIST;
1778
1779 /*} except(EXCEPTION_EXECUTE_HANDLER)
1780         {
1781         _asm int 3;
1782         STATUS(STATUS_UNSUCCESSFUL, 0);
1783         ExReleaseResourceLite(&ext->fcbLock);
1784         FsRtlExitFileSystem();
1785         }*/
1786
1787 ret = Irp->IoStatus.Status;
1788 COMPLETE;
1789 return ret;
1790 }
1791
1792
1793 /**********************************************************
1794  * AfsRdrClose
1795  * - handle actual unlinking
1796  * - handle closing
1797  **********************************************************/
1798 NTSTATUS AfsRdrClose(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
1799 {
1800 ULONG length;
1801 wchar_t *name;
1802 char kill;
1803 KEVENT ev;
1804 LARGE_INTEGER timeout;
1805 afs_ccb_t *ccb, *curr;
1806
1807 if (IrpSp->FileObject->FileName.Length == 0)
1808         SYNC_FAIL(STATUS_SUCCESS);
1809
1810 ccb = IrpSp->FileObject->FsContext2;
1811 LOCK_FCB_LIST;
1812
1813 /* set share correctly so future opens can succeed */
1814 IoRemoveShareAccess(IrpSp->FileObject, &fcb->share_access);
1815 ObDereferenceObject(ccb->token);
1816
1817 curr = fcb->ccb_list;
1818 if (fcb->ccb_list == ccb)
1819         fcb->ccb_list = fcb->ccb_list->next;
1820 else
1821         while (curr->next)
1822                 {
1823                 if (curr->next == ccb)
1824                         {
1825                         curr->next = curr->next->next;
1826                         break;
1827                         }
1828                 curr = curr->next;
1829                 }
1830
1831 if (!fcb->ccb_list)
1832         {
1833         uc_close(fcb->fid);
1834         if (fcb->delPending)
1835                 {
1836                 uc_unlink(ccb->name+2);
1837                 }
1838         ExDeleteResourceLite(&fcb->_resource);
1839         ExDeleteResourceLite(&fcb->_pagingIoResource);
1840         RtlDeleteElementGenericTable(&rdrExt->fcbTable, &fcb);
1841         ExFreeToNPagedLookasideList(&rdrExt->fcbMemList, fcb);
1842         }
1843
1844 ExFreePoolWithTag(ccb->name, AFS_RDR_TAG);
1845 if (ccb->filter && ccb->filter != SEARCH_MATCH_ALL)
1846         ExFreePoolWithTag(ccb->filter, AFS_RDR_TAG);
1847 ExFreeToNPagedLookasideList(&rdrExt->ccbMemList, ccb);
1848
1849 UNLOCK_FCB_LIST;
1850
1851 SYNC_FAIL(STATUS_SUCCESS);
1852 }
1853
1854
1855 /**********************************************************
1856  * AfsRdrShutdown
1857  * - should flush all data
1858  **********************************************************/
1859 NTSTATUS AfsRdrShutdown(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp)
1860 {
1861 _asm int 3;
1862 STATUS(STATUS_SUCCESS, 0);
1863 COMPLETE;
1864 }
1865
1866
1867 /**********************************************************
1868  * AfsRdrFlushFile
1869  * - flushes specified file to userspace and then disk
1870  **********************************************************/
1871 NTSTATUS AfsRdrFlushFile(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
1872 {
1873 NTSTATUS ret;
1874 afs_ccb_t *ccb;
1875
1876 /*TRY*/
1877 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1878
1879 if (IrpSp->FileObject->FileName.Length == 0)
1880         SYNC_RET(STATUS_INVALID_DEVICE_REQUEST);
1881
1882 ccb = IrpSp->FileObject->FsContext2;
1883
1884 CcFlushCache(&fcb->sectionPtrs, NULL, 0, &Irp->IoStatus);
1885
1886 //SYNC_FAIL2(/*STATUS_LOCK_NOT_GRANTED*//*STATUS_NOT_IMPLEMENTED*/STATUS_SUCCESS, 0);
1887
1888 /*EXCEPT(STATUS_UNSUCCESSFUL, 0);*/
1889 COMPLETE;
1890 return Irp->IoStatus.Status;
1891 }
1892
1893
1894 /**********************************************************
1895  * AfsRdrLockCtrl
1896  * - should handle lock requests
1897  **********************************************************/
1898 NTSTATUS AfsRdrLockCtrl(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp, afs_fcb_t *fcb)
1899 {
1900 NTSTATUS ret;
1901
1902 /*TRY*/
1903 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1904
1905 /* complete lock on control device object without processing, as directed */
1906 if (IrpSp->FileObject->FileName.Length == 0)
1907         {
1908         rpt0(("lock", "lock granted on root device obj"));
1909         SYNC_FAIL(STATUS_SUCCESS);
1910         }
1911
1912 SYNC_FAIL2(/*STATUS_LOCK_NOT_GRANTED*//*STATUS_NOT_IMPLEMENTED*/STATUS_SUCCESS, 0);
1913
1914 /*EXCEPT(STATUS_UNSUCCESSFUL, 0);*/
1915 }
1916
1917
1918 /**********************************************************
1919  * AfsRdrQueryVol
1920  * - handle volume information requests
1921  **********************************************************/
1922 NTSTATUS AfsRdrQueryVol(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp)
1923 {
1924 FILE_FS_ATTRIBUTE_INFORMATION *infoAttr;
1925 FILE_FS_DEVICE_INFORMATION *infoDevice;
1926 FILE_FS_SIZE_INFORMATION * infoSize;
1927 FILE_FS_VOLUME_INFORMATION *infoVolume;
1928 NTSTATUS ret;
1929
1930 TRY
1931
1932 switch (IrpSp->Parameters.QueryVolume.FsInformationClass)
1933         {
1934         case FileFsAttributeInformation:
1935                 infoAttr = (FILE_FS_ATTRIBUTE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
1936                 memset(infoAttr, 0, sizeof(FILE_FS_ATTRIBUTE_INFORMATION));
1937                 infoAttr->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_CASE_SENSITIVE_SEARCH;        //TODOTODO:?
1938                 infoAttr->MaximumComponentNameLength = 255;             // should this be 255?
1939                 ///RtlCopyMemory(infoAttr->FileSystemName, L"AFS", 2);
1940                 ///infoAttr->FileSystemNameLength = 2;
1941                 //StringCbCopyLen(infoAttr->FileSystemName, IrpSp->Parameters.QueryVolume.Length-sizeof(*infoAttr)-2, L"AFS", &infoAttr->FileSystemNameLength);
1942                 //IrpSp->Parameters.QueryVolume.Length = 0;
1943                 //Irp->IoStatus.Information = sizeof(*infoAttr) + (infoAttr->FileSystemNameLength - sizeof(WCHAR));
1944                 if (sizeof(*infoAttr) + wcslen(AFS_FS_NAME)*sizeof(wchar_t) > IrpSp->Parameters.QueryVolume.Length)
1945                         {
1946                         infoAttr->FileSystemNameLength = 0;
1947                         rpt0(("vol", "overflowing attr buffer %d", IrpSp->Parameters.QueryVolume.Length));
1948                         SYNC_FAIL2(STATUS_BUFFER_OVERFLOW, sizeof(*infoAttr));
1949                         }
1950                 else
1951                         {
1952                         infoAttr->FileSystemNameLength = wcslen(AFS_FS_NAME)*sizeof(wchar_t);
1953                         StringCbCopyW(infoAttr->FileSystemName, IrpSp->Parameters.QueryVolume.Length - sizeof(*infoAttr) + sizeof(WCHAR), AFS_FS_NAME);
1954                         SYNC_FAIL2(STATUS_SUCCESS, sizeof(*infoAttr) + (infoAttr->FileSystemNameLength - sizeof(WCHAR)));
1955                         }               
1956                 break;
1957
1958         case FileFsDeviceInformation:
1959                 infoDevice = (FILE_FS_DEVICE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
1960                 memset(infoDevice, 0, sizeof(FILE_FS_DEVICE_INFORMATION));
1961                 infoDevice->DeviceType = FILE_DEVICE_DISK;//DeviceObject->DeviceType;// FILE_DEVICE_NETWORK_FILE_SYSTEM;
1962                 infoDevice->Characteristics = DeviceObject->Characteristics;//FILE_DEVICE_IS_MOUNTED /*| FILE_REMOTE_DEVICE*/;          // remote device?
1963                 IrpSp->Parameters.QueryVolume.Length = sizeof(*infoDevice);
1964                 SYNC_FAIL2(STATUS_SUCCESS, IrpSp->Parameters.QueryVolume.Length);
1965                 break;
1966
1967         case FileFsSizeInformation:
1968                 infoSize = (FILE_FS_SIZE_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
1969                 memset(infoSize, 0, sizeof(FILE_FS_SIZE_INFORMATION));
1970                 infoSize->TotalAllocationUnits.QuadPart =               0x00000000F0000000;             //FIX
1971                 infoSize->AvailableAllocationUnits.QuadPart =   0x00000000E0000000;
1972                 infoSize->SectorsPerAllocationUnit = 1;
1973                 infoSize->BytesPerSector = 1;
1974                 IrpSp->Parameters.QueryVolume.Length = sizeof(*infoSize);
1975                 SYNC_FAIL2(STATUS_SUCCESS, IrpSp->Parameters.QueryVolume.Length);
1976                 break;
1977
1978         case FileFsVolumeInformation:
1979                 infoVolume = (FILE_FS_VOLUME_INFORMATION*)Irp->AssociatedIrp.SystemBuffer;
1980                 memset(infoVolume, 0, sizeof(FILE_FS_VOLUME_INFORMATION));
1981                 infoVolume->VolumeCreationTime.QuadPart = AfsTimeToWindowsTime(1080000000);//0x43218765);               //TODO:fix
1982                 infoVolume->VolumeSerialNumber = 0x12345678;                            //TODO:fix
1983                 infoVolume->SupportsObjects = FALSE;
1984                 //StringCbCopyLen(infoVolume->VolumeLabel, IrpSp->Parameters.QueryVolume.Length-sizeof(*infoVolume)-2, L"AfsRed", &infoVolume->VolumeLabelLength);
1985                 //IrpSp->Parameters.QueryVolume.Length = 0;
1986                 if (sizeof(*infoVolume) + 12 > IrpSp->Parameters.QueryVolume.Length)
1987                         {
1988                         infoVolume->VolumeLabelLength = 0;
1989                         rpt0(("vol", "overflowing buffer %d", IrpSp->Parameters.QueryVolume.Length));
1990                         SYNC_FAIL2(STATUS_BUFFER_OVERFLOW, sizeof(*infoVolume));
1991                         }
1992                 else
1993                         {
1994                         infoVolume->VolumeLabelLength = 12;
1995                         RtlCopyMemory(infoVolume->VolumeLabel, L"AfsRed", 12);
1996                         SYNC_FAIL2(STATUS_SUCCESS, sizeof(*infoVolume) + (infoVolume->VolumeLabelLength - sizeof(WCHAR)));
1997                         }               
1998                 break;
1999         //case FileFsFullSizeInformation:
2000                 //TODO:
2001         }
2002
2003 EXCEPT(STATUS_UNSUCCESSFUL, 0);
2004
2005 rpt0(("vol", "vol class %d unknown", IrpSp->Parameters.QueryVolume.FsInformationClass));
2006 SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
2007 }
2008
2009 VOID AfsRdrUnload(DRIVER_OBJECT *DriverObject)
2010 {
2011 UNICODE_STRING userModeName;
2012
2013 FsRtlNotifyUninitializeSync(&rdrExt->notifyList);
2014
2015 RtlInitUnicodeString(&userModeName, L"\\DosDevices\\afscom");
2016 IoDeleteSymbolicLink(&userModeName);
2017
2018 /*RtlInitUnicodeString(&userModeName, L"\\DosDevices\\T:");
2019 IoDeleteSymbolicLink(&userModeName);*/
2020
2021 ExDeleteNPagedLookasideList(&rdrExt->fcbMemList);
2022 ExDeleteNPagedLookasideList(&rdrExt->ccbMemList);
2023
2024 rpc_shutdown();
2025
2026 IoDeleteDevice(ComDevice);
2027 IoDeleteDevice(RdrDevice);
2028
2029 #ifdef RPT_ENA
2030 rptCliClose(REPORT);
2031 #endif
2032
2033 KdPrint(("RdrUnload exiting.\n"));
2034 }
2035
2036
2037 // handles all non-handled irp's synchronously
2038 NTSTATUS AfsRdrNull(DEVICE_OBJECT *DeviceObject, IRP *Irp, IO_STACK_LOCATION *IrpSp)
2039 {
2040 NTSTATUS ret;
2041
2042 /*TRY
2043 rpt0(("kunhand", IrpMjFuncDesc[IrpSp->MajorFunction]));*/
2044
2045 SYNC_FAIL(STATUS_NOT_IMPLEMENTED);
2046
2047 /*EXCEPT(STATUS_UNSUCCESSFUL, 0);
2048
2049 ret = Irp->IoStatus.Status;
2050 COMPLETE_NO_BOOST;
2051 return ret;*/
2052 }
2053
2054 NTSTATUS ComDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
2055 {
2056 IO_STACK_LOCATION *IrpSp, *IrpSpClient;
2057 NTSTATUS ret;
2058 struct ComExtension *ext;
2059 void *ptr, *ptr2;
2060 rpc_t find, *find_ptr;
2061 LARGE_INTEGER timeout;
2062 struct afsFcb *fcb;
2063 rpc_t *rpc, **rpcp;
2064 ULONG len;
2065 ULONG code, read;
2066 PACCESS_TOKEN acc_token;
2067
2068 ext = (struct ComExtension *)DeviceObject->DeviceExtension;
2069 IrpSp = IoGetCurrentIrpStackLocation(Irp);
2070
2071 switch (IrpSp->MajorFunction)
2072         {
2073         case IRP_MJ_CREATE:
2074                 IrpSp->FileObject->FsContext = 0;
2075                 IrpSp->FileObject->FsContext2 = 0;
2076                 if (IrpSp->FileObject->FileName.Length)
2077                         {
2078                         /* ioctls come from fs, vos, bos, etc. using a pre-existing interface */
2079                         /* downcalls come from afsd, using a new interface */
2080                         /* upcall hooks come from afsd */
2081                         if (!wcscmp(IrpSp->FileObject->FileName.Buffer, L"\\ioctl"))
2082                                 IrpSp->FileObject->FsContext2 = COMM_IOCTL;
2083                         else if (!wcscmp(IrpSp->FileObject->FileName.Buffer, L"\\downcall"))
2084                                 IrpSp->FileObject->FsContext2 = COMM_DOWNCALL;
2085                         else if (!wcscmp(IrpSp->FileObject->FileName.Buffer, L"\\upcallhook"))
2086                                 IrpSp->FileObject->FsContext2 = COMM_UPCALLHOOK;
2087                         }
2088                 if (!IrpSp->FileObject->FsContext2)
2089                         SYNC_FAIL2(STATUS_INVALID_DEVICE_REQUEST, 0);
2090
2091                 acc_token = SeQuerySubjectContextToken(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
2092                 ASSERT(acc_token);
2093                 /* SeQueryAuthenticationIdToken */
2094                 IrpSp->FileObject->FsContext = acc_token;
2095                 STATUS(STATUS_SUCCESS, FILE_OPENED);
2096                 break;
2097
2098         case IRP_MJ_CLEANUP:
2099                 /* acc_token does not have to be released */
2100         case IRP_MJ_CLOSE:
2101                 STATUS(STATUS_SUCCESS, 0);
2102                 break;
2103
2104         case IRP_MJ_WRITE:
2105                 /* we only process MDL writes */
2106                 //_asm int 3;
2107                 if (!Irp->MdlAddress ||
2108                         !(ptr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)))     /* should be LowPagePriority */
2109                         SYNC_FAIL(STATUS_INSUFFICIENT_RESOURCES);
2110
2111                 if (!IrpSp->FileObject->FsContext ||
2112                         !IrpSp->FileObject->FsContext2)
2113                         SYNC_FAIL(STATUS_INVALID_HANDLE);
2114
2115                 if (IrpSp->FileObject->FsContext2 == COMM_UPCALLHOOK)
2116                         {
2117                         rpc_recv(ptr, IrpSp->Parameters.Write.Length);
2118                         STATUS(STATUS_SUCCESS, IrpSp->Parameters.Write.Length);
2119                         }
2120                 else
2121                         STATUS(STATUS_INVALID_DEVICE_REQUEST, 0);
2122                 break;
2123         case IRP_MJ_READ:
2124                 if (!Irp->MdlAddress || !(ptr = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority)))     // should be LowPagePriority
2125                         _asm int 3;
2126
2127                 if (IrpSp->FileObject->FsContext2 == COMM_UPCALLHOOK)
2128                         {
2129                         /*timeout.QuadPart = -10000000L;*/
2130                         timeout.QuadPart = -100000000L;
2131                         KeWaitForSingleObject(&comExt->outEvent, Executive, KernelMode, FALSE, &timeout);
2132
2133                         if (!rpc_send(ptr, IrpSp->Parameters.Read.Length, &read))
2134                                 {
2135                                 KeClearEvent(&comExt->outEvent);
2136                                 KeWaitForSingleObject(&comExt->outEvent, Executive, KernelMode/*UserMode*/, FALSE, &timeout);
2137                                 if (!rpc_send(ptr, IrpSp->Parameters.Read.Length, &read))
2138                                         {
2139                                         KeClearEvent(&comExt->outEvent);
2140                                         SYNC_FAIL(STATUS_UNSUCCESSFUL);
2141                                         }
2142                                 }
2143                         SYNC_FAIL2(STATUS_SUCCESS, read);
2144                         }
2145                 else
2146                         STATUS(STATUS_INVALID_DEVICE_REQUEST, 0);
2147                 break;
2148         case IRP_MJ_DEVICE_CONTROL:
2149                 return AfsRdrDeviceControl(DeviceObject, Irp, IrpSp, NULL);
2150         default:
2151                 STATUS(STATUS_INVALID_DEVICE_REQUEST, 0);
2152                 break;
2153         }
2154
2155 ret = Irp->IoStatus.Status;
2156 COMPLETE;
2157 return ret;
2158 }
2159
2160
2161 // handles all irp's for primary (fs) device
2162 NTSTATUS Dispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp)
2163 {
2164 IO_STACK_LOCATION *IrpSp;
2165 NTSTATUS ret;
2166 afs_fcb_t *fcb;
2167 afs_ccb_t *ccb;
2168
2169 if (DeviceObject->DeviceType == FILE_DEVICE_DATALINK)
2170         return ComDispatch(DeviceObject, Irp);
2171
2172 IrpSp = IoGetCurrentIrpStackLocation(Irp);
2173
2174 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));
2175
2176 fcb = IrpSp->FileObject->FsContext;//FindFcb(IrpSp->FileObject);
2177 if (IrpSp->MajorFunction != IRP_MJ_CREATE)
2178         ASSERT(fcb);
2179
2180 if (IrpSp->FileObject && IrpSp->FileObject->FsContext2)
2181         {
2182         ccb = IrpSp->FileObject->FsContext2;
2183         rpc_set_context(ccb->token);
2184         }
2185
2186 switch (IrpSp->MajorFunction)
2187         {
2188         case IRP_MJ_CREATE:
2189                 ret = AfsRdrCreate(DeviceObject, Irp, IrpSp, NULL);                     break;
2190         case IRP_MJ_DIRECTORY_CONTROL:
2191                 ret = AfsRdrDirCtrl(DeviceObject, Irp, IrpSp, fcb);                     break;
2192         case IRP_MJ_READ:
2193                 ret = AfsRdrRead(DeviceObject, Irp, IrpSp, fcb);                        break;
2194         case IRP_MJ_WRITE:
2195                 ret = AfsRdrWrite(DeviceObject, Irp, IrpSp, fcb);                       break;
2196         case IRP_MJ_CLOSE:
2197                 ret = AfsRdrClose(DeviceObject, Irp, IrpSp, fcb);                       break;
2198         case IRP_MJ_QUERY_INFORMATION:
2199                 ret = AfsRdrQueryInfo(DeviceObject, Irp, IrpSp, fcb);           break;
2200         case IRP_MJ_DEVICE_CONTROL:
2201                 ret = AfsRdrDeviceControl(DeviceObject, Irp, IrpSp, fcb);       break;
2202         case IRP_MJ_CLEANUP:
2203                 ret = AfsRdrCleanup(DeviceObject, Irp, IrpSp, fcb);                     break;
2204         case IRP_MJ_LOCK_CONTROL:
2205                 ret = AfsRdrLockCtrl(DeviceObject, Irp, IrpSp, fcb);            break;
2206         case IRP_MJ_QUERY_VOLUME_INFORMATION:
2207                 ret = AfsRdrQueryVol(DeviceObject, Irp, IrpSp);                         break;
2208         case IRP_MJ_SHUTDOWN:
2209                 ret = AfsRdrShutdown(DeviceObject, Irp, IrpSp);                         break;
2210         case IRP_MJ_FILE_SYSTEM_CONTROL:
2211                 if (IrpSp->MinorFunction == IRP_MN_USER_FS_REQUEST &&
2212                         (IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_1 ||
2213                          IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2 ||
2214                          IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK ||
2215                          IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK))
2216                         STATUS(STATUS_OPLOCK_NOT_GRANTED, 0);
2217                 else
2218                         STATUS(STATUS_INVALID_DEVICE_REQUEST/*STATUS_NOT_IMPLEMENTED*//*STATUS_INVALID_PARAMETER*/, 0);
2219                 ret = Irp->IoStatus.Status;
2220                 goto complete;
2221         case IRP_MJ_SET_INFORMATION:
2222                 ret = AfsRdrSetInfo(DeviceObject, Irp, IrpSp, fcb);                     break;
2223         case IRP_MJ_FLUSH_BUFFERS:
2224                 ret = AfsRdrFlushFile(DeviceObject, Irp, IrpSp, fcb);           break;
2225         default:
2226                 ret = AfsRdrNull(DeviceObject, Irp, IrpSp);                                     break;
2227         }
2228 rpc_remove_context();
2229 return ret;
2230
2231 complete:
2232 rpc_remove_context();
2233 COMPLETE;
2234 return ret;
2235 }
2236
2237 BOOLEAN
2238 fastIoRead (
2239     IN struct _FILE_OBJECT *FileObject,
2240     IN PLARGE_INTEGER FileOffset,
2241     IN ULONG Length,
2242     IN BOOLEAN Wait,
2243     IN ULONG LockKey,
2244     OUT PVOID Buffer,
2245     OUT PIO_STATUS_BLOCK IoStatus,
2246     IN struct _DEVICE_OBJECT *DeviceObject
2247     )
2248 {
2249 BOOLEAN ret;
2250 ULONG adj_len;
2251 afs_fcb_t *fcb;
2252
2253 fcb = FileObject->FsContext;
2254 ASSERT(fcb);
2255
2256 FsRtlEnterFileSystem();
2257 LOCK_PAGING_FCB;
2258 adj_len = Length;
2259 if (FileOffset->QuadPart > fcb->FileSize.QuadPart)
2260         {
2261         UNLOCK_PAGING_FCB;
2262         FsRtlExitFileSystem();
2263         IoStatus->Status = STATUS_END_OF_FILE;
2264         IoStatus->Information = 0;
2265         return TRUE;
2266         }
2267 if (FileOffset->QuadPart + Length > fcb->FileSize.QuadPart)
2268         adj_len = (ULONG)(fcb->FileSize.QuadPart - FileOffset->QuadPart);
2269
2270 try
2271         {
2272         ret = CcCopyRead(FileObject, FileOffset, adj_len, Wait, Buffer, IoStatus);
2273         /*if (IoStatus->Status == STATUS_SUCCESS &&
2274                 (adj_len < Length))
2275                 IoStatus->Status = STATUS_END_OF_FILE;*/
2276 //      KdPrint(("read  %x at %x fast done %x\n", Length, (ULONG)FileOffset->QuadPart, IoStatus->Information));
2277         FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
2278         UNLOCK_PAGING_FCB;
2279         FsRtlExitFileSystem();
2280         }
2281 except (EXCEPTION_EXECUTE_HANDLER)
2282         {
2283         UNLOCK_PAGING_FCB;
2284         FsRtlExitFileSystem();
2285         return FALSE;
2286         }
2287 return ret;
2288 }
2289
2290 BOOLEAN
2291 fastIoWrite (
2292     IN struct _FILE_OBJECT *FileObject,
2293     IN PLARGE_INTEGER FileOffset,
2294     IN ULONG Length,
2295     IN BOOLEAN Wait,
2296     IN ULONG LockKey,
2297     OUT PVOID Buffer,
2298     OUT PIO_STATUS_BLOCK IoStatus,
2299     IN struct _DEVICE_OBJECT *DeviceObject
2300     )
2301 {
2302 BOOLEAN ret;
2303 LARGE_INTEGER adj_end;
2304 afs_fcb_t *fcb;
2305
2306 fcb = FileObject->FsContext;
2307 ASSERT(fcb);
2308
2309 FsRtlEnterFileSystem();
2310 LOCK_PAGING_FCB;
2311
2312 if (FileOffset->QuadPart + Length > fcb->FileSize.QuadPart)
2313         {
2314         adj_end.QuadPart = fcb->FileSize.QuadPart + Length;
2315         fcb->AllocationSize = fcb->FileSize = fcb->ValidDataLength = adj_end;
2316         LOCK_FCB;
2317         try
2318                 {
2319                 CcSetFileSizes(FileObject, (CC_FILE_SIZES*)&fcb->AllocationSize);
2320                 }
2321         except (EXCEPTION_EXECUTE_HANDLER)
2322                 {
2323                 UNLOCK_FCB;
2324                 UNLOCK_PAGING_FCB;
2325                 FsRtlExitFileSystem();
2326                 return FALSE;
2327                 }
2328         UNLOCK_FCB;
2329         }
2330
2331 try
2332         {
2333         ret = CcCopyWrite(FileObject, FileOffset, Length, Wait, Buffer);
2334         IoStatus->Status = ret?STATUS_SUCCESS:STATUS_UNSUCCESSFUL;
2335         IoStatus->Information = ret?Length:0;
2336 //      KdPrint(("write %x at %x fast done\n", Length, (ULONG)FileOffset->QuadPart));
2337         FileObject->CurrentByteOffset.QuadPart += IoStatus->Information;
2338         UNLOCK_PAGING_FCB;
2339         FsRtlExitFileSystem();
2340         }
2341 except (EXCEPTION_EXECUTE_HANDLER)
2342         {
2343         UNLOCK_PAGING_FCB;
2344         FsRtlExitFileSystem();
2345         return FALSE;
2346         }
2347 return ret;
2348 }
2349
2350 RTL_GENERIC_COMPARE_RESULTS FcbCompareRoutine(struct _RTL_GENERIC_TABLE *Table, PVOID FirstStruct, PVOID SecondStruct)
2351         {
2352         afs_fcb_t *p1, *p2;
2353
2354         p1 = (void*)*(afs_fcb_t**)FirstStruct;  p2 = (void*)*(afs_fcb_t**)SecondStruct;
2355         if (p1->fid < p2->fid)
2356                 return GenericLessThan;
2357         if (p1->fid > p2->fid)
2358                 return GenericGreaterThan;
2359         return GenericEqual;
2360         }
2361
2362 RTL_GENERIC_COMPARE_RESULTS ReqCompareRoutine(struct _RTL_GENERIC_TABLE *Table, PVOID FirstStruct, PVOID SecondStruct)
2363         {
2364         rpc_t *p1, *p2;
2365
2366         p1 = *(rpc_t**)FirstStruct;  p2 = *(rpc_t**)SecondStruct;
2367         if (p1->key < p2->key)
2368                 return GenericLessThan;
2369         if (p1->key > p2->key)
2370                 return GenericGreaterThan;
2371         return GenericEqual;
2372         }
2373
2374 PVOID AllocateRoutine(struct _RTL_GENERIC_TABLE *Table, CLONG  ByteSize)
2375         {
2376         PVOID ret;
2377         ret = ExAllocatePoolWithTag(NonPagedPool, ByteSize, AFS_RDR_TAG);
2378         ASSERT(ret);
2379         RtlZeroMemory(ret, ByteSize);
2380         return ret;
2381         }
2382
2383 VOID FreeRoutine(struct _RTL_GENERIC_TABLE *Table, PVOID Buffer)
2384         {
2385         ExFreePoolWithTag(Buffer, AFS_RDR_TAG);
2386         }
2387
2388 //KSPIN_LOCK rpc_lock;
2389 //KIRQL irql;
2390 FAST_MUTEX rpc_lock;
2391
2392 void ifs_lock_rpcs()
2393 {
2394 ExAcquireFastMutex(&rpc_lock);
2395 //KeAcquireSpinLock(&rpc_lock, &irql);
2396 }
2397
2398 void ifs_unlock_rpcs()
2399 {
2400 ExReleaseFastMutex(&rpc_lock);
2401 //KeReleaseSpinLock(&rpc_lock, irql);
2402 }
2403
2404 NTSTATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
2405 {
2406 NTSTATUS err;
2407 UNICODE_STRING rdrName, comName, userModeName, userModeCom;
2408 int x;
2409 IO_STATUS_BLOCK status;
2410 FAST_IO_DISPATCH *fastIoDispatch;
2411
2412 //_asm int 3;
2413
2414 //try {
2415 #ifdef RPT_ENA
2416 REPORT = rptOpen(NULL, "afskern");
2417 #endif
2418 rpt0(("init", "rpt initialized at %x", REPORT));
2419
2420 RtlInitUnicodeString(&rdrName, L"\\Device\\afsrdr");
2421 RtlInitUnicodeString(&comName, L"\\Device\\afscom");
2422
2423 rpt0(("init", "kern initializing"));
2424 //KeInitializeSpinLock(&rpc_lock);
2425 ExInitializeFastMutex(&rpc_lock);
2426
2427 IoAllocateDriverObjectExtension(DriverObject, (void *)0x394389f7, sizeof(FAST_IO_DISPATCH), &fastIoDispatch);
2428 RtlZeroMemory(fastIoDispatch, sizeof(FAST_IO_DISPATCH));
2429 fastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
2430 fastIoDispatch->FastIoRead = fastIoRead;
2431 fastIoDispatch->FastIoWrite = fastIoWrite;
2432 DriverObject->FastIoDispatch = fastIoDispatch;
2433
2434 for (x = 0; x < IRP_MJ_MAXIMUM_FUNCTION; x++)
2435         DriverObject->MajorFunction[x] = Dispatch;
2436 DriverObject->DriverUnload = AfsRdrUnload;
2437
2438 err = IoCreateDevice(DriverObject, sizeof(struct AfsRdrExtension)*2, &rdrName, FILE_DEVICE_NETWORK_FILE_SYSTEM, /*FILE_REMOTE_DEVICE*/0, FALSE, &RdrDevice);
2439 if (!NT_SUCCESS(STATUS_SUCCESS))
2440         return STATUS_UNSUCCESSFUL;
2441 err = IoCreateDevice(DriverObject, sizeof(struct ComExtension)*2, &comName, FILE_DEVICE_DATALINK, 0, FALSE, &ComDevice);
2442 if (!NT_SUCCESS(STATUS_SUCCESS))
2443         return STATUS_UNSUCCESSFUL;
2444
2445 RdrDevice->Flags |= DO_DIRECT_IO;
2446 RdrDevice->StackSize = 5;                                       /* could this be zero? */
2447 rdrExt = ((struct AfsRdrExtension*)RdrDevice->DeviceExtension);
2448 RtlZeroMemory(rdrExt, sizeof(struct AfsRdrExtension));
2449
2450 /* could raise exception */
2451 FsRtlNotifyInitializeSync(&rdrExt->notifyList);
2452 InitializeListHead(&rdrExt->listHead);
2453
2454 rdrExt->callbacks.AcquireForLazyWrite = lazyWriteLock;
2455 rdrExt->callbacks.ReleaseFromLazyWrite = lazyWriteUnlock;
2456 rdrExt->callbacks.AcquireForReadAhead = readAheadLock;
2457 rdrExt->callbacks.ReleaseFromReadAhead = readAheadUnlock;
2458 ExInitializeNPagedLookasideList(&rdrExt->fcbMemList, NULL, NULL, 0, sizeof(afs_fcb_t), AFS_RDR_TAG, 0);
2459 ExInitializeNPagedLookasideList(&rdrExt->ccbMemList, NULL, NULL, 0, sizeof(afs_ccb_t), AFS_RDR_TAG, 0);
2460 ExInitializeFastMutex(&rdrExt->fcbLock);
2461 RtlInitializeGenericTable(&rdrExt->fcbTable, FcbCompareRoutine, AllocateRoutine, FreeRoutine, NULL);
2462
2463
2464 ComDevice->Flags |= DO_DIRECT_IO;
2465 ComDevice->StackSize = 5;                                       // ??
2466 comExt = ((struct ComExtension*)ComDevice->DeviceExtension);
2467 RtlZeroMemory(comExt, sizeof(struct ComExtension));
2468
2469 //ExInitializeNPagedLookasideList(&comExt->outMemList, NULL, NULL, 0, sizeof(struct KOutEntry)+100, AFS_RDR_TAG, 0);
2470 InitializeListHead(&comExt->outReqList);
2471 KeInitializeSpinLock(&comExt->outLock);
2472 ExInitializeFastMutex(&comExt->inLock);
2473 RtlInitializeGenericTable(&comExt->inTable, ReqCompareRoutine, AllocateRoutine, FreeRoutine, NULL);
2474 KeInitializeEvent(&comExt->outEvent, NotificationEvent, TRUE);
2475 KeInitializeEvent(&comExt->cancelEvent, NotificationEvent, TRUE);
2476
2477 comExt->rdr = rdrExt;
2478 rdrExt->com = comExt;
2479
2480 RtlInitUnicodeString(&userModeCom, L"\\DosDevices\\afscom");
2481 err = IoCreateSymbolicLink(&userModeCom, &comName);
2482
2483 /*RtlInitUnicodeString(&rdrName, L"\\Device\\afsrdr\\1\\CITI.UMICH.EDU");
2484 RtlInitUnicodeString(&userModeName, L"\\DosDevices\\W:");
2485 err = IoCreateSymbolicLink(&userModeName, &rdrName);*/
2486
2487 /*} except(EXCEPTION_EXECUTE_HANDLER)
2488         {
2489         _asm int 3;
2490         //logerror();
2491         return -1;
2492         }*/
2493
2494 KdPrint(("DriverEntry exiting.\n"));
2495 return STATUS_SUCCESS;
2496 }