Something went wrong. Try again.
Reactos
Something went wrong. Try again.
36 kB · 1196 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197////////////////////////////////////////////////////////////////////// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine// All rights reserved// This file was released under the GPLv2 on June 2015./////////////////////////////////////////////////////////////////////*************************************************************************** File: Fastio.cpp** Module: UDF File System Driver (Kernel mode execution only)** Description:* Contains code to handle the various "fast-io" calls.**************************************************************************/
#include "udffs.h"
// define the file specific bug-check id#define UDF_BUG_CHECK_ID UDF_FILE_FAST_IO
/*************************************************************************** Function: UDFFastIoCheckIfPossible()** Description:* To fast-io or not to fast-io, that is the question ...* This routine helps the I/O Manager determine whether the FSD wishes* to permit fast-io on a specific file stream.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE**************************************************************************/BOOLEANNTAPIUDFFastIoCheckIfPossible( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN BOOLEAN CheckForReadOperation, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ){ BOOLEAN ReturnedStatus = FALSE; PtrUDFFCB Fcb = NULL; PtrUDFCCB Ccb = NULL; LARGE_INTEGER IoLength;
// Obtain a pointer to the FCB and CCB for the file stream. Ccb = (PtrUDFCCB)(FileObject->FsContext2); ASSERT(Ccb); Fcb = Ccb->Fcb; ASSERT(Fcb);
// Validate that this is a fast-IO request to a regular file. // The UDF FSD for example, will not allow fast-IO requests // to volume objects, or to directories. if ((Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) || (Fcb->FCBFlags & UDF_FCB_DIRECTORY)) { // This is not allowed. IoStatus->Status = STATUS_INVALID_PARAMETER; MmPrint((" UDFFastIoCheckIfPossible() TRUE, Failed\n")); return FALSE; }/* // back pressure for very smart and fast system cache ;) if(Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) { AdPrint((" Verify queue overflow -> UDFFastIoCheckIfPossible() = FALSE\n")); return FALSE; }*/ IoLength.QuadPart = Length;
// The FSD can determine the checks that it needs to perform. // Typically, a FSD will check whether there exist any byte-range // locks that would prevent a fast-IO operation from proceeding.
// ... (FSD specific checks go here).
if (CheckForReadOperation) { // The following routine is exported by the FSRTL // package and it returns TRUE if the read operation should be // allowed to proceed based on the status of the current byte-range // locks on the file stream. If we do not use the FSRTL package // for byte-range locking support, then we must substitute our // own checks over here. ReturnedStatus = FsRtlFastCheckLockForRead(&(Fcb->NTRequiredFCB->FileLock), FileOffset, &IoLength, LockKey, FileObject, PsGetCurrentProcess()); } else {// if(Fcb->Vcb->VCBFlags ); // This is a write request. Invoke the FSRTL byte-range lock package // to see whether the write should be allowed to proceed. ReturnedStatus = FsRtlFastCheckLockForWrite(&(Fcb->NTRequiredFCB->FileLock), FileOffset, &IoLength, LockKey, FileObject, PsGetCurrentProcess()); }
MmPrint((" UDFFastIoCheckIfPossible() %s\n", ReturnedStatus ? "TRUE" : "FALSE")); return(ReturnedStatus);// return FALSE;
} // end UDFFastIoCheckIfPossible()
/* */FAST_IO_POSSIBLENTAPIUDFIsFastIoPossible( IN PtrUDFFCB Fcb ){ if( !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) /*|| !FsRtlOplockIsFastIoPossible(&(Fcb->Oplock))*/ ) { UDFPrint((" FastIoIsNotPossible\n")); return FastIoIsNotPossible; }/* // back pressure for very smart and fast system cache ;) if(Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) { AdPrint((" Verify queue overflow -> UDFIsFastIoPossible() = FastIoIsNotPossible\n")); return FastIoIsNotPossible; }*/ if(FsRtlAreThereCurrentFileLocks(&(Fcb->NTRequiredFCB->FileLock)) ) { UDFPrint((" FastIoIsQuestionable\n")); return FastIoIsQuestionable; } UDFPrint((" FastIoIsPossible\n")); return FastIoIsPossible;} // end UDFIsFastIoPossible()
/*************************************************************************** Function: UDFFastIoQueryBasicInfo()** Description:* Bypass the traditional IRP method to perform a query basic* information operation.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE**************************************************************************/BOOLEANNTAPIUDFFastIoQueryBasicInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ){ BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL; LONG Length = sizeof(FILE_BASIC_INFORMATION); PtrUDFFCB Fcb; PtrUDFCCB Ccb; PtrUDFNTRequiredFCB NtReqFcb = NULL; BOOLEAN MainResourceAcquired = FALSE;
FsRtlEnterFileSystem();
UDFPrint(("UDFFastIo \n")); // if the file is already opended we can satisfy this request // immediately 'cause all the data we need must be cached _SEH2_TRY {
_SEH2_TRY {
// Get the FCB and CCB pointers. Ccb = (PtrUDFCCB)(FileObject->FsContext2); ASSERT(Ccb); Fcb = Ccb->Fcb; ASSERT(Fcb); NtReqFcb = Fcb->NTRequiredFCB; //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
if (!(Fcb->FCBFlags & UDF_FCB_PAGE_FILE)) { // Acquire the MainResource shared. UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) { try_return(RC = STATUS_CANT_WAIT); } MainResourceAcquired = TRUE; }
ReturnedStatus = ((RC = UDFGetBasicInformation(FileObject, Fcb, Buffer, &Length)) == STATUS_SUCCESS);
} _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
RC = UDFExceptionHandler(PtrIrpContext, NULL);
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
} _SEH2_END;try_exit: NOTHING; } _SEH2_FINALLY { if (MainResourceAcquired) { UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); UDFReleaseResource(&(NtReqFcb->MainResource)); MainResourceAcquired = FALSE; } IoStatus->Status = RC; if(ReturnedStatus) { IoStatus->Information = sizeof(FILE_BASIC_INFORMATION); } else { IoStatus->Information = 0; } } _SEH2_END;
FsRtlExitFileSystem();
return(ReturnedStatus);} // end UDFFastIoQueryBasicInfo()
/*************************************************************************** Function: UDFFastIoQueryStdInfo()** Description:* Bypass the traditional IRP method to perform a query standard* information operation.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE**************************************************************************/BOOLEANNTAPIUDFFastIoQueryStdInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject){ BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL; LONG Length = sizeof(FILE_STANDARD_INFORMATION); PtrUDFFCB Fcb; PtrUDFCCB Ccb;// PtrUDFNTRequiredFCB NtReqFcb = NULL;// BOOLEAN MainResourceAcquired = FALSE;
FsRtlEnterFileSystem();
UDFPrint(("UDFFastIo \n")); // if the file is already opended we can satisfy this request // immediately 'cause all the data we need must be cached _SEH2_TRY {
_SEH2_TRY {
// Get the FCB and CCB pointers. Ccb = (PtrUDFCCB)(FileObject->FsContext2); ASSERT(Ccb); Fcb = Ccb->Fcb; ASSERT(Fcb);// NtReqFcb = Fcb->NTRequiredFCB; //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
/* if (!(Fcb->FCBFlags & UDF_FCB_PAGE_FILE)) { // Acquire the MainResource shared. UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) { try_return(RC = STATUS_CANT_WAIT); } MainResourceAcquired = TRUE; }*/ ReturnedStatus = ((RC = UDFGetStandardInformation(Fcb, Buffer, &Length)) == STATUS_SUCCESS);
} _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
RC = UDFExceptionHandler(PtrIrpContext, NULL);
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
} _SEH2_END;//try_exit: NOTHING; } _SEH2_FINALLY {/* if (MainResourceAcquired) { UDFReleaseResource(&(NtReqFcb->MainResource)); MainResourceAcquired = FALSE; }*/ IoStatus->Status = RC; if(ReturnedStatus) { IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION); } else { IoStatus->Information = 0; } } _SEH2_END;
FsRtlExitFileSystem();
return(ReturnedStatus);} // end UDFFastIoQueryStdInfo()
/*************************************************************************** Function: UDFFastIoAcqCreateSec()** Description:* Not really a fast-io operation. Used by the VMM to acquire FSD resources* before processing a file map (create section object) request.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: None (we must be prepared to handle VMM initiated calls)**************************************************************************/VOIDNTAPIUDFFastIoAcqCreateSec( IN PFILE_OBJECT FileObject ){ PtrUDFNTRequiredFCB NtReqFcb = (PtrUDFNTRequiredFCB)(FileObject->FsContext);
MmPrint((" AcqForCreateSection()\n")); // Acquire the MainResource exclusively for the file stream if(!ExIsResourceAcquiredExclusiveLite(&(NtReqFcb->MainResource)) || !ExIsResourceAcquiredExclusiveLite(&(NtReqFcb->PagingIoResource)) ) { UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); } else { MmPrint((" already acquired\n")); } UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), TRUE);
// Although this is typically not required, the UDF FSD will // also acquire the PagingIoResource exclusively at this time // to conform with the resource acquisition described in the set // file information routine. Once again though, we will probably // not need to do this. UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), TRUE); NtReqFcb->AcqSectionCount++;
return;} // end UDFFastIoAcqCreateSec()
/*************************************************************************** Function: UDFFastIoRelCreateSec()** Description:* Not really a fast-io operation. Used by the VMM to release FSD resources* after processing a file map (create section object) request.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: None**************************************************************************/VOIDNTAPIUDFFastIoRelCreateSec( IN PFILE_OBJECT FileObject){ PtrUDFNTRequiredFCB NtReqFcb = (PtrUDFNTRequiredFCB)(FileObject->FsContext);
MmPrint((" RelFromCreateSection()\n"));
NtReqFcb->AcqSectionCount--; // Release the PagingIoResource for the file stream UDFReleaseResource(&(NtReqFcb->PagingIoResource));
// Release the MainResource for the file stream UDFReleaseResource(&(NtReqFcb->MainResource));
return;} // end UDFFastIoRelCreateSec()
/*************************************************************************** Function: UDFAcqLazyWrite()** Description:* Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD* resources before performing a delayed write (write behind/lazy write)* operation.* NOTE: this function really must succeed since the Cache Manager will* typically ignore failure and continue on ...** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)**************************************************************************/BOOLEAN NTAPI UDFAcqLazyWrite( IN PVOID Context, IN BOOLEAN Wait){ // The context is whatever we passed to the Cache Manager when invoking // the CcInitializeCacheMaps() function. In the case of the UDF FSD // implementation, this context is a pointer to the NT_REQ_FCB structure. PtrUDFNTRequiredFCB NtReqFcb = (PtrUDFNTRequiredFCB)Context;
MmPrint((" UDFAcqLazyWrite()\n"));
// Acquire the PagingIoResource in the NT_REQ_FCB exclusively. Then, set the // lazy-writer thread id in the NT_REQ_FCB structure for identification // when an actual write request is received by the FSD. // Note: The lazy-writer typically always supplies WAIT set to TRUE. if (!UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), Wait)) return FALSE;
// Now, set the lazy-writer thread id. ASSERT(!(NtReqFcb->LazyWriterThreadID)); NtReqFcb->LazyWriterThreadID = HandleToUlong(PsGetCurrentThreadId());
ASSERT(IoGetTopLevelIrp() == NULL); IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
// If our FSD needs to perform some special preparations in anticipation // of receving a lazy-writer request, do so now. return TRUE;} // end UDFAcqLazyWrite()
/*************************************************************************** Function: UDFRelLazyWrite()** Description:* Not really a fast-io operation. Used by the NT Cache Mgr to release FSD* resources after performing a delayed write (write behind/lazy write)* operation.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: None**************************************************************************/VOIDNTAPIUDFRelLazyWrite( IN PVOID Context){ // The context is whatever we passed to the Cache Manager when invoking // the CcInitializeCacheMaps() function. In the case of the UDF FSD // implementation, this context is a pointer to the NT_REQ_FCB structure. PtrUDFNTRequiredFCB NtReqFcb = (PtrUDFNTRequiredFCB)Context;
MmPrint((" UDFRelLazyWrite()\n"));
// Remove the current thread-id from the NT_REQ_FCB // and release the MainResource. ASSERT((NtReqFcb->LazyWriterThreadID) == HandleToUlong(PsGetCurrentThreadId())); NtReqFcb->LazyWriterThreadID = 0;
// Release the acquired resource. UDFReleaseResource(&(NtReqFcb->PagingIoResource));
IoSetTopLevelIrp( NULL ); return;} // end UDFRelLazyWrite()
/*************************************************************************** Function: UDFAcqReadAhead()** Description:* Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD* resources before performing a read-ahead operation.* NOTE: this function really must succeed since the Cache Manager will* typically ignore failure and continue on ...** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE (Cache Manager does not tolerate FALSE well)**************************************************************************/BOOLEANNTAPIUDFAcqReadAhead( IN PVOID Context, IN BOOLEAN Wait ){ // The context is whatever we passed to the Cache Manager when invoking // the CcInitializeCacheMaps() function. In the case of the UDF FSD // implementation, this context is a pointer to the NT_REQ_FCB structure.#define NtReqFcb ((PtrUDFNTRequiredFCB)Context)
MmPrint((" AcqForReadAhead()\n"));
// Acquire the MainResource in the NT_REQ_FCB shared. // Note: The read-ahead thread typically always supplies WAIT set to TRUE. UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) return FALSE;
ASSERT(IoGetTopLevelIrp() == NULL); IoSetTopLevelIrp((PIRP)FSRTL_CACHE_TOP_LEVEL_IRP);
return TRUE;#undef NtReqFcb
} // end UDFAcqReadAhead()
/*************************************************************************** Function: UDFRelReadAhead()** Description:* Not really a fast-io operation. Used by the NT Cache Mgr to release FSD* resources after performing a read-ahead operation.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: None**************************************************************************/VOIDNTAPIUDFRelReadAhead( IN PVOID Context){ // The context is whatever we passed to the Cache Manager when invoking // the CcInitializeCacheMaps() function. In the case of the UDF FSD // implementation, this context is a pointer to the NT_REQ_FCB structure.#define NtReqFcb ((PtrUDFNTRequiredFCB)Context)
MmPrint((" RelFromReadAhead()\n"));
// Release the acquired resource. UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); UDFReleaseResource(&(NtReqFcb->MainResource));
// Of course, the FSD should undo whatever else seems appropriate at this // time. IoSetTopLevelIrp( NULL );
return;#undef NtReqFcb} // end UDFRelReadAhead()
/* the remaining are only valid under NT Version 4.0 and later */#if(_WIN32_WINNT >= 0x0400)
/*************************************************************************** Function: UDFFastIoQueryNetInfo()** Description:* Get information requested by a redirector across the network. This call* will originate from the LAN Manager server.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE**************************************************************************/BOOLEANNTAPIUDFFastIoQueryNetInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject){ BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL; LONG Length = sizeof(FILE_NETWORK_OPEN_INFORMATION); PtrUDFFCB Fcb; PtrUDFCCB Ccb; PtrUDFNTRequiredFCB NtReqFcb = NULL; BOOLEAN MainResourceAcquired = FALSE;
FsRtlEnterFileSystem();
UDFPrint(("UDFFastIo \n")); // if the file is already opended we can satisfy this request // immediately 'cause all the data we need must be cached _SEH2_TRY {
_SEH2_TRY {
// Get the FCB and CCB pointers. Ccb = (PtrUDFCCB)(FileObject->FsContext2); ASSERT(Ccb); Fcb = Ccb->Fcb; ASSERT(Fcb); NtReqFcb = Fcb->NTRequiredFCB; //Fcb->Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
if (!(Fcb->FCBFlags & UDF_FCB_PAGE_FILE)) { // Acquire the MainResource shared. UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); if (!UDFAcquireResourceShared(&(NtReqFcb->MainResource), Wait)) { try_return(RC = STATUS_CANT_WAIT); } MainResourceAcquired = TRUE; }
ReturnedStatus = ((RC = UDFGetNetworkInformation(Fcb, Buffer, &Length)) == STATUS_SUCCESS);
} _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
RC = UDFExceptionHandler(PtrIrpContext, NULL);
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
} _SEH2_END;try_exit: NOTHING; } _SEH2_FINALLY { if (MainResourceAcquired) { UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb); UDFReleaseResource(&(NtReqFcb->MainResource)); MainResourceAcquired = FALSE; } IoStatus->Status = RC; if(ReturnedStatus) { IoStatus->Information = sizeof(FILE_NETWORK_OPEN_INFORMATION); } else { IoStatus->Information = 0; } } _SEH2_END;
FsRtlExitFileSystem();
return(ReturnedStatus);
} // end UDFFastIoQueryNetInfo()
/*************************************************************************** Function: UDFFastIoMdlRead()** Description:* Bypass the traditional IRP method to perform a MDL read operation.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE**************************************************************************//*BOOLEAN UDFFastIoMdlRead(IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG LockKey,OUT PMDL* MdlChain,OUT PIO_STATUS_BLOCK IoStatus,IN PDEVICE_OBJECT DeviceObject){ BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL;
FsRtlEnterFileSystem();
_SEH2_TRY {
_SEH2_TRY {
// See description in UDFFastIoRead() before filling-in the // stub here. NOTHING;
} __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
RC = UDFExceptionHandler(PtrIrpContext, NULL);
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
}
//try_exit: NOTHING;
} _SEH2_FINALLY {
}
FsRtlExitFileSystem();
return(ReturnedStatus);}*/
/*************************************************************************** Function: UDFFastIoMdlReadComplete()** Description:* Bypass the traditional IRP method to inform the NT Cache Manager and the* FSD that the caller no longer requires the data locked in the system cache* or the MDL to stay around anymore ..** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE**************************************************************************//*BOOLEAN UDFFastIoMdlReadComplete(IN PFILE_OBJECT FileObject,OUT PMDL MdlChain,IN PDEVICE_OBJECT DeviceObject){ BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL;
FsRtlEnterFileSystem();
_SEH2_TRY {
_SEH2_TRY {
// See description in UDFFastIoRead() before filling-in the // stub here. NOTHING;
} __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
RC = UDFExceptionHandler(PtrIrpContext, NULL);
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
}
//try_exit: NOTHING;
} _SEH2_FINALLY {
}
FsRtlExitFileSystem();
return(ReturnedStatus);}*/
/*************************************************************************** Function: UDFFastIoPrepareMdlWrite()** Description:* Bypass the traditional IRP method to prepare for a MDL write operation.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE**************************************************************************//*BOOLEANUDFFastIoPrepareMdlWrite( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ){ BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL;
FsRtlEnterFileSystem();
_SEH2_TRY {
_SEH2_TRY {
// See description in UDFFastIoRead() before filling-in the // stub here. NOTHING;
} __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
RC = UDFExceptionHandler(PtrIrpContext, NULL);
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
}
//try_exit: NOTHING;
} _SEH2_FINALLY {
}
FsRtlExitFileSystem();
return(ReturnedStatus);}*/
/*************************************************************************** Function: UDFFastIoMdlWriteComplete()** Description:* Bypass the traditional IRP method to inform the NT Cache Manager and the* FSD that the caller has updated the contents of the MDL. This data can* now be asynchronously written out to secondary storage by the Cache Mgr.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: TRUE/FALSE**************************************************************************//*BOOLEAN UDFFastIoMdlWriteComplete(IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,OUT PMDL MdlChain,IN PDEVICE_OBJECT DeviceObject){ BOOLEAN ReturnedStatus = FALSE; // fast i/o failed/not allowed NTSTATUS RC = STATUS_SUCCESS; PtrUDFIrpContext PtrIrpContext = NULL;
FsRtlEnterFileSystem();
_SEH2_TRY {
_SEH2_TRY {
// See description in UDFFastIoRead() before filling-in the // stub here. NOTHING;
} __except (UDFExceptionFilter(PtrIrpContext, GetExceptionInformation())) {
RC = UDFExceptionHandler(PtrIrpContext, NULL);
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
}
//try_exit: NOTHING;
} _SEH2_FINALLY {
}
FsRtlExitFileSystem();
return(ReturnedStatus);}*/
/*************************************************************************** Function: UDFFastIoAcqModWrite()** Description:* Not really a fast-io operation. Used by the VMM to acquire FSD resources* before initiating a write operation via the Modified Page/Block Writer.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: STATUS_SUCCESS/Error (__try not to return an error, will 'ya ? :-)**************************************************************************/NTSTATUSNTAPIUDFFastIoAcqModWrite( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER EndingOffset, OUT PERESOURCE *ResourceToRelease, IN PDEVICE_OBJECT DeviceObject){ NTSTATUS RC = STATUS_SUCCESS;
FsRtlEnterFileSystem();
MmPrint((" AcqModW %I64x\n", EndingOffset->QuadPart));
#define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
// We must determine which resource(s) we would like to // acquire at this time. We know that a write is imminent; // we will probably therefore acquire appropriate resources // exclusively.
// We must first get the FCB and CCB pointers from the file object // that is passed in to this function (as an argument). Note that // the ending offset (when examined in conjunction with current valid data // length) may help us in determining the appropriate resource(s) to acquire.
// For example, if the ending offset is beyond current valid data length, // We may decide to acquire *both* the MainResource and the PagingIoResource // exclusively; otherwise, we may decide simply to acquire the PagingIoResource.
// Consult the text for more information on synchronization in FSDs.
// One final note; the VMM expects that we will return a pointer to // the resource that we acquired (single return value). This pointer // will be returned back to we in the release call (below).
if(UDFAcquireResourceShared(&(NtReqFcb->PagingIoResource), FALSE)) { if(EndingOffset->QuadPart <= NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart) { UDFReleaseResource(&(NtReqFcb->PagingIoResource)); RC = STATUS_CANT_WAIT; } else { NtReqFcb->AcqFlushCount++; (*ResourceToRelease) = &(NtReqFcb->PagingIoResource); MmPrint((" AcqModW OK\n")); } } else { RC = STATUS_CANT_WAIT; }
#undef NtReqFcb
FsRtlExitFileSystem();
return RC;} // end UDFFastIoAcqModWrite()
/*************************************************************************** Function: UDFFastIoRelModWrite()** Description:* Not really a fast-io operation. Used by the VMM to release FSD resources* after processing a modified page/block write operation.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: STATUS_SUCCESS/Error (an error returned here is really not expected!)**************************************************************************/NTSTATUSNTAPIUDFFastIoRelModWrite( IN PFILE_OBJECT FileObject, IN PERESOURCE ResourceToRelease, IN PDEVICE_OBJECT DeviceObject){ FsRtlEnterFileSystem();
MmPrint((" RelModW\n"));
#define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
// The MPW has complete the write for modified pages and therefore // wants us to release pre-acquired resource(s).
// We must undo here whatever it is that we did in the // UDFFastIoAcqModWrite() call above.
NtReqFcb->AcqFlushCount--; ASSERT(ResourceToRelease == &(NtReqFcb->PagingIoResource)); UDFReleaseResource(ResourceToRelease);
#undef NtReqFcb
FsRtlExitFileSystem();
return(STATUS_SUCCESS);} // end UDFFastIoRelModWrite()
/*************************************************************************** Function: UDFFastIoAcqCcFlush()** Description:* Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD* resources before performing a CcFlush() operation on a specific file* stream.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: STATUS_SUCCESS/Error**************************************************************************/NTSTATUSNTAPIUDFFastIoAcqCcFlush( IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject){// NTSTATUS RC = STATUS_SUCCESS;
FsRtlEnterFileSystem();
MmPrint((" AcqCcFlush\n"));
// Acquire appropriate resources that will allow correct synchronization // with a flush call (and avoid deadlock).
#define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
// UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), TRUE); UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource), TRUE);// ASSERT(!(NtReqFcb->AcqFlushCount)); NtReqFcb->AcqFlushCount++;
#undef NtReqFcb
FsRtlExitFileSystem();
return(STATUS_SUCCESS);
} // end UDFFastIoAcqCcFlush()
/*************************************************************************** Function: UDFFastIoRelCcFlush()** Description:* Not really a fast-io operation. Used by the NT Cache Mgr to acquire FSD* resources before performing a CcFlush() operation on a specific file* stream.** Expected Interrupt Level (for execution) :** IRQL_PASSIVE_LEVEL** Return Value: STATUS_SUCCESS/Error**************************************************************************/NTSTATUSNTAPIUDFFastIoRelCcFlush( IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject ){// NTSTATUS RC = STATUS_SUCCESS;
FsRtlEnterFileSystem();
MmPrint((" RelCcFlush\n"));
#define NtReqFcb ((PtrUDFNTRequiredFCB)(FileObject->FsContext))
// Release resources acquired in UDFFastIoAcqCcFlush() above.
NtReqFcb->AcqFlushCount--; UDFReleaseResource(&(NtReqFcb->PagingIoResource));// UDFReleaseResource(&(NtReqFcb->MainResource));
#undef NtReqFcb
FsRtlExitFileSystem();
return(STATUS_SUCCESS);
} // end UDFFastIoRelCcFlush()
/*BOOLEANUDFFastIoDeviceControl ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ){ switch(IoControlCode) { case FSCTL_ALLOW_EXTENDED_DASD_IO: { IoStatus->Information = 0; IoStatus->Status = STATUS_SUCCESS; break; } case FSCTL_IS_VOLUME_MOUNTED: { PtrUDFFCB Fcb; PtrUDFCCB Ccb;
Ccb = (PtrUDFCCB)(FileObject->FsContext2); Fcb = Ccb->Fcb;
if(Fcb && !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK) && !(Fcb->Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_LOCKED) ) { return FALSE; }
IoStatus->Information = 0; IoStatus->Status = STATUS_SUCCESS;
break; } default: return FALSE; } return TRUE;}*/
#endif //_WIN32_WINNT >= 0x0400
BOOLEANNTAPIUDFFastIoCopyWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ){ PtrUDFFCB Fcb = NULL; PtrUDFCCB Ccb = NULL;
// Obtain a pointer to the FCB and CCB for the file stream. Ccb = (PtrUDFCCB)(FileObject->FsContext2); ASSERT(Ccb); Fcb = Ccb->Fcb; ASSERT(Fcb);
// back pressure for very smart and fast system cache ;) if(Fcb->Vcb->VerifyCtx.QueuedCount || Fcb->Vcb->VerifyCtx.ItemCount >= UDF_MAX_VERIFY_CACHE) { AdPrint((" Verify queue overflow -> UDFFastIoCopyWrite() = FALSE\n")); return FALSE; } if(Fcb->NTRequiredFCB->SectionObject.DataSectionObject && Length >= 0x10000 && FileOffset->LowPart && !(FileOffset->LowPart & 0x00ffffff)) {
MmPrint((" no FastIo 16Mb\n")); return FALSE; } return FsRtlCopyWrite(FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject);
} // end UDFFastIoCopyWrite()