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