Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880/* * COPYRIGHT: See COPYRIGHT.TXT * PROJECT: Ext2 File System Driver for WinNT/2K/XP * FILE: fsctl.c * PROGRAMMER: Matt Wu <mattwu@163.com> * HOMEPAGE: http://www.ext2fsd.com * UPDATE HISTORY: */
/* INCLUDES *****************************************************************/
#include "ext2fs.h"
/* GLOBALS ***************************************************************/
extern PEXT2_GLOBAL Ext2Global;
/* DEFINITIONS *************************************************************/
#ifdef ALLOC_PRAGMA#pragma alloc_text(PAGE, Ext2IsHandleCountZero)#pragma alloc_text(PAGE, Ext2LockVcb)#pragma alloc_text(PAGE, Ext2LockVolume)#pragma alloc_text(PAGE, Ext2UnlockVcb)#pragma alloc_text(PAGE, Ext2UnlockVolume)#pragma alloc_text(PAGE, Ext2AllowExtendedDasdIo)#pragma alloc_text(PAGE, Ext2GetRetrievalPointerBase)#pragma alloc_text(PAGE, Ext2QueryExtentMappings)#pragma alloc_text(PAGE, Ext2QueryRetrievalPointers)#pragma alloc_text(PAGE, Ext2GetRetrievalPointers)#pragma alloc_text(PAGE, Ext2UserFsRequest)#pragma alloc_text(PAGE, Ext2IsMediaWriteProtected)#pragma alloc_text(PAGE, Ext2MountVolume)#pragma alloc_text(PAGE, Ext2PurgeVolume)#pragma alloc_text(PAGE, Ext2PurgeFile)#pragma alloc_text(PAGE, Ext2DismountVolume)#pragma alloc_text(PAGE, Ext2IsVolumeMounted)#pragma alloc_text(PAGE, Ext2VerifyVolume)#pragma alloc_text(PAGE, Ext2FileSystemControl)#endif
VOIDExt2SetVpbFlag ( IN PVPB Vpb, IN USHORT Flag ){ KIRQL OldIrql;
IoAcquireVpbSpinLock(&OldIrql); Vpb->Flags |= Flag; IoReleaseVpbSpinLock(OldIrql);}
VOIDExt2ClearVpbFlag ( IN PVPB Vpb, IN USHORT Flag ){ KIRQL OldIrql;
IoAcquireVpbSpinLock(&OldIrql); Vpb->Flags &= ~Flag; IoReleaseVpbSpinLock(OldIrql);}
BOOLEANExt2IsHandleCountZero(IN PEXT2_VCB Vcb){ PEXT2_FCB Fcb; PLIST_ENTRY List;
for ( List = Vcb->FcbList.Flink; List != &Vcb->FcbList; List = List->Flink ) {
Fcb = CONTAINING_RECORD(List, EXT2_FCB, Next);
ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
DEBUG(DL_INF, ( "Ext2IsHandleCountZero: Inode:%xh File:%S OpenHandleCount=%xh\n", Fcb->Inode->i_ino, Fcb->Mcb->ShortName.Buffer, Fcb->OpenHandleCount));
if (Fcb->OpenHandleCount) { return FALSE; } }
return TRUE;}
NTSTATUSExt2LockVcb (IN PEXT2_VCB Vcb, IN PFILE_OBJECT FileObject){ NTSTATUS Status = STATUS_SUCCESS;
_SEH2_TRY {
if (FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { DEBUG(DL_INF, ( "Ext2LockVolume: Volume is already locked.\n")); Status = STATUS_ACCESS_DENIED; _SEH2_LEAVE; }
if (Vcb->OpenHandleCount > (ULONG)(FileObject ? 1 : 0)) { DEBUG(DL_INF, ( "Ext2LockVcb: There are still opened files.\n"));
Status = STATUS_ACCESS_DENIED; _SEH2_LEAVE; }
if (!Ext2IsHandleCountZero(Vcb)) { DEBUG(DL_INF, ( "Ext2LockVcb: Thare are still opened files.\n"));
Status = STATUS_ACCESS_DENIED; _SEH2_LEAVE; }
SetLongFlag(Vcb->Flags, VCB_VOLUME_LOCKED); Ext2SetVpbFlag(Vcb->Vpb, VPB_LOCKED); Vcb->LockFile = FileObject;
DEBUG(DL_INF, ( "Ext2LockVcb: Volume locked.\n"));
} _SEH2_FINALLY { // Nothing } _SEH2_END;
return Status;}
NTSTATUSExt2LockVolume (IN PEXT2_IRP_CONTEXT IrpContext){ PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT DeviceObject; PEXT2_VCB Vcb = NULL; NTSTATUS Status; BOOLEAN VcbResourceAcquired = FALSE;
_SEH2_TRY {
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Status = STATUS_UNSUCCESSFUL;
// // This request is not allowed on the main device object // if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb));
IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
#if (_WIN32_WINNT >= 0x0500) CcWaitForCurrentLazyWriterActivity();#endif ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE );
VcbResourceAcquired = TRUE;
/* flush dirty data before locking the volume */ if (!IsVcbReadOnly(Vcb)) { Ext2FlushFiles(IrpContext, Vcb, FALSE); Ext2FlushVolume(IrpContext, Vcb, FALSE); }
Status = Ext2LockVcb(Vcb, IrpSp->FileObject);
} _SEH2_FINALLY {
if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); }
if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END;
return Status;}
NTSTATUSExt2UnlockVcb ( IN PEXT2_VCB Vcb, IN PFILE_OBJECT FileObject ){ NTSTATUS Status;
_SEH2_TRY {
if (FileObject && FileObject->FsContext != Vcb) { Status = STATUS_NOT_LOCKED; _SEH2_LEAVE; }
if (!FlagOn(Vcb->Flags, VCB_VOLUME_LOCKED)) { DEBUG(DL_ERR, ( ": Ext2UnlockVcb: Volume is not locked.\n")); Status = STATUS_NOT_LOCKED; _SEH2_LEAVE; }
if (Vcb->LockFile == FileObject) { ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED); Ext2ClearVpbFlag(Vcb->Vpb, VPB_LOCKED); DEBUG(DL_INF, ( "Ext2UnlockVcb: Volume unlocked.\n")); Status = STATUS_SUCCESS; } else { Status = STATUS_NOT_LOCKED; }
} _SEH2_FINALLY { // Nothing } _SEH2_END;
return Status;}
NTSTATUSExt2UnlockVolume ( IN PEXT2_IRP_CONTEXT IrpContext){ PIO_STACK_LOCATION IrpSp = NULL; PDEVICE_OBJECT DeviceObject = NULL; PEXT2_VCB Vcb = NULL; NTSTATUS Status; BOOLEAN VcbResourceAcquired = FALSE;
_SEH2_TRY {
ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
// // This request is not allowed on the main device object // if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE ); VcbResourceAcquired = TRUE;
Status = Ext2UnlockVcb(Vcb, IrpSp->FileObject);
} _SEH2_FINALLY {
if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); }
if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END;
return Status;}
NTSTATUSExt2InvalidateVolumes ( IN PEXT2_IRP_CONTEXT IrpContext ){ NTSTATUS Status; PIRP Irp; PIO_STACK_LOCATION IrpSp;
#ifndef __REACTOS__ PVPB NewVpb = NULL;#endif HANDLE Handle; PLIST_ENTRY ListEntry;
ULONG InputLength = 0; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; BOOLEAN GlobalResourceAcquired = FALSE;
LUID Privilege = {SE_TCB_PRIVILEGE, 0};
_SEH2_TRY {
Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (!IsExt2FsDevice(IrpSp->DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; }
if (!SeSinglePrivilegeCheck(Privilege, Irp->RequestorMode)) { Status = STATUS_PRIVILEGE_NOT_HELD; _SEH2_LEAVE; }
#ifndef _GNU_NTIFS_ InputLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;#else InputLength = ((PEXTENDED_IO_STACK_LOCATION)(IrpSp))-> Parameters.FileSystemControl.InputBufferLength;#endif
#if defined(_WIN64) if (IoIs32bitProcess(Irp)) { if (InputLength != sizeof(UINT32)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Handle = (HANDLE) LongToHandle( (*(PUINT32)Irp->AssociatedIrp.SystemBuffer) ); } else#endif { if (InputLength != sizeof(HANDLE)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer; }
Status = ObReferenceObjectByHandle( Handle, 0, *IoFileObjectType, KernelMode, (void **)&FileObject, NULL );
if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } else { DeviceObject = FileObject->DeviceObject; ObDereferenceObject(FileObject); }
ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE); GlobalResourceAcquired = TRUE;
ListEntry = Ext2Global->VcbList.Flink; while (ListEntry != &Ext2Global->VcbList) {
PEXT2_VCB Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next); ListEntry = ListEntry->Flink;
DEBUG(DL_DBG, ( "Ext2InvalidateVolumes: Vcb=%xh Vcb->Vpb=%xh " "Blink = %p &Vcb->Next = %p\n", Vcb, Vcb->Vpb, ListEntry->Blink, &Vcb->Next));
if (Vcb->Vpb && (Vcb->Vpb->RealDevice == DeviceObject)) {
DEBUG(DL_DBG, ( "Ext2InvalidateVolumes: Got Vcb=%xh Vcb->Vpb=%xh " "Blink = %p &Vcb->Next = %p\n", Vcb, Vcb->Vpb, ListEntry->Blink, &Vcb->Next)); /* dismount the volume */ Ext2CheckDismount(IrpContext, Vcb, FALSE); } }
} _SEH2_FINALLY {
if (GlobalResourceAcquired) { ExReleaseResourceLite(&Ext2Global->Resource); }
if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END;
return Status;}
NTSTATUSExt2AllowExtendedDasdIo(IN PEXT2_IRP_CONTEXT IrpContext){ PIO_STACK_LOCATION IrpSp; PEXT2_VCB Vcb; PEXT2_CCB Ccb; NTSTATUS status;
IrpSp = IoGetCurrentIrpStackLocation(IrpContext->Irp);
Vcb = (PEXT2_VCB) IrpSp->FileObject->FsContext; Ccb = (PEXT2_CCB) IrpSp->FileObject->FsContext2;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb));
if (Ccb) { SetLongFlag(Ccb->Flags, CCB_ALLOW_EXTENDED_DASD_IO); status = STATUS_SUCCESS; } else { status = STATUS_INVALID_PARAMETER; }
Ext2CompleteIrpContext(IrpContext, status); return status;}
/* * Ext2OplockRequest * * oplock requests handler routine * * Arguments: * IrpContext: the ext2 irp context * * Return Value: * NTSTATUS: The return status for the operation * */
NTSTATUSExt2OplockRequest ( IN PEXT2_IRP_CONTEXT IrpContext){ NTSTATUS Status;
ULONG FsCtrlCode; PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject;
PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp; PEXTENDED_IO_STACK_LOCATION EIrpSp;
PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL;
ULONG OplockCount = 0;
BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE;
ASSERT(IrpContext);
_SEH2_TRY {
Irp = IrpContext->Irp; ASSERT(Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp); ASSERT(IrpSp); EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp;
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
// // This request is not allowed on the main device object // if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb));
FileObject = IrpContext->FileObject;
Fcb = (PEXT2_FCB) FileObject->FsContext;
// // This request is not allowed on volumes //
if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) { Status = STATUS_FILE_DELETED; _SEH2_LEAVE; }
Ccb = (PEXT2_CCB) FileObject->FsContext2; if (Ccb == NULL) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
FsCtrlCode = EIrpSp->Parameters.FileSystemControl.FsControlCode;
switch (FsCtrlCode) {
case FSCTL_REQUEST_OPLOCK_LEVEL_1: case FSCTL_REQUEST_OPLOCK_LEVEL_2: case FSCTL_REQUEST_BATCH_OPLOCK:
VcbResourceAcquired = ExAcquireResourceSharedLite( &Vcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
FcbResourceAcquired = ExAcquireResourceExclusiveLite ( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
if (FsCtrlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2) { OplockCount = (ULONG) FsRtlAreThereCurrentFileLocks(&Fcb->FileLockAnchor); } else { OplockCount = Fcb->OpenHandleCount; }
break;
case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE: case FSCTL_OPBATCH_ACK_CLOSE_PENDING : case FSCTL_OPLOCK_BREAK_NOTIFY: case FSCTL_OPLOCK_BREAK_ACK_NO_2:
FcbResourceAcquired = ExAcquireResourceSharedLite ( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT));
break;
default:
Ext2BugCheck(EXT2_BUGCHK_FSCTL, FsCtrlCode, 0, 0); }
// // Call the FsRtl routine to grant/acknowledge oplock. //
Status = FsRtlOplockFsctrl( &Fcb->Oplock, Irp, OplockCount );
// // Set the flag indicating if Fast I/O is possible //
Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); IrpContext->Irp = NULL;
} _SEH2_FINALLY {
if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); }
if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); }
if (!_SEH2_AbnormalTermination()) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END;
return Status;}
NTSTATUSExt2IsVolumeDirty ( IN PEXT2_IRP_CONTEXT IrpContext){ NTSTATUS status = STATUS_SUCCESS; PIRP Irp; PEXTENDED_IO_STACK_LOCATION IrpSp; PULONG VolumeState;
_SEH2_TRY {
Irp = IrpContext->Irp; IrpSp = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
// // Get a pointer to the output buffer. Look at the system buffer field in th // irp first. Then the Irp Mdl. //
if (Irp->AssociatedIrp.SystemBuffer != NULL) {
VolumeState = Irp->AssociatedIrp.SystemBuffer;
} else if (Irp->MdlAddress != NULL) {
VolumeState = MmGetSystemAddressForMdl( Irp->MdlAddress );
} else {
status = STATUS_INVALID_USER_BUFFER; _SEH2_LEAVE; }
if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG)) { status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
*VolumeState = 0;
} _SEH2_FINALLY {
if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, status); } } _SEH2_END;
return status;}
NTSTATUSExt2QueryExtentMappings( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_FCB Fcb, IN PLARGE_INTEGER RequestVbn, OUT PLARGE_INTEGER * pMappedRuns){ PLARGE_INTEGER MappedRuns = NULL; PLARGE_INTEGER PartialRuns = NULL;
PEXT2_EXTENT Chain = NULL; PEXT2_EXTENT Extent = NULL;
LONGLONG Vbn = 0; ULONG Length = 0; ULONG i = 0;
NTSTATUS Status = STATUS_SUCCESS;
_SEH2_TRY {
/* now building all the request extents */ while (Vbn < RequestVbn->QuadPart) {
Length = 0x80000000; /* 2g bytes */ if (RequestVbn->QuadPart < Vbn + Length) { Length = (ULONG)(RequestVbn->QuadPart - Vbn); }
/* build extents for sub-range */ Extent = NULL; Status = Ext2BuildExtents( IrpContext, Vcb, Fcb->Mcb, Vbn, Length, FALSE, &Extent);
if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
if (Chain) { Ext2JointExtents(Chain, Extent); } else { Chain = Extent; }
/* allocate extent array */ PartialRuns = Ext2AllocatePool( NonPagedPool, (Ext2CountExtents(Chain) + 2) * (2 * sizeof(LARGE_INTEGER)), 'RE2E');
if (PartialRuns == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; } RtlZeroMemory( PartialRuns, (Ext2CountExtents(Chain) + 2) * (2 * sizeof(LARGE_INTEGER)));
if (MappedRuns) { RtlMoveMemory(PartialRuns, MappedRuns, i * 2 * sizeof(LARGE_INTEGER)); Ext2FreePool(MappedRuns, 'RE2E'); } MappedRuns = PartialRuns;
/* walk all the Mcb runs in Extent */ for (; Extent != NULL; Extent = Extent->Next) { MappedRuns[i*2 + 0].QuadPart = Vbn + Extent->Offset; MappedRuns[i*2 + 1].QuadPart = Extent->Lba; i = i+1; }
Vbn = Vbn + Length; }
*pMappedRuns = MappedRuns;
} _SEH2_FINALLY {
if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) { if (MappedRuns) { Ext2FreePool(MappedRuns, 'RE2E'); } *pMappedRuns = NULL; }
if (Chain) { Ext2DestroyExtentChain(Chain); } } _SEH2_END;
return Status;}
NTSTATUSExt2QueryRetrievalPointers ( IN PEXT2_IRP_CONTEXT IrpContext){ PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp; PEXTENDED_IO_STACK_LOCATION EIrpSp;
PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject;
PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL;
PLARGE_INTEGER RequestVbn; PLARGE_INTEGER * pMappedRuns;
ULONG InputSize; ULONG OutputSize;
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN FcbResourceAcquired = FALSE;
_SEH2_TRY {
ASSERT(IrpContext); Irp = IrpContext->Irp; ASSERT(Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp); EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp; ASSERT(IrpSp);
InputSize = EIrpSp->Parameters.FileSystemControl.InputBufferLength; OutputSize = EIrpSp->Parameters.FileSystemControl.OutputBufferLength;
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
DbgBreak();
/* This request is not allowed on the main device object */ if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); ASSERT(IsMounted(Vcb));
FileObject = IrpContext->FileObject; Fcb = (PEXT2_FCB) FileObject->FsContext;
/* check Fcb is valid or not */ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) { Status = STATUS_FILE_DELETED; _SEH2_LEAVE; }
Ccb = (PEXT2_CCB) FileObject->FsContext2; if (Ccb == NULL) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
/* Is requstor in kernel and Fcb a paging file ? */ if (Irp->RequestorMode != KernelMode || !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE) || InputSize != sizeof(LARGE_INTEGER) || OutputSize != sizeof(PVOID)) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
if (!ExAcquireResourceExclusiveLite ( &Fcb->MainResource, Ext2CanIWait())) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE;
RequestVbn = EIrpSp->Parameters.FileSystemControl.Type3InputBuffer; pMappedRuns = Irp->UserBuffer;
DbgBreak();
/* request size beyonds whole file size */ if (RequestVbn->QuadPart >= Fcb->Header.AllocationSize.QuadPart) { Status = STATUS_END_OF_FILE; _SEH2_LEAVE; }
Status = Ext2QueryExtentMappings( IrpContext, Vcb, Fcb, RequestVbn, pMappedRuns );
} _SEH2_FINALLY {
if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); }
if (!_SEH2_AbnormalTermination()) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } } _SEH2_END;
return Status;}
NTSTATUSExt2GetRetrievalPointers ( IN PEXT2_IRP_CONTEXT IrpContext){ PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp; PEXTENDED_IO_STACK_LOCATION EIrpSp;
PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject;
PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL;
PSTARTING_VCN_INPUT_BUFFER SVIB; PRETRIEVAL_POINTERS_BUFFER RPSB;
PEXT2_EXTENT Chain = NULL; PEXT2_EXTENT Extent = NULL;
LONGLONG Vbn = 0; ULONG Length = 0; ULONG i = 0;
ULONG UsedSize = 0; ULONG InputSize; ULONG OutputSize;
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN FcbResourceAcquired = FALSE;
_SEH2_TRY {
ASSERT(IrpContext); Irp = IrpContext->Irp; ASSERT(Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp); EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp; ASSERT(IrpSp);
InputSize = EIrpSp->Parameters.FileSystemControl.InputBufferLength; OutputSize = EIrpSp->Parameters.FileSystemControl.OutputBufferLength;
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
/* This request is not allowed on the main device object */ if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); ASSERT(IsMounted(Vcb));
FileObject = IrpContext->FileObject; Fcb = (PEXT2_FCB) FileObject->FsContext;
/* check Fcb is valid or not */ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) { Status = STATUS_FILE_DELETED; _SEH2_LEAVE; }
Ccb = (PEXT2_CCB) FileObject->FsContext2; if (Ccb == NULL) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
if (InputSize < sizeof(STARTING_VCN_INPUT_BUFFER) || OutputSize < sizeof(RETRIEVAL_POINTERS_BUFFER) ) { Status = STATUS_BUFFER_TOO_SMALL; _SEH2_LEAVE; }
if (!ExAcquireResourceExclusiveLite ( &Fcb->MainResource, Ext2CanIWait())) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE;
SVIB = (PSTARTING_VCN_INPUT_BUFFER) EIrpSp->Parameters.FileSystemControl.Type3InputBuffer; RPSB = (PRETRIEVAL_POINTERS_BUFFER) Ext2GetUserBuffer(Irp);
/* probe user buffer */
_SEH2_TRY { if (Irp->RequestorMode != KernelMode) { ProbeForRead (SVIB, InputSize, sizeof(UCHAR)); ProbeForWrite(RPSB, OutputSize, sizeof(UCHAR)); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = STATUS_INVALID_USER_BUFFER; } _SEH2_END;
if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
UsedSize = FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER, Extents[0]);
/* request size beyonds whole file size ? */ DEBUG(DL_DBG, ("Ext2GetRetrievalPointers: Startin from Vbn: %I64xh\n", SVIB->StartingVcn.QuadPart)); Vbn = (SVIB->StartingVcn.QuadPart << BLOCK_BITS); if (Vbn >= Fcb->Header.AllocationSize.QuadPart ) { Status = STATUS_END_OF_FILE; _SEH2_LEAVE; }
/* now building all the request extents */ while (Vbn < Fcb->Header.AllocationSize.QuadPart) {
ASSERT(Chain == NULL); Length = 0x80000000; /* 2g bytes */ if (Fcb->Header.AllocationSize.QuadPart < Vbn + Length) { Length = (ULONG)(Fcb->Header.AllocationSize.QuadPart - Vbn); }
/* build extents for sub-range */ Status = Ext2BuildExtents( IrpContext, Vcb, Fcb->Mcb, Vbn, Length, FALSE, &Chain);
if (!NT_SUCCESS(Status)) { DbgBreak(); _SEH2_LEAVE; }
/* fill user buffer of RETRIEVAL_POINTERS_BUFFER */ Extent = Chain; while (Extent) {
DEBUG(DL_MAP, ("Ext2GetRetrievalPointers: %wZ %d Vbn = %I64xh Lbn = %I64xh\n", &Fcb->Mcb->FullName, i, ((Vbn + Extent->Offset) >> BLOCK_BITS), Extent->Lba));
RPSB->Extents[i].Lcn.QuadPart = (Extent->Lba >> BLOCK_BITS); RPSB->Extents[i].NextVcn.QuadPart = ((Vbn + Extent->Offset + Extent->Length) >> BLOCK_BITS); if (i == 0) { RPSB->StartingVcn.QuadPart = ((Vbn + Extent->Offset) >> BLOCK_BITS); } else { ASSERT(RPSB->Extents[i-1].NextVcn.QuadPart == ((Vbn + Extent->Offset) >> BLOCK_BITS)); } if (UsedSize + sizeof(RETRIEVAL_POINTERS_BUFFER) > OutputSize) { Status = STATUS_BUFFER_OVERFLOW; _SEH2_LEAVE; } UsedSize += sizeof(LARGE_INTEGER) * 2; Irp->IoStatus.Information = (ULONG_PTR)UsedSize; RPSB->ExtentCount = ++i; Extent = Extent->Next; }
if (Chain) { Ext2DestroyExtentChain(Chain); Chain = NULL; }
Vbn = Vbn + Length; }
#if 0 { NTSTATUS _s; ULONG _i = 0; LARGE_INTEGER RequestVbn = Fcb->Header.AllocationSize; PLARGE_INTEGER MappedRuns = NULL;
_s = Ext2QueryExtentMappings( IrpContext, Vcb, Fcb, &RequestVbn, &MappedRuns ); if (!NT_SUCCESS(_s) || NULL == MappedRuns) { DbgBreak(); goto exit_to_get_rps; }
while (MappedRuns[_i*2 + 0].QuadPart != 0 || MappedRuns[_i*2 + 1].QuadPart != 0 ) { DEBUG(DL_MAP, ("Ext2QueryExtentMappings: %wZ %d Vbn = %I64xh Lbn = %I64xh\n", &Fcb->Mcb->FullName, _i, MappedRuns[_i*2 + 0].QuadPart, MappedRuns[_i*2 + 1].QuadPart)); _i++; }
exit_to_get_rps:
if (MappedRuns) { Ext2FreePool(MappedRuns, 'RE2E'); } }#endif
} _SEH2_FINALLY {
if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); }
if (Chain) { Ext2DestroyExtentChain(Chain); }
if (!_SEH2_AbnormalTermination()) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } } _SEH2_END;
return Status;}
NTSTATUSExt2GetRetrievalPointerBase ( IN PEXT2_IRP_CONTEXT IrpContext){ PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp; PEXTENDED_IO_STACK_LOCATION EIrpSp;
PDEVICE_OBJECT DeviceObject; PFILE_OBJECT FileObject;
PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL;
PLARGE_INTEGER FileAreaOffset;
ULONG OutputSize;
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN FcbResourceAcquired = FALSE;
_SEH2_TRY {
ASSERT(IrpContext); Irp = IrpContext->Irp; ASSERT(Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp); EIrpSp = (PEXTENDED_IO_STACK_LOCATION)IrpSp; ASSERT(IrpSp);
OutputSize = EIrpSp->Parameters.FileSystemControl.OutputBufferLength;
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
/* This request is not allowed on the main device object */ if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB))); ASSERT(IsMounted(Vcb));
FileObject = IrpContext->FileObject; Fcb = (PEXT2_FCB) FileObject->FsContext;
/* check Fcb is valid or not */ if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
if (IsFlagOn(Fcb->Mcb->Flags, MCB_FILE_DELETED)) { Status = STATUS_FILE_DELETED; _SEH2_LEAVE; }
Ccb = (PEXT2_CCB) FileObject->FsContext2; if (Ccb == NULL) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; }
ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB)));
if (OutputSize < sizeof(LARGE_INTEGER)) { Status = STATUS_BUFFER_TOO_SMALL; _SEH2_LEAVE; }
if (!ExAcquireResourceExclusiveLite ( &Fcb->MainResource, Ext2CanIWait())) { Status = STATUS_PENDING; _SEH2_LEAVE; } FcbResourceAcquired = TRUE;
FileAreaOffset = (PLARGE_INTEGER) Ext2GetUserBuffer(Irp);
/* probe user buffer */
_SEH2_TRY { if (Irp->RequestorMode != KernelMode) { ProbeForWrite(FileAreaOffset, OutputSize, sizeof(UCHAR)); }
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
Status = STATUS_INVALID_USER_BUFFER; } _SEH2_END;
if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
DEBUG(DL_DBG, ("Ext2GetRetrievalPointerBase: FileAreaOffset is 0.\n"));
FileAreaOffset->QuadPart = 0; // sector offset to the first allocatable unit on the filesystem
Irp->IoStatus.Information = sizeof(LARGE_INTEGER);
} _SEH2_FINALLY {
if (FcbResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); }
if (!_SEH2_AbnormalTermination()) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } } _SEH2_END;
return Status;}
NTSTATUSExt2InspectReparseData( IN PREPARSE_DATA_BUFFER RDB, IN ULONG InputBufferLength){ NTSTATUS Status = STATUS_SUCCESS;
if (!RDB) { Status = STATUS_INVALID_PARAMETER; goto out; }
if (InputBufferLength < sizeof(REPARSE_DATA_BUFFER)) { Status = STATUS_BUFFER_OVERFLOW; goto out; }
if (InputBufferLength < RDB->ReparseDataLength) { Status = STATUS_BUFFER_OVERFLOW; goto out; }
if (RDB->ReparseTag != IO_REPARSE_TAG_SYMLINK) { Status = STATUS_NOT_IMPLEMENTED; goto out; }
if ((PUCHAR)RDB->SymbolicLinkReparseBuffer.PathBuffer + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset + RDB->SymbolicLinkReparseBuffer.SubstituteNameLength > (PUCHAR)RDB + InputBufferLength ) { Status = STATUS_BUFFER_OVERFLOW; goto out; }
if ((PUCHAR)RDB->SymbolicLinkReparseBuffer.PathBuffer + RDB->SymbolicLinkReparseBuffer.PrintNameOffset + RDB->SymbolicLinkReparseBuffer.PrintNameLength > (PUCHAR)RDB + InputBufferLength) { Status = STATUS_BUFFER_OVERFLOW; goto out; }
if (RDB->SymbolicLinkReparseBuffer.Flags != SYMLINK_FLAG_RELATIVE) { Status = STATUS_NOT_IMPLEMENTED; goto out; }
out: return Status;}
VOIDExt2InitializeReparseData(IN PREPARSE_DATA_BUFFER RDB, USHORT PathBufferLength){ ASSERT(FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.SubstituteNameOffset) == REPARSE_DATA_BUFFER_HEADER_SIZE); RDB->ReparseTag = IO_REPARSE_TAG_SYMLINK; RDB->ReparseDataLength = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer.DataBuffer) + PathBufferLength * sizeof(WCHAR); RDB->Reserved = 0; RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset = PathBufferLength; RDB->SymbolicLinkReparseBuffer.SubstituteNameLength = PathBufferLength; RDB->SymbolicLinkReparseBuffer.PrintNameOffset = 0; RDB->SymbolicLinkReparseBuffer.PrintNameLength = PathBufferLength; RDB->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE; RtlZeroMemory(&RDB->SymbolicLinkReparseBuffer.PathBuffer, PathBufferLength * 2);}
NTSTATUSExt2ReadSymlink ( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN PVOID Buffer, IN ULONG Size, OUT PULONG BytesRead ){ return Ext2ReadInode ( IrpContext, Vcb, Mcb, 0, Buffer, Size, FALSE, BytesRead);}
NTSTATUSExt2GetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext){ PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp; PEXTENDED_IO_STACK_LOCATION EIrpSp;
PDEVICE_OBJECT DeviceObject;
PEXT2_VCB Vcb = NULL; PEXT2_CCB Ccb = NULL; PEXT2_MCB Mcb = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL; BOOLEAN MainResourceAcquired = FALSE;
PVOID OutputBuffer; ULONG OutputBufferLength; ULONG BytesRead = 0;
PREPARSE_DATA_BUFFER RDB;
UNICODE_STRING UniName; OEM_STRING OemName;
PCHAR OemNameBuffer = NULL; int OemNameLength = 0, i;
Ccb = IrpContext->Ccb; ASSERT(Ccb != NULL); ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB))); DeviceObject = IrpContext->DeviceObject; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Mcb = IrpContext->Fcb->Mcb; Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp);
_SEH2_TRY {
if (!Mcb || !IsInodeSymLink(&Mcb->Inode) || !IsFlagOn(Ccb->Flags, CCB_OPEN_REPARSE_POINT)) { Status = STATUS_NOT_A_REPARSE_POINT; _SEH2_LEAVE; }
OutputBuffer = (PVOID)Irp->AssociatedIrp.SystemBuffer; OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
RDB = (PREPARSE_DATA_BUFFER)OutputBuffer; if (!RDB) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } if (OutputBufferLength < sizeof(REPARSE_DATA_BUFFER)) { Status = STATUS_BUFFER_OVERFLOW; _SEH2_LEAVE; }
OemNameLength = (ULONG)Mcb->Inode.i_size; if (OemNameLength > USHRT_MAX) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } OemName.Length = (USHORT)OemNameLength; OemName.MaximumLength = OemNameLength + 1; OemNameBuffer = OemName.Buffer = Ext2AllocatePool(NonPagedPool, OemName.MaximumLength, 'NL2E'); if (!OemNameBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
Status = Ext2ReadSymlink(IrpContext, Vcb, Mcb, OemNameBuffer, OemNameLength, &BytesRead ); OemName.Buffer[OemName.Length] = '\0'; for (i = 0;i < OemName.Length;i++) { if (OemName.Buffer[i] == '/') { OemName.Buffer[i] = '\\'; } }
if (OutputBufferLength - FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) > USHRT_MAX) { UniName.Length = USHRT_MAX; } else { UniName.Length = (USHORT)OutputBufferLength - FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer); } UniName.MaximumLength = UniName.Length; UniName.Length = (USHORT)Ext2OEMToUnicodeSize(Vcb, &OemName); Irp->IoStatus.Information = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + 2 * UniName.Length; if (UniName.MaximumLength < 2*UniName.Length) { Status = STATUS_BUFFER_TOO_SMALL; _SEH2_LEAVE; }
Ext2InitializeReparseData(RDB, UniName.Length); UniName.Buffer = RDB->SymbolicLinkReparseBuffer.PathBuffer; /* (PWCHAR)((PUCHAR)& + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset); */ Ext2OEMToUnicode(Vcb, &UniName, &OemName); RtlMoveMemory( (PUCHAR)RDB->SymbolicLinkReparseBuffer.PathBuffer + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset, UniName.Buffer, UniName.Length);
Status = STATUS_SUCCESS;
} _SEH2_FINALLY {
if (OemNameBuffer) { Ext2FreePool(OemNameBuffer, 'NL2E'); }
if (!_SEH2_AbnormalTermination()) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } } } _SEH2_END;
return Status;}
NTSTATUSExt2WriteSymlink ( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN PEXT2_MCB Mcb, IN PVOID Buffer, IN ULONG Size, OUT PULONG BytesWritten){ NTSTATUS Status = STATUS_SUCCESS; PUCHAR Data = (PUCHAR)(&Mcb->Inode.i_block[0]);
if (Size >= EXT2_LINKLEN_IN_INODE) {
/* initialize inode i_block[] */ if (0 == Mcb->Inode.i_blocks) { memset(Data, 0, EXT2_LINKLEN_IN_INODE); ClearFlag(Mcb->Inode.i_flags, EXT4_EXTENTS_FL); Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); }
Status = Ext2WriteInode(IrpContext, Vcb, Mcb, 0, Buffer, Size, FALSE, BytesWritten); if (!NT_SUCCESS(Status)) { goto out; }
} else {
/* free inode blocks before writing in line */ if (Mcb->Inode.i_blocks) { LARGE_INTEGER Zero = {0, 0}; Ext2TruncateFile(IrpContext, Vcb, Mcb, &Zero); }
ClearFlag(Mcb->Inode.i_flags, EXT4_EXTENTS_FL); memset(Data, 0, EXT2_LINKLEN_IN_INODE); RtlCopyMemory(Data, Buffer, Size); }
Mcb->Inode.i_size = Size; Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
if (BytesWritten) { *BytesWritten = Size; }
out: return Status;}
NTSTATUSExt2SetReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext){ PIRP Irp = NULL; PIO_STACK_LOCATION IrpSp;
PDEVICE_OBJECT DeviceObject;
PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL; PEXT2_MCB Mcb = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PVOID InputBuffer; ULONG InputBufferLength; ULONG BytesWritten = 0;
PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ PEXT2_MCB ParentMcb = NULL;
PREPARSE_DATA_BUFFER RDB;
UNICODE_STRING UniName; OEM_STRING OemName;
PCHAR OemNameBuffer = NULL; int OemNameLength = 0, i;
BOOLEAN MainResourceAcquired = FALSE; BOOLEAN FcbLockAcquired = FALSE;
_SEH2_TRY {
Ccb = IrpContext->Ccb; ASSERT(Ccb != NULL); ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB))); DeviceObject = IrpContext->DeviceObject; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Fcb = IrpContext->Fcb; Mcb = Fcb->Mcb; Irp = IrpContext->Irp; IrpSp = IoGetCurrentIrpStackLocation(Irp);
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); FcbLockAcquired = TRUE;
ParentMcb = Mcb->Parent; ParentDcb = ParentMcb->Fcb; if (ParentDcb == NULL) { ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); } if (ParentDcb) { Ext2ReferXcb(&ParentDcb->ReferenceCount); }
if (!Mcb) _SEH2_LEAVE;
if (FcbLockAcquired) { ExReleaseResourceLite(&Vcb->FcbLock); FcbLockAcquired = FALSE; }
if (!ExAcquireResourceSharedLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; _SEH2_LEAVE; } MainResourceAcquired = TRUE;
InputBuffer = Irp->AssociatedIrp.SystemBuffer; InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
RDB = (PREPARSE_DATA_BUFFER)InputBuffer; Status = Ext2InspectReparseData(RDB, InputBufferLength); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
UniName.Length = RDB->SymbolicLinkReparseBuffer.SubstituteNameLength; UniName.MaximumLength = UniName.Length; UniName.Buffer = (PWCHAR)((PUCHAR)&RDB->SymbolicLinkReparseBuffer.PathBuffer + RDB->SymbolicLinkReparseBuffer.SubstituteNameOffset);
OemNameLength = Ext2UnicodeToOEMSize(Vcb, &UniName); if (OemNameLength > USHRT_MAX) { Status = STATUS_INVALID_PARAMETER; _SEH2_LEAVE; } OemName.Length = (USHORT)OemNameLength; OemName.MaximumLength = OemNameLength + 1; OemNameBuffer = OemName.Buffer = Ext2AllocatePool(PagedPool, OemName.MaximumLength, 'NL2E'); if (!OemNameBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
Ext2UnicodeToOEM(Vcb, &OemName, &UniName); OemName.Buffer[OemName.Length] = '\0'; for (i = 0;i < OemName.Length;i++) { if (OemName.Buffer[i] == '\\') { OemName.Buffer[i] = '/'; } }
/* free all data blocks of the inode (to be set as symlink) */ { LARGE_INTEGER zero = {0}; Status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &zero); }
/* decrease dir count of group desc and vcb stat */ if (S_ISDIR(Mcb->Inode.i_mode)) {
ULONG group = (Mcb->Inode.i_ino - 1) / INODES_PER_GROUP; Ext2UpdateGroupDirStat(IrpContext, Vcb, group);
/* drop extra reference for dir inode */ ext3_dec_count(&Mcb->Inode); }
/* overwrite inode mode as type SYMLINK */ Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode); SetFlag(Mcb->FileAttr, FILE_ATTRIBUTE_REPARSE_POINT);
Status = Ext2WriteSymlink(IrpContext, Vcb, Mcb, OemNameBuffer, OemNameLength, &BytesWritten); if (NT_SUCCESS(Status)) { Ext2SetFileType(IrpContext, Vcb, ParentDcb, Mcb, S_IFLNK | S_IRWXUGO); }
} _SEH2_FINALLY {
if (FcbLockAcquired) { ExReleaseResourceLite(&Vcb->FcbLock); FcbLockAcquired = FALSE; }
if (MainResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); }
if (OemNameBuffer) { Ext2FreePool(OemNameBuffer, 'NL2E'); }
if (NT_SUCCESS(Status)) { Ext2NotifyReportChange( IrpContext, Vcb, Mcb, FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_ACTION_MODIFIED ); }
if (!_SEH2_AbnormalTermination()) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } }
if (ParentDcb) { Ext2ReleaseFcb(ParentDcb); } } _SEH2_END;
return Status;}
NTSTATUSExt2TruncateSymlink( PEXT2_IRP_CONTEXT IrpContext, PEXT2_VCB Vcb, PEXT2_MCB Mcb, ULONG Size ){ NTSTATUS status = STATUS_SUCCESS; PUCHAR data = (PUCHAR)&Mcb->Inode.i_block; ULONG len = (ULONG)Mcb->Inode.i_size; LARGE_INTEGER NewSize;
if (len < EXT2_LINKLEN_IN_INODE && !Mcb->Inode.i_blocks) {
RtlZeroMemory(data + Size, EXT2_LINKLEN_IN_INODE - Size); Mcb->Inode.i_size = Size; Ext2SaveInode(IrpContext, Vcb, &Mcb->Inode);
} else { NewSize.QuadPart = Size; status = Ext2TruncateFile(IrpContext, Vcb, Mcb, &NewSize); if (!NT_SUCCESS(status)) { goto out; } }
out: return status;}
/* FIXME: We can only handle one reparse point right now. */NTSTATUSExt2DeleteReparsePoint (IN PEXT2_IRP_CONTEXT IrpContext){ PIRP Irp = NULL;
PDEVICE_OBJECT DeviceObject;
PEXT2_VCB Vcb = NULL; PEXT2_FCB Fcb = NULL; PEXT2_CCB Ccb = NULL; PEXT2_MCB Mcb = NULL;
PEXT2_FCB ParentDcb = NULL; /* Dcb of it's current parent */ PEXT2_MCB ParentMcb = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
BOOLEAN FcbLockAcquired = FALSE; BOOLEAN MainResourceAcquired = FALSE;
_SEH2_TRY {
Ccb = IrpContext->Ccb; ASSERT(Ccb != NULL); ASSERT((Ccb->Identifier.Type == EXT2CCB) && (Ccb->Identifier.Size == sizeof(EXT2_CCB))); DeviceObject = IrpContext->DeviceObject; Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; Mcb = IrpContext->Fcb->Mcb; Irp = IrpContext->Irp;
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); FcbLockAcquired = TRUE;
ParentMcb = Mcb->Parent; ParentDcb = ParentMcb->Fcb; if (ParentDcb == NULL) { ParentDcb = Ext2AllocateFcb(Vcb, ParentMcb); } if (ParentDcb) { Ext2ReferXcb(&ParentDcb->ReferenceCount); }
if (!Mcb || !IsInodeSymLink(&Mcb->Inode) || !IsFlagOn(Ccb->Flags, CCB_OPEN_REPARSE_POINT)) { Status = STATUS_NOT_A_REPARSE_POINT; _SEH2_LEAVE; }
Fcb = Ext2AllocateFcb (Vcb, Mcb); if (Fcb) { Ext2ReferXcb(&Fcb->ReferenceCount); } else { Status = STATUS_INSUFFICIENT_RESOURCES; _SEH2_LEAVE; }
if (FcbLockAcquired) { ExReleaseResourceLite(&Vcb->FcbLock); FcbLockAcquired = FALSE; }
if (!ExAcquireResourceSharedLite( &Fcb->MainResource, IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) { Status = STATUS_PENDING; _SEH2_LEAVE; } MainResourceAcquired = TRUE;
Status = Ext2TruncateSymlink(IrpContext, Vcb, Mcb, 0); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
/* inode is to be removed */ SetFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);
} _SEH2_FINALLY {
if (FcbLockAcquired) { ExReleaseResourceLite(&Vcb->FcbLock); }
if (MainResourceAcquired) { ExReleaseResourceLite(&Fcb->MainResource); }
if (NT_SUCCESS(Status)) { Ext2NotifyReportChange( IrpContext, Vcb, Mcb, FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_ACTION_MODIFIED );
}
if (!_SEH2_AbnormalTermination()) { if (Status == STATUS_PENDING || Status == STATUS_CANT_WAIT) { Status = Ext2QueueRequest(IrpContext); } else { Ext2CompleteIrpContext(IrpContext, Status); } }
if (ParentDcb) { Ext2ReleaseFcb(ParentDcb); }
if (Fcb) { Ext2ReleaseFcb(Fcb); } } _SEH2_END;
return Status;}
NTSTATUSExt2UserFsRequest (IN PEXT2_IRP_CONTEXT IrpContext){ PIRP Irp; PIO_STACK_LOCATION IoStackLocation; ULONG FsControlCode; NTSTATUS Status;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
#ifndef _GNU_NTIFS_ FsControlCode = IoStackLocation->Parameters.FileSystemControl.FsControlCode;#else FsControlCode = ((PEXTENDED_IO_STACK_LOCATION) IoStackLocation)->Parameters.FileSystemControl.FsControlCode;#endif
switch (FsControlCode) {
case FSCTL_GET_REPARSE_POINT: Status = Ext2GetReparsePoint(IrpContext); break;
case FSCTL_SET_REPARSE_POINT: Status = Ext2SetReparsePoint(IrpContext); break;
case FSCTL_DELETE_REPARSE_POINT: Status = Ext2DeleteReparsePoint(IrpContext); break;
case FSCTL_LOCK_VOLUME: Status = Ext2LockVolume(IrpContext); break;
case FSCTL_UNLOCK_VOLUME: Status = Ext2UnlockVolume(IrpContext); break;
case FSCTL_DISMOUNT_VOLUME: Status = Ext2DismountVolume(IrpContext); break;
case FSCTL_IS_VOLUME_MOUNTED: Status = Ext2IsVolumeMounted(IrpContext); break;
case FSCTL_INVALIDATE_VOLUMES: Status = Ext2InvalidateVolumes(IrpContext); break;
#if (_WIN32_WINNT >= 0x0500) case FSCTL_ALLOW_EXTENDED_DASD_IO: Status = Ext2AllowExtendedDasdIo(IrpContext); break;#endif //(_WIN32_WINNT >= 0x0500)
case FSCTL_REQUEST_OPLOCK_LEVEL_1: case FSCTL_REQUEST_OPLOCK_LEVEL_2: case FSCTL_REQUEST_BATCH_OPLOCK: case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE: case FSCTL_OPBATCH_ACK_CLOSE_PENDING: case FSCTL_OPLOCK_BREAK_NOTIFY: case FSCTL_OPLOCK_BREAK_ACK_NO_2:
Status = Ext2OplockRequest(IrpContext); break;
case FSCTL_IS_VOLUME_DIRTY: Status = Ext2IsVolumeDirty(IrpContext); break;
case FSCTL_QUERY_RETRIEVAL_POINTERS: Status = Ext2QueryRetrievalPointers(IrpContext); break;
case FSCTL_GET_RETRIEVAL_POINTERS: Status = Ext2GetRetrievalPointers(IrpContext); break;
case FSCTL_GET_RETRIEVAL_POINTER_BASE: Status = Ext2GetRetrievalPointerBase(IrpContext); break;
default:
DEBUG(DL_INF, ( "Ext2UserFsRequest: Invalid User Request: %xh.\n", FsControlCode)); Status = STATUS_INVALID_DEVICE_REQUEST;
Ext2CompleteIrpContext(IrpContext, Status); }
return Status;}
BOOLEANExt2IsMediaWriteProtected ( IN PEXT2_IRP_CONTEXT IrpContext, IN PDEVICE_OBJECT TargetDevice){ PIRP Irp; KEVENT Event; NTSTATUS Status; IO_STATUS_BLOCK IoStatus;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_IS_WRITABLE, TargetDevice, NULL, 0, NULL, 0, FALSE, &Event, &IoStatus );
if (Irp == NULL) { return FALSE; }
SetFlag(IoGetNextIrpStackLocation(Irp)->Flags, SL_OVERRIDE_VERIFY_VOLUME);
Status = IoCallDriver(TargetDevice, Irp);
if (Status == STATUS_PENDING) {
(VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );
Status = IoStatus.Status; }
return (BOOLEAN)(Status == STATUS_MEDIA_WRITE_PROTECTED);}
NTSTATUSExt2MountVolume (IN PEXT2_IRP_CONTEXT IrpContext){ PDEVICE_OBJECT MainDeviceObject; BOOLEAN GlobalDataResourceAcquired = FALSE; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; PDEVICE_OBJECT TargetDeviceObject; NTSTATUS Status = STATUS_UNRECOGNIZED_VOLUME; PDEVICE_OBJECT VolumeDeviceObject = NULL; PEXT2_VCB Vcb = NULL, OldVcb = NULL; PVPB OldVpb = NULL, Vpb = NULL; PEXT2_SUPER_BLOCK Ext2Sb = NULL; ULONG dwBytes; DISK_GEOMETRY DiskGeometry;
_SEH2_TRY {
ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
MainDeviceObject = IrpContext->DeviceObject;
// // Make sure we can wait. //
SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
// // This request is only allowed on the main device object // if (!IsExt2FsDevice(MainDeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; }
if (IsFlagOn(Ext2Global->Flags, EXT2_UNLOAD_PENDING)) { Status = STATUS_UNRECOGNIZED_VOLUME; _SEH2_LEAVE; }
#if 0 if (IrpContext->RealDevice->Size >= sizeof(ULONG) + sizeof(DEVICE_OBJECT) && *((PULONG)IrpContext->RealDevice->DeviceExtension) == 'DSSA') { } else { Status = STATUS_UNRECOGNIZED_VOLUME; _SEH2_LEAVE; }#endif
Irp = IrpContext->Irp; IoStackLocation = IoGetCurrentIrpStackLocation(Irp); TargetDeviceObject = IoStackLocation->Parameters.MountVolume.DeviceObject;
dwBytes = sizeof(DISK_GEOMETRY); Status = Ext2DiskIoControl( TargetDeviceObject, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, &dwBytes );
if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
Status = IoCreateDevice( MainDeviceObject->DriverObject, sizeof(EXT2_VCB), NULL, FILE_DEVICE_DISK_FILE_SYSTEM, 0, FALSE, &VolumeDeviceObject );
if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } INC_MEM_COUNT(PS_VCB, VolumeDeviceObject, sizeof(EXT2_VCB));
#ifdef _PNP_POWER_ /* don't care about power management requests */ VolumeDeviceObject->DeviceObjectExtension->PowerControlNeeded = FALSE;#endif
VolumeDeviceObject->StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1); ClearFlag(VolumeDeviceObject->Flags, DO_DEVICE_INITIALIZING);
/* These are for buffer-address alignment requirements. Never do this check, unless you want fail user requests :)
if (TargetDeviceObject->AlignmentRequirement > VolumeDeviceObject->AlignmentRequirement) {
VolumeDeviceObject->AlignmentRequirement = TargetDeviceObject->AlignmentRequirement; }
if (DiskGeometry.BytesPerSector - 1 > VolumeDeviceObject->AlignmentRequirement) { VolumeDeviceObject->AlignmentRequirement = DiskGeometry.BytesPerSector - 1; TargetDeviceObject->AlignmentRequirement = DiskGeometry.BytesPerSector - 1; }*/ (IoStackLocation->Parameters.MountVolume.Vpb)->DeviceObject = VolumeDeviceObject; Vpb = IoStackLocation->Parameters.MountVolume.Vpb;
Vcb = (PEXT2_VCB) VolumeDeviceObject->DeviceExtension;
RtlZeroMemory(Vcb, sizeof(EXT2_VCB)); Vcb->Identifier.Type = EXT2VCB; Vcb->Identifier.Size = sizeof(EXT2_VCB); Vcb->TargetDeviceObject = TargetDeviceObject; Vcb->DiskGeometry = DiskGeometry; InitializeListHead(&Vcb->Next);
Status = Ext2LoadSuper(Vcb, FALSE, &Ext2Sb); if (!NT_SUCCESS(Status)) { Vcb = NULL; Status = STATUS_UNRECOGNIZED_VOLUME; _SEH2_LEAVE; } ASSERT (NULL != Ext2Sb);
/* check Linux Ext2/Ext3 volume magic */ if (Ext2Sb->s_magic == EXT2_SUPER_MAGIC) { DEBUG(DL_INF, ( "Volume of ext2 file system is found.\n")); } else { Status = STATUS_UNRECOGNIZED_VOLUME; Vcb = NULL; _SEH2_LEAVE; }
DEBUG(DL_DBG, ("Ext2MountVolume: DevObject=%p Vcb=%p\n", VolumeDeviceObject, Vcb));
/* initialize Vcb structure */ Status = Ext2InitializeVcb( IrpContext, Vcb, Ext2Sb, TargetDeviceObject, VolumeDeviceObject, Vpb);
if (NT_SUCCESS(Status)) {
PLIST_ENTRY List;
ExAcquireResourceExclusiveLite(&(Ext2Global->Resource), TRUE); GlobalDataResourceAcquired = TRUE;
for (List = Ext2Global->VcbList.Flink; List != &Ext2Global->VcbList; List = List->Flink) {
OldVcb = CONTAINING_RECORD(List, EXT2_VCB, Next); OldVpb = OldVcb->Vpb;
/* in case we are already in the queue, should not happen */ if (OldVpb == Vpb) { continue; }
if ( (OldVpb->SerialNumber == Vpb->SerialNumber) && (!IsMounted(OldVcb)) && (IsFlagOn(OldVcb->Flags, VCB_NEW_VPB)) && (OldVpb->RealDevice == TargetDeviceObject) && (OldVpb->VolumeLabelLength == Vpb->VolumeLabelLength) && (RtlEqualMemory(&OldVpb->VolumeLabel[0], &Vpb->VolumeLabel[0], Vpb->VolumeLabelLength)) && (RtlEqualMemory(&OldVcb->SuperBlock->s_uuid[0], &Vcb->SuperBlock->s_uuid[0], 16)) ) { ClearFlag(OldVcb->Flags, VCB_MOUNTED); } }
SetLongFlag(Vcb->Flags, VCB_MOUNTED); SetFlag(Vcb->Vpb->Flags, VPB_MOUNTED); Ext2InsertVcb(Vcb); Vcb = NULL; Vpb = NULL; ObDereferenceObject(TargetDeviceObject);
} else {
Vcb = NULL; }
} _SEH2_FINALLY {
if (GlobalDataResourceAcquired) { ExReleaseResourceLite(&Ext2Global->Resource); }
if (!NT_SUCCESS(Status)) {
if (!NT_SUCCESS(Status)) { if ( Vpb != NULL ) { Vpb->DeviceObject = NULL; } }
if (Vcb) { Ext2DestroyVcb(Vcb); } else { if (Ext2Sb) { Ext2FreePool(Ext2Sb, EXT2_SB_MAGIC); } if (VolumeDeviceObject) { IoDeleteDevice(VolumeDeviceObject); DEC_MEM_COUNT(PS_VCB, VolumeDeviceObject, sizeof(EXT2_VCB)); } } }
if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END;
return Status;}
VOIDExt2VerifyVcb (IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb ){ NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN bVerify = FALSE; ULONG ChangeCount = 0; ULONG dwBytes;
PIRP Irp; PEXTENDED_IO_STACK_LOCATION IrpSp;
_SEH2_TRY {
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
Irp = IrpContext->Irp; IrpSp = (PEXTENDED_IO_STACK_LOCATION)IoGetCurrentIrpStackLocation(Irp);
bVerify = IsFlagOn(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
if ( (IsFlagOn(Vcb->Flags, VCB_REMOVABLE_MEDIA) || IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) && !bVerify ) {
dwBytes = sizeof(ULONG); Status = Ext2DiskIoControl( Vcb->TargetDeviceObject, IOCTL_DISK_CHECK_VERIFY, NULL, 0, &ChangeCount, &dwBytes );
if ( STATUS_VERIFY_REQUIRED == Status || STATUS_DEVICE_NOT_READY == Status || STATUS_NO_MEDIA_IN_DEVICE == Status || (NT_SUCCESS(Status) && (ChangeCount != Vcb->ChangeCount))) {
KIRQL Irql;
IoAcquireVpbSpinLock(&Irql); if (Vcb->Vpb == Vcb->Vpb->RealDevice->Vpb) { SetFlag(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME); } IoReleaseVpbSpinLock(Irql);
} else {
if (!NT_SUCCESS(Status)) { Ext2NormalizeAndRaiseStatus(IrpContext, Status); } } }
if ( IsFlagOn(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME)) { IoSetHardErrorOrVerifyDevice( Irp, Vcb->Vpb->RealDevice ); Ext2NormalizeAndRaiseStatus ( IrpContext, STATUS_VERIFY_REQUIRED ); }
if (IsMounted(Vcb)) {
if ( (IrpContext->MajorFunction == IRP_MJ_WRITE) || (IrpContext->MajorFunction == IRP_MJ_SET_INFORMATION) || (IrpContext->MajorFunction == IRP_MJ_SET_EA) || (IrpContext->MajorFunction == IRP_MJ_FLUSH_BUFFERS) || (IrpContext->MajorFunction == IRP_MJ_SET_VOLUME_INFORMATION) || (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL && IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST && IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_MARK_VOLUME_DIRTY)) {
if (IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED)) {
KIRQL Irql;
IoAcquireVpbSpinLock(&Irql); if (Vcb->Vpb == Vcb->Vpb->RealDevice->Vpb) { SetFlag (Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME); } IoReleaseVpbSpinLock(Irql);
IoSetHardErrorOrVerifyDevice( Irp, Vcb->Vpb->RealDevice );
Ext2RaiseStatus(IrpContext, STATUS_MEDIA_WRITE_PROTECTED); } } }
} _SEH2_FINALLY {
} _SEH2_END;
}
NTSTATUSExt2VerifyVolume (IN PEXT2_IRP_CONTEXT IrpContext){ PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PEXT2_SUPER_BLOCK ext2_sb = NULL; PEXT2_VCB Vcb = NULL; BOOLEAN VcbResourceAcquired = FALSE; PIRP Irp; ULONG ChangeCount = 0; ULONG dwBytes;
_SEH2_TRY {
ASSERT(IrpContext != NULL); ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject; // // This request is not allowed on the main device object // if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension; ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
VcbResourceAcquired = ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE );
if (!FlagOn(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME)) { Status = STATUS_SUCCESS; _SEH2_LEAVE; }
if (!IsMounted(Vcb)) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; }
dwBytes = sizeof(ULONG); Status = Ext2DiskIoControl( Vcb->TargetDeviceObject, IOCTL_DISK_CHECK_VERIFY, NULL, 0, &ChangeCount, &dwBytes );
if (!NT_SUCCESS(Status)) { Status = STATUS_WRONG_VOLUME; _SEH2_LEAVE; } else { Vcb->ChangeCount = ChangeCount; }
Irp = IrpContext->Irp;
Status = Ext2LoadSuper(Vcb, TRUE, &ext2_sb);
if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; }
ASSERT(NULL != ext2_sb); if ((ext2_sb->s_magic == EXT2_SUPER_MAGIC) && (memcmp(ext2_sb->s_uuid, SUPER_BLOCK->s_uuid, 16) == 0) && (memcmp(ext2_sb->s_volume_name, SUPER_BLOCK->s_volume_name, 16) ==0)) {
ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);
if (Ext2IsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject)) { SetLongFlag(Vcb->Flags, VCB_WRITE_PROTECTED); } else { ClearLongFlag(Vcb->Flags, VCB_WRITE_PROTECTED); }
DEBUG(DL_INF, ( "Ext2VerifyVolume: Volume verify succeeded.\n"));
} else {
Status = STATUS_WRONG_VOLUME; Ext2PurgeVolume(Vcb, FALSE);
SetLongFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); ClearFlag(Vcb->TargetDeviceObject->Flags, DO_VERIFY_VOLUME);
DEBUG(DL_INF, ( "Ext2VerifyVolume: Volume verify failed.\n")); }
} _SEH2_FINALLY {
if (ext2_sb) Ext2FreePool(ext2_sb, EXT2_SB_MAGIC);
if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); }
if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END;
return Status;}
NTSTATUSExt2IsVolumeMounted (IN PEXT2_IRP_CONTEXT IrpContext){ PDEVICE_OBJECT DeviceObject; PEXT2_VCB Vcb = 0; NTSTATUS Status = STATUS_SUCCESS;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(IsMounted(Vcb));
Ext2VerifyVcb (IrpContext, Vcb);
Ext2CompleteIrpContext(IrpContext, Status);
return Status;}
NTSTATUSExt2DismountVolume (IN PEXT2_IRP_CONTEXT IrpContext){ PDEVICE_OBJECT DeviceObject; NTSTATUS Status = STATUS_UNSUCCESSFUL; PEXT2_VCB Vcb = NULL; BOOLEAN VcbResourceAcquired = FALSE;
_SEH2_TRY {
ASSERT(IrpContext != NULL);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
// // This request is not allowed on the main device object // if (IsExt2FsDevice(DeviceObject)) { Status = STATUS_INVALID_DEVICE_REQUEST; _SEH2_LEAVE; }
Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ASSERT(IsMounted(Vcb));
ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE );
VcbResourceAcquired = TRUE;
if ( IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) { Status = STATUS_VOLUME_DISMOUNTED; _SEH2_LEAVE; }
Ext2FlushFiles(IrpContext, Vcb, FALSE); Ext2FlushVolume(IrpContext, Vcb, FALSE);
ExReleaseResourceLite(&Vcb->MainResource); VcbResourceAcquired = FALSE;
Ext2PurgeVolume(Vcb, TRUE); Ext2CheckDismount(IrpContext, Vcb, TRUE);
DEBUG(DL_INF, ( "Ext2Dismount: Volume dismount pending.\n")); Status = STATUS_SUCCESS;
} _SEH2_FINALLY {
if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); }
if (!IrpContext->ExceptionInProgress) { Ext2CompleteIrpContext(IrpContext, Status); } } _SEH2_END;
return Status;}
BOOLEANExt2CheckDismount ( IN PEXT2_IRP_CONTEXT IrpContext, IN PEXT2_VCB Vcb, IN BOOLEAN bForce ){ KIRQL Irql; PVPB Vpb = Vcb->Vpb, NewVpb = NULL; BOOLEAN bDeleted = FALSE, bTearDown = FALSE; ULONG UnCleanCount = 0;
NewVpb = ExAllocatePoolWithTag(NonPagedPool, VPB_SIZE, TAG_VPB); if (NewVpb == NULL) { DEBUG(DL_ERR, ( "Ex2CheckDismount: failed to allocate NewVpb.\n")); return FALSE; } DEBUG(DL_DBG, ("Ext2CheckDismount: NewVpb allocated: %p\n", NewVpb)); INC_MEM_COUNT(PS_VPB, NewVpb, sizeof(VPB)); memset(NewVpb, '_', VPB_SIZE); RtlZeroMemory(NewVpb, sizeof(VPB));
ExAcquireResourceExclusiveLite( &Ext2Global->Resource, TRUE );
ExAcquireResourceExclusiveLite( &Vcb->MainResource, TRUE );
if (IrpContext && IrpContext->MajorFunction == IRP_MJ_CREATE && IrpContext->RealDevice == Vcb->RealDevice) { UnCleanCount = 2; } else { UnCleanCount = 1; }
IoAcquireVpbSpinLock (&Irql);
DEBUG(DL_DBG, ("Ext2CheckDismount: Vpb %p ioctl=%d Device %p\n", Vpb, Vpb->ReferenceCount, Vpb->RealDevice));
if (Vpb->ReferenceCount <= UnCleanCount) {
if (!IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
ClearFlag(Vpb->Flags, VPB_MOUNTED); ClearFlag(Vpb->Flags, VPB_LOCKED);
if ((Vcb->RealDevice != Vpb->RealDevice) && (Vcb->RealDevice->Vpb == Vpb)) { SetFlag(Vcb->RealDevice->Flags, DO_DEVICE_INITIALIZING); SetFlag(Vpb->Flags, VPB_PERSISTENT ); }
Ext2RemoveVcb(Vcb); SetLongFlag(Vcb->Flags, VCB_DISMOUNT_PENDING); }
if (Vpb->ReferenceCount) { bTearDown = TRUE; } else { bDeleted = TRUE; Vpb->DeviceObject = NULL; }
DEBUG(DL_DBG, ("Ext2CheckDismount: Vpb: %p bDeleted=%d bTearDown=%d\n", Vpb, bDeleted, bTearDown));
} else if (bForce) {
DEBUG(DL_DBG, ( "Ext2CheckDismount: New/Old Vpb %p/%p Realdevice = %p\n", NewVpb, Vcb->Vpb, Vpb->RealDevice));
/* keep vpb president and later we'll free it */ SetFlag(Vpb->Flags, VPB_PERSISTENT);
Vcb->Vpb2 = Vcb->Vpb; NewVpb->Type = IO_TYPE_VPB; NewVpb->Size = sizeof(VPB); NewVpb->Flags = Vpb->Flags & VPB_REMOVE_PENDING; NewVpb->RealDevice = Vpb->RealDevice; NewVpb->RealDevice->Vpb = NewVpb; NewVpb = NULL; ClearFlag(Vpb->Flags, VPB_MOUNTED); SetLongFlag(Vcb->Flags, VCB_NEW_VPB); ClearLongFlag(Vcb->Flags, VCB_MOUNTED); }
IoReleaseVpbSpinLock(Irql);
ExReleaseResourceLite(&Vcb->MainResource); ExReleaseResourceLite(&Ext2Global->Resource);
if (bTearDown) { DEBUG(DL_DBG, ( "Ext2CheckDismount: Tearing vcb %p ...\n", Vcb)); Ext2TearDownStream(Vcb); }
if (bDeleted) { DEBUG(DL_DBG, ( "Ext2CheckDismount: Deleting vcb %p ...\n", Vcb)); Ext2DestroyVcb(Vcb); }
if (NewVpb != NULL) { DEBUG(DL_DBG, ( "Ext2CheckDismount: freeing new Vpb %p\n", NewVpb)); ExFreePoolWithTag(NewVpb, TAG_VPB); DEC_MEM_COUNT(PS_VPB, NewVpb, sizeof(VPB)); }
return bDeleted;}
NTSTATUSExt2PurgeVolume (IN PEXT2_VCB Vcb, IN BOOLEAN FlushBeforePurge ){ PEXT2_FCB Fcb; LIST_ENTRY List, *Next;
BOOLEAN VcbResourceAcquired = FALSE; BOOLEAN FcbResourceAcquired = FALSE; BOOLEAN gdResourceAcquired = FALSE;
_SEH2_TRY {
ASSERT(Vcb != NULL); ASSERT((Vcb->Identifier.Type == EXT2VCB) && (Vcb->Identifier.Size == sizeof(EXT2_VCB)));
ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE); VcbResourceAcquired = TRUE;
if (IsVcbReadOnly(Vcb)) { FlushBeforePurge = FALSE; }
InitializeListHead(&List);
ExAcquireResourceExclusiveLite(&Vcb->FcbLock, TRUE); FcbResourceAcquired = TRUE;
while (!IsListEmpty(&Vcb->FcbList)) {
Next = RemoveHeadList(&Vcb->FcbList); Fcb = CONTAINING_RECORD(Next, EXT2_FCB, Next);
DEBUG(DL_INF, ( "Ext2PurgeVolume: %wZ refercount=%xh\n", &Fcb->Mcb->FullName, Fcb->ReferenceCount)); InsertTailList(&List, &Fcb->Next); }
while (!IsListEmpty(&List)) {
Next = RemoveHeadList(&List); Fcb = CONTAINING_RECORD(Next, EXT2_FCB, Next);
if (ExAcquireResourceExclusiveLite( &Fcb->MainResource, TRUE )) {
Ext2PurgeFile(Fcb, FlushBeforePurge);
if (Fcb->ReferenceCount <= 1) { Fcb->TsDrop.QuadPart = 0; InsertHeadList(&Vcb->FcbList, &Fcb->Next); } else { InsertTailList(&Vcb->FcbList, &Fcb->Next); } ExReleaseResourceLite(&Fcb->MainResource); } }
if (FcbResourceAcquired) { ExReleaseResourceLite(&Vcb->FcbLock); FcbResourceAcquired = FALSE; }
/* acquire bd lock to avoid bh creation */ ExAcquireResourceExclusiveLite(&Vcb->sbi.s_gd_lock, TRUE); gdResourceAcquired = TRUE;
/* discard buffer_headers for group_desc */ Ext2DropBH(Vcb);
if (FlushBeforePurge) { ExAcquireSharedStarveExclusive(&Vcb->PagingIoResource, TRUE); ExReleaseResourceLite(&Vcb->PagingIoResource);
CcFlushCache(&Vcb->SectionObject, NULL, 0, NULL); }
if (Vcb->SectionObject.ImageSectionObject) { MmFlushImageSection(&Vcb->SectionObject, MmFlushForWrite); }
if (Vcb->SectionObject.DataSectionObject) { CcPurgeCacheSection(&Vcb->SectionObject, NULL, 0, FALSE); }
DEBUG(DL_INF, ( "Ext2PurgeVolume: Volume flushed and purged.\n"));
} _SEH2_FINALLY {
if (gdResourceAcquired) { ExReleaseResourceLite(&Vcb->sbi.s_gd_lock); }
if (FcbResourceAcquired) { ExReleaseResourceLite(&Vcb->FcbLock); }
if (VcbResourceAcquired) { ExReleaseResourceLite(&Vcb->MainResource); } } _SEH2_END;
return STATUS_SUCCESS;}
NTSTATUSExt2PurgeFile ( IN PEXT2_FCB Fcb, IN BOOLEAN FlushBeforePurge ){ IO_STATUS_BLOCK IoStatus;
ASSERT(Fcb != NULL);
ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB)));
if (!IsVcbReadOnly(Fcb->Vcb) && FlushBeforePurge) { DEBUG(DL_INF, ( "Ext2PurgeFile: CcFlushCache on %wZ.\n", &Fcb->Mcb->FullName)); ExAcquireSharedStarveExclusive(&Fcb->PagingIoResource, TRUE); ExReleaseResourceLite(&Fcb->PagingIoResource); CcFlushCache(&Fcb->SectionObject, NULL, 0, &IoStatus); ClearFlag(Fcb->Flags, FCB_FILE_MODIFIED); }
if (Fcb->SectionObject.ImageSectionObject) { DEBUG(DL_INF, ( "Ext2PurgeFile: MmFlushImageSection on %wZ.\n", &Fcb->Mcb->FullName)); MmFlushImageSection(&Fcb->SectionObject, MmFlushForWrite); }
if (Fcb->SectionObject.DataSectionObject) { DEBUG(DL_INF, ( "Ext2PurgeFile: CcPurgeCacheSection on %wZ.\n", &Fcb->Mcb->FullName)); CcPurgeCacheSection(&Fcb->SectionObject, NULL, 0, FALSE); }
return STATUS_SUCCESS;}
NTSTATUSExt2FileSystemControl (IN PEXT2_IRP_CONTEXT IrpContext){ NTSTATUS Status;
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == EXT2ICX) && (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
switch (IrpContext->MinorFunction) {
case IRP_MN_USER_FS_REQUEST: Status = Ext2UserFsRequest(IrpContext); break;
case IRP_MN_MOUNT_VOLUME: Status = Ext2MountVolume(IrpContext); break;
case IRP_MN_VERIFY_VOLUME: Status = Ext2VerifyVolume(IrpContext); break;
default:
DEBUG(DL_ERR, ( "Ext2FilsSystemControl: Invalid Device Request.\n")); Status = STATUS_INVALID_DEVICE_REQUEST; Ext2CompleteIrpContext(IrpContext, Status); }
return Status;}