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