xref: /reactos/drivers/filesystems/cdfs/lockctrl.c (revision 84344399)
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7     LockCtrl.c
8 
9 Abstract:
10 
11     This module implements the Lock Control routines for Cdfs called
12     by the Fsd/Fsp dispatch driver.
13 
14 
15 --*/
16 
17 #include "cdprocs.h"
18 
19 //
20 //  The Bug check file id for this module
21 //
22 
23 #define BugCheckFileId                   (CDFS_BUG_CHECK_LOCKCTRL)
24 
25 #ifdef ALLOC_PRAGMA
26 #pragma alloc_text(PAGE, CdCommonLockControl)
27 #pragma alloc_text(PAGE, CdFastLock)
28 #pragma alloc_text(PAGE, CdFastUnlockAll)
29 #pragma alloc_text(PAGE, CdFastUnlockAllByKey)
30 #pragma alloc_text(PAGE, CdFastUnlockSingle)
31 #endif
32 
33 
34 NTSTATUS
35 CdCommonLockControl (
36     _Inout_ PIRP_CONTEXT IrpContext,
37     _Inout_ PIRP Irp
38     )
39 
40 /*++
41 
42 Routine Description:
43 
44     This is the common routine for Lock Control called by both the fsd and fsp
45     threads.
46 
47 Arguments:
48 
49     Irp - Supplies the Irp to process
50 
51 Return Value:
52 
53     NTSTATUS - The return status for the operation
54 
55 --*/
56 
57 {
58     NTSTATUS Status;
59     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
60 
61     TYPE_OF_OPEN TypeOfOpen;
62     PFCB Fcb;
63     PCCB Ccb;
64 
65     PAGED_CODE();
66 
67     //
68     //  Extract and decode the type of file object we're being asked to process
69     //
70 
71     TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
72 
73     //
74     //  If the file is not a user file open then we reject the request
75     //  as an invalid parameter
76     //
77 
78     if (TypeOfOpen != UserFileOpen) {
79 
80         CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
81         return STATUS_INVALID_PARAMETER;
82     }
83 
84     //
85     //  We check whether we can proceed based on the state of the file oplocks.
86     //  This call might post the irp for us.
87     //
88 
89     Status = FsRtlCheckOplock( CdGetFcbOplock(Fcb),
90                                Irp,
91                                IrpContext,
92                                (PVOID)CdOplockComplete,/* ReactOS Change: GCC "assignment from incompatible pointer type" */
93                                NULL );
94 
95     //
96     //  If we don't get success then the oplock package completed the request.
97     //
98 
99     if (Status != STATUS_SUCCESS) {
100 
101         return Status;
102     }
103 
104     //
105     //  Verify the Fcb.
106     //
107 
108     CdVerifyFcbOperation( IrpContext, Fcb );
109 
110     //
111     //  If we don't have a file lock, then get one now.
112     //
113 
114     if (Fcb->FileLock == NULL) { CdCreateFileLock( IrpContext, Fcb, TRUE ); }
115 
116     //
117     //  Now call the FsRtl routine to do the actual processing of the
118     //  Lock request
119     //
120 
121     Status = FsRtlProcessFileLock( Fcb->FileLock, Irp, NULL );
122 
123     //
124     //  Set the flag indicating if Fast I/O is possible
125     //
126 
127     CdLockFcb( IrpContext, Fcb );
128     Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
129     CdUnlockFcb( IrpContext, Fcb );
130 
131     //
132     //  Complete the request.
133     //
134 
135     CdCompleteRequest( IrpContext, NULL, Status );
136     return Status;
137 }
138 
139 
140 BOOLEAN
141 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
142 CdFastLock (
143     _In_ PFILE_OBJECT FileObject,
144     _In_ PLARGE_INTEGER FileOffset,
145     _In_ PLARGE_INTEGER Length,
146     _In_ PEPROCESS ProcessId,
147     _In_ ULONG Key,
148     _In_ BOOLEAN FailImmediately,
149     _In_ BOOLEAN ExclusiveLock,
150     _Out_ PIO_STATUS_BLOCK IoStatus,
151     _In_ PDEVICE_OBJECT DeviceObject
152     )
153 
154 /*++
155 
156 Routine Description:
157 
158     This is a call back routine for doing the fast lock call.
159 
160 Arguments:
161 
162     FileObject - Supplies the file object used in this operation
163 
164     FileOffset - Supplies the file offset used in this operation
165 
166     Length - Supplies the length used in this operation
167 
168     ProcessId - Supplies the process ID used in this operation
169 
170     Key - Supplies the key used in this operation
171 
172     FailImmediately - Indicates if the request should fail immediately
173         if the lock cannot be granted.
174 
175     ExclusiveLock - Indicates if this is a request for an exclusive or
176         shared lock
177 
178     IoStatus - Receives the Status if this operation is successful
179 
180 Return Value:
181 
182     BOOLEAN - TRUE if this operation completed and FALSE if caller
183         needs to take the long route.
184 
185 --*/
186 
187 {
188     BOOLEAN Results = FALSE;
189 
190     PFCB Fcb;
191     TYPE_OF_OPEN TypeOfOpen;
192 
193     PAGED_CODE();
194 
195     UNREFERENCED_PARAMETER( DeviceObject );
196 
197     ASSERT_FILE_OBJECT( FileObject );
198 
199     IoStatus->Information = 0;
200 
201     //
202     //  Decode the type of file object we're being asked to process and
203     //  make sure that is is only a user file open.
204     //
205 
206     TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
207 
208     if (TypeOfOpen != UserFileOpen) {
209 
210         IoStatus->Status = STATUS_INVALID_PARAMETER;
211         return TRUE;
212     }
213 
214     //
215     //  Only deal with 'good' Fcb's.
216     //
217 
218     if (!CdVerifyFcbOperation( NULL, Fcb )) {
219 
220         return FALSE;
221     }
222 
223     FsRtlEnterFileSystem();
224 
225     //
226     //  Use a try-finally to facilitate cleanup.
227     //
228 
229     _SEH2_TRY {
230 
231         //
232         //  We check whether we can proceed based on the state of the file oplocks.
233         //
234 
235         if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) {
236 
237             try_return( NOTHING );
238         }
239 
240         //
241         //  If we don't have a file lock, then get one now.
242         //
243 
244         if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) {
245 
246             try_return( NOTHING );
247         }
248 
249         //
250         //  Now call the FsRtl routine to perform the lock request.
251         //
252 
253 #ifdef _MSC_VER
254 #pragma prefast(suppress: 28159, "prefast thinks this is an obsolete routine, but it is ok for CDFS to use it")
255 #endif
256         if ((Results = FsRtlFastLock( Fcb->FileLock,
257                                       FileObject,
258                                       FileOffset,
259                                       Length,
260                                       ProcessId,
261                                       Key,
262                                       FailImmediately,
263                                       ExclusiveLock,
264                                       IoStatus,
265                                       NULL,
266                                       FALSE )) != FALSE) {
267 
268             //
269             //  Set the flag indicating if Fast I/O is questionable.  We
270             //  only change this flag if the current state is possible.
271             //  Retest again after synchronizing on the header.
272             //
273 
274             if (Fcb->IsFastIoPossible == FastIoIsPossible) {
275 
276                 CdLockFcb( NULL, Fcb );
277                 Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
278                 CdUnlockFcb( NULL, Fcb );
279             }
280         }
281 
282     try_exit:  NOTHING;
283     } _SEH2_FINALLY {
284 
285         FsRtlExitFileSystem();
286     } _SEH2_END;
287 
288     return Results;
289 }
290 
291 
292 BOOLEAN
293 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
294 CdFastUnlockSingle (
295     _In_ PFILE_OBJECT FileObject,
296     _In_ PLARGE_INTEGER FileOffset,
297     _In_ PLARGE_INTEGER Length,
298     _In_ PEPROCESS ProcessId,
299     _In_ ULONG Key,
300     _Out_ PIO_STATUS_BLOCK IoStatus,
301     _In_ PDEVICE_OBJECT DeviceObject
302     )
303 
304 /*++
305 
306 Routine Description:
307 
308     This is a call back routine for doing the fast unlock single call.
309 
310 Arguments:
311 
312     FileObject - Supplies the file object used in this operation
313 
314     FileOffset - Supplies the file offset used in this operation
315 
316     Length - Supplies the length used in this operation
317 
318     ProcessId - Supplies the process ID used in this operation
319 
320     Key - Supplies the key used in this operation
321 
322     Status - Receives the Status if this operation is successful
323 
324 Return Value:
325 
326     BOOLEAN - TRUE if this operation completed and FALSE if caller
327         needs to take the long route.
328 
329 --*/
330 
331 {
332     BOOLEAN Results = FALSE;
333     TYPE_OF_OPEN TypeOfOpen;
334     PFCB Fcb;
335 
336     PAGED_CODE();
337 
338     UNREFERENCED_PARAMETER( DeviceObject );
339 
340     IoStatus->Information = 0;
341 
342     //
343     //  Decode the type of file object we're being asked to process and
344     //  make sure that is is only a user file open.
345     //
346 
347     TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
348 
349     if (TypeOfOpen != UserFileOpen) {
350 
351         IoStatus->Status = STATUS_INVALID_PARAMETER;
352         return TRUE;
353     }
354 
355     //
356     //  Only deal with 'good' Fcb's.
357     //
358 
359     if (!CdVerifyFcbOperation( NULL, Fcb )) {
360 
361         return FALSE;
362     }
363 
364     //
365     //  If there is no lock then return immediately.
366     //
367 
368     if (Fcb->FileLock == NULL) {
369 
370         IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
371         return TRUE;
372     }
373 
374     FsRtlEnterFileSystem();
375 
376     _SEH2_TRY {
377 
378         //
379         //  We check whether we can proceed based on the state of the file oplocks.
380         //
381 
382         if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) {
383 
384             try_return( NOTHING );
385         }
386 
387         //
388         //  If we don't have a file lock, then get one now.
389         //
390 
391         if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) {
392 
393             try_return( NOTHING );
394         }
395 
396         //
397         //  Now call the FsRtl routine to do the actual processing of the
398         //  Lock request.  The call will always succeed.
399         //
400 
401         Results = TRUE;
402         IoStatus->Status = FsRtlFastUnlockSingle( Fcb->FileLock,
403                                                   FileObject,
404                                                   FileOffset,
405                                                   Length,
406                                                   ProcessId,
407                                                   Key,
408                                                   NULL,
409                                                   FALSE );
410 
411         //
412         //  Set the flag indicating if Fast I/O is possible.  We are
413         //  only concerned if there are no longer any filelocks on this
414         //  file.
415         //
416 
417         if (!FsRtlAreThereCurrentFileLocks( Fcb->FileLock ) &&
418             (Fcb->IsFastIoPossible != FastIoIsPossible)) {
419 
420             CdLockFcb( IrpContext, Fcb );
421             Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
422             CdUnlockFcb( IrpContext, Fcb );
423         }
424 
425     try_exit:  NOTHING;
426     } _SEH2_FINALLY {
427 
428         FsRtlExitFileSystem();
429     } _SEH2_END;
430 
431     return Results;
432 }
433 
434 
435 BOOLEAN
436 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
437 CdFastUnlockAll (
438     _In_ PFILE_OBJECT FileObject,
439     _In_ PEPROCESS ProcessId,
440     _Out_ PIO_STATUS_BLOCK IoStatus,
441     _In_ PDEVICE_OBJECT DeviceObject
442     )
443 
444 /*++
445 
446 Routine Description:
447 
448     This is a call back routine for doing the fast unlock all call.
449 
450 Arguments:
451 
452     FileObject - Supplies the file object used in this operation
453 
454     ProcessId - Supplies the process ID used in this operation
455 
456     Status - Receives the Status if this operation is successful
457 
458 Return Value:
459 
460     BOOLEAN - TRUE if this operation completed and FALSE if caller
461         needs to take the long route.
462 
463 --*/
464 
465 {
466     BOOLEAN Results = FALSE;
467     TYPE_OF_OPEN TypeOfOpen;
468     PFCB Fcb;
469 
470     PAGED_CODE();
471 
472     UNREFERENCED_PARAMETER( DeviceObject );
473 
474     IoStatus->Information = 0;
475 
476     //
477     //  Decode the type of file object we're being asked to process and
478     //  make sure that is is only a user file open.
479     //
480 
481     TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
482 
483     if (TypeOfOpen != UserFileOpen) {
484 
485         IoStatus->Status = STATUS_INVALID_PARAMETER;
486         return TRUE;
487     }
488 
489     //
490     //  Only deal with 'good' Fcb's.
491     //
492 
493     if (!CdVerifyFcbOperation( NULL, Fcb )) {
494 
495         return FALSE;
496     }
497 
498     //
499     //  If there is no lock then return immediately.
500     //
501 
502     if (Fcb->FileLock == NULL) {
503 
504         IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
505         return TRUE;
506     }
507 
508     FsRtlEnterFileSystem();
509 
510     _SEH2_TRY {
511 
512         //
513         //  We check whether we can proceed based on the state of the file oplocks.
514         //
515 
516         if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) {
517 
518             try_return( NOTHING );
519         }
520 
521         //
522         //  If we don't have a file lock, then get one now.
523         //
524 
525         if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) {
526 
527             try_return( NOTHING );
528         }
529 
530         //
531         //  Now call the FsRtl routine to do the actual processing of the
532         //  Lock request.  The call will always succeed.
533         //
534 
535         Results = TRUE;
536         IoStatus->Status = FsRtlFastUnlockAll( Fcb->FileLock,
537                                                FileObject,
538                                                ProcessId,
539                                                NULL );
540 
541 
542         //
543         //  Set the flag indicating if Fast I/O is possible
544         //
545 
546         CdLockFcb( IrpContext, Fcb );
547         Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
548         CdUnlockFcb( IrpContext, Fcb );
549 
550     try_exit:  NOTHING;
551     } _SEH2_FINALLY {
552 
553         FsRtlExitFileSystem();
554     } _SEH2_END;
555 
556     return Results;
557 }
558 
559 
560 BOOLEAN
561 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
562 CdFastUnlockAllByKey (
563     _In_ PFILE_OBJECT FileObject,
564     _In_ PVOID ProcessId,
565     _In_ ULONG Key,
566     _Out_ PIO_STATUS_BLOCK IoStatus,
567     _In_ PDEVICE_OBJECT DeviceObject
568     )
569 
570 /*++
571 
572 Routine Description:
573 
574     This is a call back routine for doing the fast unlock all by key call.
575 
576 Arguments:
577 
578     FileObject - Supplies the file object used in this operation
579 
580     ProcessId - Supplies the process ID used in this operation
581 
582     Key - Supplies the key used in this operation
583 
584     Status - Receives the Status if this operation is successful
585 
586 Return Value:
587 
588     BOOLEAN - TRUE if this operation completed and FALSE if caller
589         needs to take the long route.
590 
591 --*/
592 
593 {
594     BOOLEAN Results = FALSE;
595     TYPE_OF_OPEN TypeOfOpen;
596     PFCB Fcb;
597 
598     PAGED_CODE();
599 
600     UNREFERENCED_PARAMETER( DeviceObject );
601 
602     IoStatus->Information = 0;
603 
604     //
605     //  Decode the type of file object we're being asked to process and
606     //  make sure that is is only a user file open.
607     //
608 
609     TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
610 
611     if (TypeOfOpen != UserFileOpen) {
612 
613         IoStatus->Status = STATUS_INVALID_PARAMETER;
614         return TRUE;
615     }
616 
617     //
618     //  Only deal with 'good' Fcb's.
619     //
620 
621     if (!CdVerifyFcbOperation( NULL, Fcb )) {
622 
623         return FALSE;
624     }
625 
626     //
627     //  If there is no lock then return immediately.
628     //
629 
630     if (Fcb->FileLock == NULL) {
631 
632         IoStatus->Status = STATUS_RANGE_NOT_LOCKED;
633         return TRUE;
634     }
635 
636     FsRtlEnterFileSystem();
637 
638     _SEH2_TRY {
639 
640         //
641         //  We check whether we can proceed based on the state of the file oplocks.
642         //
643 
644         if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) {
645 
646             try_return( NOTHING );
647         }
648 
649         //
650         //  If we don't have a file lock, then get one now.
651         //
652 
653         if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) {
654 
655             try_return( NOTHING );
656         }
657 
658         //
659         //  Now call the FsRtl routine to do the actual processing of the
660         //  Lock request.  The call will always succeed.
661         //
662 
663         Results = TRUE;
664         IoStatus->Status = FsRtlFastUnlockAllByKey( Fcb->FileLock,
665                                                     FileObject,
666                                                     ProcessId,
667                                                     Key,
668                                                     NULL );
669 
670 
671         //
672         //  Set the flag indicating if Fast I/O is possible
673         //
674 
675         CdLockFcb( IrpContext, Fcb );
676         Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb );
677         CdUnlockFcb( IrpContext, Fcb );
678 
679     try_exit:  NOTHING;
680     } _SEH2_FINALLY {
681 
682         FsRtlExitFileSystem();
683     } _SEH2_END;
684 
685     return Results;
686 }
687 
688 
689 
690