123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203 |
- /*++
- Copyright (c) 2013 Minoca Corp. All Rights Reserved
- Module Name:
- userio.c
- Abstract:
- This module implements support for interfacing the I/O subsystem with
- user mode.
- Author:
- Evan Green 25-Apr-2013
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/kernel.h>
- #include "iop.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- #define ASSERT_SYS_OPEN_FLAGS_EQUIVALENT() \
- ASSERT((SYS_OPEN_FLAG_CREATE == OPEN_FLAG_CREATE) && \
- (SYS_OPEN_FLAG_TRUNCATE == OPEN_FLAG_TRUNCATE) && \
- (SYS_OPEN_FLAG_FAIL_IF_EXISTS == OPEN_FLAG_FAIL_IF_EXISTS) && \
- (SYS_OPEN_FLAG_APPEND == OPEN_FLAG_APPEND) && \
- (SYS_OPEN_FLAG_DIRECTORY == OPEN_FLAG_DIRECTORY) && \
- (SYS_OPEN_FLAG_NON_BLOCKING == OPEN_FLAG_NON_BLOCKING) && \
- (SYS_OPEN_FLAG_SHARED_MEMORY == OPEN_FLAG_SHARED_MEMORY) && \
- (SYS_OPEN_FLAG_NO_SYMBOLIC_LINK == OPEN_FLAG_NO_SYMBOLIC_LINK) && \
- (SYS_OPEN_FLAG_SYNCHRONIZED == OPEN_FLAG_SYNCHRONIZED) && \
- (SYS_OPEN_FLAG_NO_CONTROLLING_TERMINAL == \
- OPEN_FLAG_NO_CONTROLLING_TERMINAL) && \
- (SYS_OPEN_FLAG_NO_ACCESS_TIME == OPEN_FLAG_NO_ACCESS_TIME) && \
- (SYS_OPEN_FLAG_ASYNCHRONOUS == OPEN_FLAG_ASYNCHRONOUS))
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define CLOSE_EXECUTE_HANDLE_INITIAL_ARRAY_SIZE 16
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure stores context during a copy of a handle table.
- Members:
- DestinationTable - Stores a pointer to the destination handle table.
- SourceTable - Stores a pointer to the handle table to be copied.
- Status - Stores the current status of the copy operation. Initialize to
- STATUS_SUCCESS.
- --*/
- typedef struct _COPY_HANDLES_ITERATION_CONTEXT {
- PHANDLE_TABLE DestinationTable;
- PHANDLE_TABLE SourceTable;
- KSTATUS Status;
- } COPY_HANDLES_ITERATION_CONTEXT, *PCOPY_HANDLES_ITERATION_CONTEXT;
- /*++
- Structure Description:
- This structure stores context during a copy of a handle table.
- Members:
- HandleArray - Stores the array of handles to close, allocated in paged pool.
- HandleArraySize - Stores the number of valid entries in the array.
- HandleArrayCapacity - Stores the maximum number of elements in the handle
- array.
- Status - Stores the current status of the iteration operation. Initialize to
- STATUS_SUCCESS.
- --*/
- typedef struct _CLOSE_EXECUTE_HANDLES_CONTEXT {
- PHANDLE HandleArray;
- ULONG HandleArraySize;
- ULONG HandleArrayCapacity;
- KSTATUS Status;
- } CLOSE_EXECUTE_HANDLES_CONTEXT, *PCLOSE_EXECUTE_HANDLES_CONTEXT;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- KSTATUS
- IopSysClose (
- PKPROCESS Process,
- HANDLE Handle
- );
- VOID
- IopCopyHandleIterateRoutine (
- PHANDLE_TABLE HandleTable,
- HANDLE Descriptor,
- ULONG Flags,
- PVOID HandleValue,
- PVOID Context
- );
- VOID
- IopCloseExecuteHandleIterateRoutine (
- PHANDLE_TABLE HandleTable,
- HANDLE Descriptor,
- ULONG Flags,
- PVOID HandleValue,
- PVOID Context
- );
- VOID
- IopCheckForDirectoryHandlesIterationRoutine (
- PHANDLE_TABLE HandleTable,
- HANDLE Descriptor,
- ULONG Flags,
- PVOID HandleValue,
- PVOID Context
- );
- KSTATUS
- IopGetUserFilePath (
- PPATH_POINT Entry,
- PPATH_POINT Root,
- PSTR UserBuffer,
- PUINTN UserBufferSize
- );
- KSTATUS
- IopHandleCommonUserControl (
- PIO_HANDLE Handle,
- HANDLE Descriptor,
- ULONG MinorCode,
- BOOL FromKernelMode,
- PVOID ContextBuffer,
- UINTN ContextBufferSize
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // ------------------------------------------------------------------ Functions
- //
- VOID
- IoSysOpen (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine opens a file or other I/O object on behalf of a user mode
- application.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- ULONG Access;
- PKPROCESS CurrentProcess;
- PIO_HANDLE Directory;
- PSTR FileName;
- ULONG FileNameLength;
- PIO_HANDLE Handle;
- ULONG HandleFlags;
- ULONG OpenFlags;
- PSYSTEM_CALL_OPEN Parameters;
- KSTATUS Status;
- CurrentProcess = PsGetCurrentProcess();
- ASSERT(CurrentProcess != PsGetKernelProcess());
- Directory = NULL;
- Handle = NULL;
- Parameters = (PSYSTEM_CALL_OPEN)SystemCallParameter;
- FileName = NULL;
- FileNameLength = Parameters->PathBufferLength;
- Parameters->Handle = INVALID_HANDLE;
- Status = MmCreateCopyOfUserModeString(Parameters->Path,
- FileNameLength,
- FI_ALLOCATION_TAG,
- &FileName);
- if (!KSUCCESS(Status)) {
- goto SysOpenEnd;
- }
- //
- // Set up the flags.
- //
- ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
- Access = (Parameters->Flags >> SYS_OPEN_ACCESS_SHIFT) & IO_ACCESS_MASK;
- OpenFlags = Parameters->Flags & SYS_OPEN_FLAG_MASK;
- if (Parameters->Directory != INVALID_HANDLE) {
- Directory = ObGetHandleValue(CurrentProcess->HandleTable,
- Parameters->Directory,
- NULL);
- if (Directory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysOpenEnd;
- }
- }
- //
- // Open up the file.
- //
- Status = IoOpen(FALSE,
- Directory,
- FileName,
- FileNameLength,
- Access,
- OpenFlags,
- Parameters->CreatePermissions,
- &Handle);
- if (!KSUCCESS(Status)) {
- goto SysOpenEnd;
- }
- //
- // Create a handle table entry for this open file.
- //
- HandleFlags = 0;
- if ((Parameters->Flags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
- HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- }
- Status = ObCreateHandle(CurrentProcess->HandleTable,
- Handle,
- HandleFlags,
- &(Parameters->Handle));
- if (!KSUCCESS(Status)) {
- goto SysOpenEnd;
- }
- Status = STATUS_SUCCESS;
- SysOpenEnd:
- if (Directory != NULL) {
- IoIoHandleReleaseReference(Directory);
- }
- if (FileName != NULL) {
- MmFreePagedPool(FileName);
- }
- if (!KSUCCESS(Status)) {
- if (Handle != NULL) {
- IoClose(Handle);
- }
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysOpenDevice (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine opens a direct handle to a device on behalf of a user mode
- application.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- ULONG Access;
- PKPROCESS CurrentProcess;
- PDEVICE Device;
- PIO_HANDLE Handle;
- ULONG HandleFlags;
- ULONG OpenFlags;
- PSYSTEM_CALL_OPEN_DEVICE Parameters;
- KSTATUS Status;
- CurrentProcess = PsGetCurrentProcess();
- ASSERT(CurrentProcess != PsGetKernelProcess());
- Handle = NULL;
- Parameters = (PSYSTEM_CALL_OPEN_DEVICE)SystemCallParameter;
- Parameters->Handle = INVALID_HANDLE;
- //
- // Set up the flags.
- //
- ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
- Access = (Parameters->Flags >> SYS_OPEN_ACCESS_SHIFT) & IO_ACCESS_MASK;
- OpenFlags = Parameters->Flags & SYS_OPEN_FLAG_MASK;
- //
- // Look up the device.
- //
- Device = IoGetDeviceByNumericId(Parameters->DeviceId);
- if (Device == NULL) {
- Status = STATUS_NO_SUCH_DEVICE;
- goto SysOpenDeviceEnd;
- }
- //
- // Open up the device.
- //
- Status = IoOpenDevice(Device, Access, OpenFlags, &Handle, NULL, NULL, NULL);
- ObReleaseReference(Device);
- if (!KSUCCESS(Status)) {
- goto SysOpenDeviceEnd;
- }
- //
- // Create a handle table entry for this open device.
- //
- HandleFlags = 0;
- if ((Parameters->Flags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
- HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- }
- Status = ObCreateHandle(CurrentProcess->HandleTable,
- Handle,
- HandleFlags,
- &(Parameters->Handle));
- if (!KSUCCESS(Status)) {
- goto SysOpenDeviceEnd;
- }
- Status = STATUS_SUCCESS;
- SysOpenDeviceEnd:
- if (!KSUCCESS(Status)) {
- if (Handle != NULL) {
- IoClose(Handle);
- }
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysClose (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine closes an I/O handle opened in user mode.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PKPROCESS CurrentProcess;
- PSYSTEM_CALL_CLOSE Parameters;
- CurrentProcess = PsGetCurrentProcess();
- ASSERT(CurrentProcess != PsGetKernelProcess());
- Parameters = (PSYSTEM_CALL_CLOSE)SystemCallParameter;
- Parameters->Status = IopSysClose(CurrentProcess, Parameters->Handle);
- return;
- }
- VOID
- IoSysPerformIo (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine performs I/O for user mode.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PKPROCESS CurrentProcess;
- PIO_HANDLE HandleValue;
- IO_BUFFER IoBuffer;
- PSYSTEM_CALL_PERFORM_IO Parameters;
- UINTN Size;
- KSTATUS Status;
- ULONG Timeout;
- CurrentProcess = PsGetCurrentProcess();
- Parameters = (PSYSTEM_CALL_PERFORM_IO)SystemCallParameter;
- Size = Parameters->Size;
- Parameters->Size = 0;
- HandleValue = ObGetHandleValue(CurrentProcess->HandleTable,
- Parameters->Handle,
- NULL);
- if (HandleValue == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysPerformIoEnd;
- }
- if (Size == 0) {
- Status = STATUS_SUCCESS;
- goto SysPerformIoEnd;
- }
- if ((Parameters->Buffer + Size > KERNEL_VA_START) ||
- (Parameters->Buffer + Size < Parameters->Buffer)) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysPerformIoEnd;
- }
- Timeout = Parameters->TimeoutInMilliseconds;
- ASSERT(SYS_WAIT_TIME_INDEFINITE == WAIT_TIME_INDEFINITE);
- //
- // Hopefully this I/O buffer will never reach a driver and only be used by
- // the cache. As such, don't pin down the pages just yet, allowing the
- // opportunity to stack-allocate the I/O buffer structure. If this buffer
- // does make it to a driver, a new I/O buffer structure will be temporarily
- // allocated to pin down the pages.
- //
- Status = MmInitializeIoBuffer(&IoBuffer,
- Parameters->Buffer,
- INVALID_PHYSICAL_ADDRESS,
- Size,
- 0);
- if (!KSUCCESS(Status)) {
- goto SysPerformIoEnd;
- }
- //
- // Perform the file I/O.
- //
- if ((Parameters->Flags & SYS_IO_FLAG_WRITE) != 0) {
- Status = IoWriteAtOffset(HandleValue,
- &IoBuffer,
- Parameters->Offset,
- Size,
- 0,
- Timeout,
- &(Parameters->Size),
- NULL);
- if (Status == STATUS_BROKEN_PIPE) {
- ASSERT(CurrentProcess != PsGetKernelProcess());
- PsSignalProcess(CurrentProcess, SIGNAL_BROKEN_PIPE, NULL);
- }
- } else {
- Status = IoReadAtOffset(HandleValue,
- &IoBuffer,
- Parameters->Offset,
- Size,
- 0,
- Timeout,
- &(Parameters->Size),
- NULL);
- }
- if (!KSUCCESS(Status)) {
- goto SysPerformIoEnd;
- }
- SysPerformIoEnd:
- if (HandleValue != NULL) {
- IoIoHandleReleaseReference(HandleValue);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysPerformVectoredIo (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine performs vectored I/O for user mode.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PKPROCESS CurrentProcess;
- PIO_HANDLE HandleValue;
- PIO_BUFFER IoBuffer;
- PSYSTEM_CALL_PERFORM_VECTORED_IO Parameters;
- UINTN Size;
- KSTATUS Status;
- ULONG Timeout;
- CurrentProcess = PsGetCurrentProcess();
- Parameters = (PSYSTEM_CALL_PERFORM_VECTORED_IO)SystemCallParameter;
- Size = Parameters->Size;
- Parameters->Size = 0;
- IoBuffer = NULL;
- HandleValue = ObGetHandleValue(CurrentProcess->HandleTable,
- Parameters->Handle,
- NULL);
- if (HandleValue == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysPerformVectoredIoEnd;
- }
- if (Size == 0) {
- Status = STATUS_SUCCESS;
- goto SysPerformVectoredIoEnd;
- }
- Timeout = Parameters->TimeoutInMilliseconds;
- ASSERT(SYS_WAIT_TIME_INDEFINITE == WAIT_TIME_INDEFINITE);
- //
- // Allocate an I/O buffer for this user mode buffer. Keep it in paged-pool,
- // and not pinned for now. If the particular I/O requests something more
- // serious, it will lock the buffer.
- //
- Status = MmCreateIoBufferFromVector(Parameters->VectorArray,
- FALSE,
- Parameters->VectorCount,
- &IoBuffer);
- if (!KSUCCESS(Status)) {
- goto SysPerformVectoredIoEnd;
- }
- //
- // Perform the file I/O.
- //
- if ((Parameters->Flags & SYS_IO_FLAG_WRITE) != 0) {
- Status = IoWriteAtOffset(HandleValue,
- IoBuffer,
- Parameters->Offset,
- Size,
- 0,
- Timeout,
- &(Parameters->Size),
- NULL);
- if (Status == STATUS_BROKEN_PIPE) {
- ASSERT(CurrentProcess != PsGetKernelProcess());
- PsSignalProcess(CurrentProcess, SIGNAL_BROKEN_PIPE, NULL);
- }
- } else {
- Status = IoReadAtOffset(HandleValue,
- IoBuffer,
- Parameters->Offset,
- Size,
- 0,
- Timeout,
- &(Parameters->Size),
- NULL);
- }
- if (!KSUCCESS(Status)) {
- goto SysPerformVectoredIoEnd;
- }
- SysPerformVectoredIoEnd:
- if (IoBuffer != NULL) {
- MmFreeIoBuffer(IoBuffer);
- }
- if (HandleValue != NULL) {
- IoIoHandleReleaseReference(HandleValue);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysFlush (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine flushes data to its backing device for user mode.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PKPROCESS CurrentProcess;
- ULONG FlushFlags;
- PIO_HANDLE HandleValue;
- PSYSTEM_CALL_FLUSH Parameters;
- KSTATUS Status;
- CurrentProcess = PsGetCurrentProcess();
- ASSERT(CurrentProcess != PsGetKernelProcess());
- FlushFlags = 0;
- Parameters = (PSYSTEM_CALL_FLUSH)SystemCallParameter;
- if ((Parameters->Flags & SYS_FLUSH_FLAG_ALL) != 0) {
- FlushFlags = FLUSH_FLAG_ALL;
- HandleValue = NULL;
- } else {
- HandleValue = ObGetHandleValue(CurrentProcess->HandleTable,
- Parameters->Handle,
- NULL);
- if (HandleValue == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysFlushEnd;
- }
- ASSERT(HandleValue != INVALID_HANDLE);
- if ((Parameters->Flags & SYS_FLUSH_FLAG_READ) != 0) {
- FlushFlags |= FLUSH_FLAG_READ;
- }
- if ((Parameters->Flags & SYS_FLUSH_FLAG_WRITE) != 0) {
- FlushFlags |= FLUSH_FLAG_WRITE;
- }
- if ((Parameters->Flags & SYS_FLUSH_FLAG_DISCARD) != 0) {
- FlushFlags |= FLUSH_FLAG_DISCARD;
- }
- }
- Status = IoFlush(HandleValue, 0, -1, FlushFlags);
- if (!KSUCCESS(Status)) {
- goto SysFlushEnd;
- }
- SysFlushEnd:
- if (HandleValue != NULL) {
- IoIoHandleReleaseReference(HandleValue);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysCreatePipe (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine creates a pipe on behalf of a user mode application.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PKPROCESS CurrentProcess;
- PIO_HANDLE Directory;
- ULONG HandleFlags;
- ULONG OpenFlags;
- PSYSTEM_CALL_CREATE_PIPE Parameters;
- PSTR PipePath;
- PIO_HANDLE ReadHandle;
- KSTATUS Status;
- PIO_HANDLE WriteHandle;
- CurrentProcess = PsGetCurrentProcess();
- ASSERT(CurrentProcess != PsGetKernelProcess());
- Directory = NULL;
- Parameters = (PSYSTEM_CALL_CREATE_PIPE)SystemCallParameter;
- Parameters->ReadHandle = INVALID_HANDLE;
- Parameters->WriteHandle = INVALID_HANDLE;
- ReadHandle = NULL;
- PipePath = NULL;
- WriteHandle = NULL;
- if (Parameters->PathLength != 0) {
- Status = MmCreateCopyOfUserModeString(Parameters->Path,
- Parameters->PathLength,
- FI_ALLOCATION_TAG,
- &PipePath);
- if (!KSUCCESS(Status)) {
- goto SysCreatePipeEnd;
- }
- }
- if (Parameters->Directory != INVALID_HANDLE) {
- Directory = ObGetHandleValue(CurrentProcess->HandleTable,
- Parameters->Directory,
- NULL);
- if (Directory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysCreatePipeEnd;
- }
- }
- if ((Parameters->OpenFlags &
- ~(SYS_OPEN_FLAG_NON_BLOCKING | SYS_OPEN_FLAG_CLOSE_ON_EXECUTE)) != 0) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysCreatePipeEnd;
- }
- OpenFlags = Parameters->OpenFlags & SYS_OPEN_FLAG_NON_BLOCKING;
- //
- // Create the pipe.
- //
- Status = IoCreatePipe(FALSE,
- Directory,
- PipePath,
- Parameters->PathLength,
- OpenFlags,
- Parameters->Permissions,
- &ReadHandle,
- &WriteHandle);
- if (!KSUCCESS(Status)) {
- goto SysCreatePipeEnd;
- }
- //
- // Create user mode handles if no path was specified.
- //
- if (PipePath == NULL) {
- //
- // Create handle table entries for these handles.
- //
- HandleFlags = 0;
- if ((Parameters->OpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
- HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- }
- Status = ObCreateHandle(CurrentProcess->HandleTable,
- ReadHandle,
- HandleFlags,
- &(Parameters->ReadHandle));
- if (!KSUCCESS(Status)) {
- goto SysCreatePipeEnd;
- }
- Status = ObCreateHandle(CurrentProcess->HandleTable,
- WriteHandle,
- HandleFlags,
- &(Parameters->WriteHandle));
- if (!KSUCCESS(Status)) {
- goto SysCreatePipeEnd;
- }
- } else {
- IoClose(ReadHandle);
- IoClose(WriteHandle);
- ReadHandle = NULL;
- WriteHandle = NULL;
- }
- Status = STATUS_SUCCESS;
- SysCreatePipeEnd:
- if (Directory != NULL) {
- IoIoHandleReleaseReference(Directory);
- }
- if (PipePath != NULL) {
- MmFreePagedPool(PipePath);
- }
- if (!KSUCCESS(Status)) {
- if (ReadHandle != NULL) {
- IoClose(ReadHandle);
- }
- if (WriteHandle != NULL) {
- IoClose(WriteHandle);
- }
- if (Parameters->ReadHandle != INVALID_HANDLE) {
- ObDestroyHandle(CurrentProcess->HandleTable,
- Parameters->ReadHandle);
- }
- if (Parameters->WriteHandle != INVALID_HANDLE) {
- ObDestroyHandle(CurrentProcess->HandleTable,
- Parameters->WriteHandle);
- }
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysGetCurrentDirectory (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine handles the system call requesting the path of the current
- working directory.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PPATH_POINT CurrentDirectory;
- PATH_POINT CurrentDirectoryCopy;
- PSYSTEM_CALL_GET_CURRENT_DIRECTORY Parameters;
- PPROCESS_PATHS Paths;
- PKPROCESS Process;
- PPATH_POINT RootDirectory;
- PATH_POINT RootDirectoryCopy;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallGetCurrentDirectory);
- Parameters = (PSYSTEM_CALL_GET_CURRENT_DIRECTORY)SystemCallParameter;
- Process = PsGetCurrentProcess();
- ASSERT(Process != PsGetKernelProcess());
- //
- // Get the path entries for this process's current directory and root
- // directory.
- //
- CurrentDirectory = NULL;
- RootDirectory = NULL;
- Paths = &(Process->Paths);
- KeAcquireQueuedLock(Paths->Lock);
- if (Parameters->Root != FALSE) {
- if (Paths->Root.PathEntry != NULL) {
- IO_COPY_PATH_POINT(&CurrentDirectoryCopy, &(Paths->Root));
- IO_PATH_POINT_ADD_REFERENCE(&CurrentDirectoryCopy);
- CurrentDirectory = &CurrentDirectoryCopy;
- }
- //
- // Leave the root NULL for now (i.e. the real root). It will get set to
- // the current directory if the caller does not have permission to
- // escape a changed root.
- //
- } else {
- ASSERT(Paths->CurrentDirectory.PathEntry != NULL);
- IO_COPY_PATH_POINT(&CurrentDirectoryCopy, &(Paths->CurrentDirectory));
- IO_PATH_POINT_ADD_REFERENCE(&CurrentDirectoryCopy);
- CurrentDirectory = &CurrentDirectoryCopy;
- if (Paths->Root.PathEntry != NULL) {
- IO_COPY_PATH_POINT(&RootDirectoryCopy, &(Paths->Root));
- IO_PATH_POINT_ADD_REFERENCE(&RootDirectoryCopy);
- RootDirectory = &RootDirectoryCopy;
- }
- }
- KeReleaseQueuedLock(Process->Paths.Lock);
- //
- // If the caller does not have permission to escape a changed root, then
- // pretend they're at the real root.
- //
- if ((Parameters->Root != FALSE) &&
- (!KSUCCESS(PsCheckPermission(PERMISSION_ESCAPE_CHROOT)))) {
- RootDirectory = CurrentDirectory;
- if (RootDirectory != NULL) {
- IO_PATH_POINT_ADD_REFERENCE(RootDirectory);
- }
- }
- Status = IopGetUserFilePath(CurrentDirectory,
- RootDirectory,
- Parameters->Buffer,
- &(Parameters->BufferSize));
- if (!KSUCCESS(Status)) {
- goto SysGetCurrentDirectoryEnd;
- }
- SysGetCurrentDirectoryEnd:
- if (CurrentDirectory != NULL) {
- IO_PATH_POINT_RELEASE_REFERENCE(CurrentDirectory);
- }
- if (RootDirectory != NULL) {
- IO_PATH_POINT_RELEASE_REFERENCE(RootDirectory);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysChangeDirectory (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine handles the system call requesting to change the current
- working directory.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- BOOL EscapeRoot;
- PIO_HANDLE ExistingHandle;
- PFILE_OBJECT FileObject;
- PIO_HANDLE NewHandle;
- PSTR NewPath;
- ULONG NewPathSize;
- PATH_POINT OldPathPoint;
- PSYSTEM_CALL_CHANGE_DIRECTORY Parameters;
- PPATH_POINT PathPoint;
- PKPROCESS Process;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallChangeDirectory);
- Parameters = (PSYSTEM_CALL_CHANGE_DIRECTORY)SystemCallParameter;
- EscapeRoot = FALSE;
- ExistingHandle = NULL;
- PathPoint = NULL;
- NewHandle = NULL;
- NewPath = NULL;
- Process = PsGetCurrentProcess();
- ASSERT(Process != PsGetKernelProcess());
- //
- // There are a few rules if the caller is trying to change the root. The
- // usual way to escape a changed root is to use an open directory
- // descriptor outside the changed root. Disallow this by refusing to change
- // the root if there's an open directory descriptor. Enforce a thread
- // count of one to prevent race conditions where directories are opened
- // just as the root changes.
- //
- if (Parameters->Root != FALSE) {
- Status = PsCheckPermission(PERMISSION_CHROOT);
- if (!KSUCCESS(Status)) {
- goto SysChangeDirectoryEnd;
- }
- if (Process->ThreadCount != 1) {
- Status = STATUS_PERMISSION_DENIED;
- goto SysChangeDirectoryEnd;
- }
- Parameters->Status = STATUS_SUCCESS;
- ObHandleTableIterate(Process->HandleTable,
- IopCheckForDirectoryHandlesIterationRoutine,
- &Status);
- if (!KSUCCESS(Parameters->Status)) {
- goto SysChangeDirectoryEnd;
- }
- //
- // If all parameters are invalid, the caller is requesting to escape
- // the root.
- //
- if ((Parameters->Handle == INVALID_HANDLE) &&
- (Parameters->Buffer == NULL) &&
- (Parameters->BufferLength == 0)) {
- Status = PsCheckPermission(PERMISSION_ESCAPE_CHROOT);
- if (!KSUCCESS(Status)) {
- goto SysChangeDirectoryEnd;
- }
- EscapeRoot = TRUE;
- }
- }
- //
- // If a handle was supplied, use the handle.
- //
- if (Parameters->Handle != INVALID_HANDLE) {
- ExistingHandle = ObGetHandleValue(Process->HandleTable,
- Parameters->Handle,
- NULL);
- if (ExistingHandle == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysChangeDirectoryEnd;
- }
- PathPoint = &(ExistingHandle->PathPoint);
- FileObject = PathPoint->PathEntry->FileObject;
- if ((FileObject->Properties.Type != IoObjectRegularDirectory) &&
- (FileObject->Properties.Type != IoObjectObjectDirectory)) {
- Status = STATUS_NOT_A_DIRECTORY;
- goto SysChangeDirectoryEnd;
- }
- ASSERT(FileObject == ExistingHandle->FileObject);
- //
- // More commonly a path was supplied, so open the path.
- //
- } else if (EscapeRoot == FALSE) {
- //
- // Create a copy of the user mode string so it cannot be manipulated
- // during the call.
- //
- NewPathSize = Parameters->BufferLength;
- Status = MmCreateCopyOfUserModeString(Parameters->Buffer,
- NewPathSize,
- FI_ALLOCATION_TAG,
- &NewPath);
- if (!KSUCCESS(Status)) {
- goto SysChangeDirectoryEnd;
- }
- //
- // Open up the new working directory.
- //
- Status = IoOpen(FALSE,
- NULL,
- NewPath,
- NewPathSize,
- 0,
- OPEN_FLAG_DIRECTORY,
- FILE_PERMISSION_NONE,
- &NewHandle);
- if (!KSUCCESS(Status)) {
- goto SysChangeDirectoryEnd;
- }
- PathPoint = &(NewHandle->PathPoint);
- //
- // The caller is escaping back to the one true root.
- //
- } else {
- PathPoint = &IoPathPointRoot;
- }
- //
- // Replace the current working directory or root directory.
- //
- IO_PATH_POINT_ADD_REFERENCE(PathPoint);
- KeAcquireQueuedLock(Process->Paths.Lock);
- if (Parameters->Root != FALSE) {
- IO_COPY_PATH_POINT(&OldPathPoint, &(Process->Paths.Root));
- IO_COPY_PATH_POINT(&(Process->Paths.Root), PathPoint);
- } else {
- IO_COPY_PATH_POINT(&OldPathPoint, &(Process->Paths.CurrentDirectory));
- IO_COPY_PATH_POINT(&(Process->Paths.CurrentDirectory), PathPoint);
- }
- KeReleaseQueuedLock(Process->Paths.Lock);
- if (OldPathPoint.PathEntry != NULL) {
- IO_PATH_POINT_RELEASE_REFERENCE(&OldPathPoint);
- }
- Status = STATUS_SUCCESS;
- SysChangeDirectoryEnd:
- if (ExistingHandle != NULL) {
- IoIoHandleReleaseReference(ExistingHandle);
- }
- if (NewHandle != NULL) {
- IoClose(NewHandle);
- }
- if (NewPath != NULL) {
- MmFreePagedPool(NewPath);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysPoll (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine handles the poll system call, which waits on several I/O
- handles.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- ULONG AllocationSize;
- ULONG DescriptorCount;
- ULONG DescriptorIndex;
- PPOLL_DESCRIPTOR Descriptors;
- BOOL ErrorEventsOccurred;
- PFILE_OBJECT FileObject;
- HANDLE Handle;
- BOOL HaveRegularFiles;
- PIO_HANDLE IoHandle;
- PIO_OBJECT_STATE IoObjectState;
- ULONG MaskedEvents;
- ULONGLONG Microseconds;
- ULONGLONG ObjectIndex;
- SIGNAL_SET OldSignalSet;
- PSYSTEM_CALL_POLL PollInformation;
- PKPROCESS Process;
- BOOL RestoreSignalMask;
- ULONG SelectedDescriptors;
- SIGNAL_SET SignalMask;
- KSTATUS Status;
- PKTHREAD Thread;
- PPOLL_DESCRIPTOR UserDescriptors;
- ULONG WaitEvents;
- PVOID *WaitObjects;
- Descriptors = NULL;
- ErrorEventsOccurred = FALSE;
- HaveRegularFiles = FALSE;
- PollInformation = (PSYSTEM_CALL_POLL)SystemCallParameter;
- DescriptorCount = PollInformation->DescriptorCount;
- Thread = KeGetCurrentThread();
- Process = Thread->OwningProcess;
- RestoreSignalMask = FALSE;
- SelectedDescriptors = 0;
- WaitObjects = NULL;
- //
- // Set the signal mask if supplied.
- //
- if (PollInformation->SignalMask != NULL) {
- Status = MmCopyFromUserMode(&SignalMask,
- PollInformation->SignalMask,
- sizeof(SIGNAL_SET));
- if (!KSUCCESS(Status)) {
- goto PollEnd;
- }
- PsSetSignalMask(&SignalMask, &OldSignalSet);
- RestoreSignalMask = TRUE;
- }
- //
- // Polling nothing is easy.
- //
- if ((PollInformation->Descriptors == NULL) || (DescriptorCount == 0)) {
- Microseconds = PollInformation->TimeoutInMilliseconds *
- MICROSECONDS_PER_MILLISECOND;
- Status = KeDelayExecution(TRUE, FALSE, Microseconds);
- goto PollEnd;
- }
- UserDescriptors = PollInformation->Descriptors;
- //
- // Allocate space for a kernel mode array of poll descriptors.
- //
- AllocationSize = sizeof(POLL_DESCRIPTOR) * DescriptorCount;
- Descriptors = MmAllocatePagedPool(AllocationSize, IO_ALLOCATION_TAG);
- if (Descriptors == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto PollEnd;
- }
- Status = MmCopyFromUserMode(Descriptors, UserDescriptors, AllocationSize);
- if (!KSUCCESS(Status)) {
- RtlZeroMemory(Descriptors, AllocationSize);
- goto PollEnd;
- }
- //
- // Clear the returned events in the array, and translate the user mode
- // handles into kernel mode handles.
- //
- for (DescriptorIndex = 0;
- DescriptorIndex < DescriptorCount;
- DescriptorIndex += 1) {
- Handle = Descriptors[DescriptorIndex].Handle;
- Descriptors[DescriptorIndex].ReturnedEvents = 0;
- if (Handle == INVALID_HANDLE) {
- Descriptors[DescriptorIndex].Handle = NULL;
- continue;
- }
- Descriptors[DescriptorIndex].Handle =
- ObGetHandleValue(Process->HandleTable, Handle, NULL);
- if (Descriptors[DescriptorIndex].Handle == NULL) {
- Descriptors[DescriptorIndex].ReturnedEvents |=
- POLL_EVENT_INVALID_HANDLE;
- ErrorEventsOccurred = TRUE;
- }
- }
- //
- // Allocate space for the wait objects, assuming the worst case that every
- // descriptor wants to wait on error, read, high priority read, write, and
- // high priority write.
- //
- AllocationSize = 5 * DescriptorCount * sizeof(PVOID);
- WaitObjects = MmAllocatePagedPool(AllocationSize, IO_ALLOCATION_TAG);
- if (WaitObjects == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto PollEnd;
- }
- RtlZeroMemory(WaitObjects, AllocationSize);
- //
- // Add all the qualifying objects to the array of things to wait for.
- //
- ObjectIndex = 0;
- for (DescriptorIndex = 0;
- DescriptorIndex < DescriptorCount;
- DescriptorIndex += 1) {
- WaitEvents = Descriptors[DescriptorIndex].Events;
- IoHandle = Descriptors[DescriptorIndex].Handle;
- if ((WaitEvents == 0) || (IoHandle == NULL)) {
- continue;
- }
- FileObject = IoHandle->FileObject;
- //
- // Regular files and directories always poll TRUE for reading and
- // writing. Only look at the events for non-file descriptors.
- //
- ASSERT(FileObject->Properties.Type != IoObjectSymbolicLink);
- if ((FileObject->Properties.Type == IoObjectRegularFile) ||
- (FileObject->Properties.Type == IoObjectRegularDirectory) ||
- (FileObject->Properties.Type == IoObjectObjectDirectory) ||
- (FileObject->Properties.Type == IoObjectSharedMemoryObject)) {
- HaveRegularFiles = TRUE;
- continue;
- }
- IoObjectState = FileObject->IoState;
- ASSERT(IoObjectState != NULL);
- //
- // Always wait on the error event.
- //
- WaitObjects[ObjectIndex] = IoObjectState->ErrorEvent;
- ObjectIndex += 1;
- if ((WaitEvents & POLL_EVENT_IN) != 0) {
- WaitObjects[ObjectIndex] = IoObjectState->ReadEvent;
- ObjectIndex += 1;
- }
- if (((WaitEvents & POLL_EVENT_IN_HIGH_PRIORITY) != 0) &&
- (IoObjectState->ReadHighPriorityEvent != NULL)) {
- WaitObjects[ObjectIndex] = IoObjectState->ReadHighPriorityEvent;
- ObjectIndex += 1;
- }
- if ((WaitEvents & POLL_EVENT_OUT) != 0) {
- WaitObjects[ObjectIndex] = IoObjectState->WriteEvent;
- ObjectIndex += 1;
- }
- if (((WaitEvents & POLL_EVENT_OUT_HIGH_PRIORITY) != 0) &&
- (IoObjectState->WriteHighPriorityEvent != NULL)) {
- WaitObjects[ObjectIndex] = IoObjectState->WriteHighPriorityEvent;
- ObjectIndex += 1;
- }
- }
- ASSERT(ObjectIndex <= 5 * DescriptorCount);
- //
- // Wait on this list of objects.
- //
- ASSERT((ULONG)ObjectIndex == ObjectIndex);
- if ((ErrorEventsOccurred == FALSE) && (HaveRegularFiles == FALSE)) {
- Status = ObWaitOnObjects(
- WaitObjects,
- ObjectIndex,
- WAIT_FLAG_INTERRUPTIBLE,
- PollInformation->TimeoutInMilliseconds,
- NULL,
- NULL);
- if (!KSUCCESS(Status)) {
- goto PollEnd;
- }
- }
- //
- // Loop through and read out all the poll flags.
- //
- for (DescriptorIndex = 0;
- DescriptorIndex < DescriptorCount;
- DescriptorIndex += 1) {
- WaitEvents = Descriptors[DescriptorIndex].Events;
- IoHandle = Descriptors[DescriptorIndex].Handle;
- if ((IoHandle == NULL) || (WaitEvents == 0)) {
- continue;
- }
- //
- // If this descriptor fits the bill, increment the count of
- // selected descriptors.
- //
- FileObject = IoHandle->FileObject;
- if ((FileObject->Properties.Type == IoObjectRegularFile) ||
- (FileObject->Properties.Type == IoObjectRegularDirectory) ||
- (FileObject->Properties.Type == IoObjectObjectDirectory) ||
- (FileObject->Properties.Type == IoObjectSharedMemoryObject)) {
- MaskedEvents = WaitEvents & POLL_NONMASKABLE_FILE_EVENTS;
- } else {
- IoObjectState = FileObject->IoState;
- ASSERT(IoObjectState != NULL);
- //
- // The I/O object state maintains a bitmask of all the currently
- // signaled poll events. AND this with the requested events to get
- // the returned events for this descriptor.
- //
- MaskedEvents = IoObjectState->Events &
- (WaitEvents | POLL_NONMASKABLE_EVENTS);
- }
- if (MaskedEvents != 0) {
- SelectedDescriptors += 1;
- }
- Descriptors[DescriptorIndex].ReturnedEvents |= MaskedEvents;
- Status = MmUserWrite32(
- &(UserDescriptors[DescriptorIndex].ReturnedEvents),
- Descriptors[DescriptorIndex].ReturnedEvents);
- if (Status == FALSE) {
- Status = STATUS_ACCESS_VIOLATION;
- goto PollEnd;
- }
- }
- Status = STATUS_SUCCESS;
- PollEnd:
- if (RestoreSignalMask != FALSE) {
- //
- // Queue up signals before resetting the mask.
- //
- PsCheckRuntimeTimers(Thread);
- PsDispatchPendingSignals(Thread, TrapFrame);
- PsSetSignalMask(&OldSignalSet, NULL);
- }
- if (WaitObjects != NULL) {
- MmFreePagedPool(WaitObjects);
- }
- if (Descriptors != NULL) {
- //
- // For any handle that was successfully looked up, release the
- // reference that lookup added.
- //
- for (DescriptorIndex = 0;
- DescriptorIndex < DescriptorCount;
- DescriptorIndex += 1) {
- if (Descriptors[DescriptorIndex].Handle != NULL) {
- IoIoHandleReleaseReference(Descriptors[DescriptorIndex].Handle);
- }
- }
- MmFreePagedPool(Descriptors);
- }
- PollInformation->Status = Status;
- PollInformation->DescriptorsSelected = SelectedDescriptors;
- return;
- }
- VOID
- IoSysDuplicateHandle (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine implements the system call for duplicating a file handle.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- ULONG HandleFlags;
- PIO_HANDLE IoHandle;
- PVOID OldValue;
- PSYSTEM_CALL_DUPLICATE_HANDLE Parameters;
- PKPROCESS Process;
- KSTATUS Status;
- Parameters = (PSYSTEM_CALL_DUPLICATE_HANDLE)SystemCallParameter;
- Process = PsGetCurrentProcess();
- //
- // First check to see if the old handle is valid (and take a reference on
- // it).
- //
- IoHandle = ObGetHandleValue(Process->HandleTable,
- Parameters->OldHandle,
- NULL);
- if (IoHandle == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysDuplicateHandleEnd;
- }
- HandleFlags = 0;
- if ((Parameters->OpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
- HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- }
- //
- // If the new handle and the old handle are the same, then just return
- // success. That is unless the caller was trying to set the close on
- // execute flag, which is an illegal way to try and do that.
- //
- if (Parameters->OldHandle == Parameters->NewHandle) {
- Status = STATUS_SUCCESS;
- if (HandleFlags != 0) {
- Status = STATUS_INVALID_PARAMETER;
- }
- goto SysDuplicateHandleEnd;
- }
- //
- // If the caller doesn't care where the handle comes from, then allocate
- // any handle.
- //
- if (Parameters->NewHandle == INVALID_HANDLE) {
- Status = ObCreateHandle(Process->HandleTable,
- IoHandle,
- HandleFlags,
- &(Parameters->NewHandle));
- if (!KSUCCESS(Status)) {
- goto SysDuplicateHandleEnd;
- }
- //
- // Replace a specific handle value.
- //
- } else {
- Status = ObReplaceHandleValue(Process->HandleTable,
- Parameters->NewHandle,
- IoHandle,
- HandleFlags,
- &OldValue,
- NULL);
- if (!KSUCCESS(Status)) {
- goto SysDuplicateHandleEnd;
- }
- //
- // Close the old handle.
- //
- if (OldValue != NULL) {
- IopRemoveFileLocks(OldValue, Process);
- IoClose(OldValue);
- }
- }
- //
- // The reference taken during lookup is given to the new handle, so
- // NULL out the I/O handle so it doesn't get released at the end.
- //
- IoHandle = NULL;
- Status = STATUS_SUCCESS;
- SysDuplicateHandleEnd:
- if (IoHandle != NULL) {
- IoIoHandleReleaseReference(IoHandle);
- }
- Parameters->Status = Status;
- }
- VOID
- IoSysFileControl (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine implements the file control system call.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- BOOL Asynchronous;
- PIO_ASYNC_STATE AsyncState;
- BOOL Blocking;
- UINTN CopyOutSize;
- PSYSTEM_CALL_FILE_CONTROL FileControl;
- PFILE_OBJECT FileObject;
- ULONG Flags;
- PIO_HANDLE IoHandle;
- PIO_OBJECT_STATE IoState;
- FILE_CONTROL_PARAMETERS_UNION LocalParameters;
- ULONG Mask;
- PKPROCESS Process;
- PATH_POINT RootPathPoint;
- ULONG SetFlags;
- KSTATUS Status;
- PKTHREAD Thread;
- ASSERT(SystemCallNumber == SystemCallFileControl);
- Blocking = FALSE;
- CopyOutSize = 0;
- Flags = 0;
- FileControl = (PSYSTEM_CALL_FILE_CONTROL)SystemCallParameter;
- Process = PsGetCurrentProcess();
- IoHandle = NULL;
- //
- // Get the handle and the flags. The "close from" operation is the only
- // exception, it doesn't actually need a valid handle.
- //
- if (FileControl->Command != FileControlCommandCloseFrom) {
- IoHandle = ObGetHandleValue(Process->HandleTable,
- FileControl->File,
- &Flags);
- if (IoHandle == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysFileControlEnd;
- }
- }
- switch (FileControl->Command) {
- case FileControlCommandDuplicate:
- if (FileControl->Parameters == NULL) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysFileControlEnd;
- }
- Status = MmCopyFromUserMode(&LocalParameters,
- FileControl->Parameters,
- sizeof(HANDLE));
- if (!KSUCCESS(Status)) {
- goto SysFileControlEnd;
- }
- if (LocalParameters.DuplicateDescriptor >= (HANDLE)OB_MAX_HANDLES) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysFileControlEnd;
- }
- Flags &= ~FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- //
- // Increment the reference count on the I/O handle first, since as soon
- // as the new descriptor is created user mode could come in on a
- // different thread and close it.
- //
- IoIoHandleAddReference(IoHandle);
- Status = ObCreateHandle(Process->HandleTable,
- IoHandle,
- Flags,
- &(LocalParameters.DuplicateDescriptor));
- if (KSUCCESS(Status)) {
- CopyOutSize = sizeof(HANDLE);
- } else {
- IoIoHandleReleaseReference(IoHandle);
- }
- break;
- case FileControlCommandGetFlags:
- LocalParameters.Flags = Flags;
- CopyOutSize = sizeof(ULONG);
- break;
- case FileControlCommandSetFlags:
- if (FileControl->Parameters == NULL) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysFileControlEnd;
- }
- Status = MmCopyFromUserMode(&LocalParameters,
- FileControl->Parameters,
- sizeof(ULONG));
- if (!KSUCCESS(Status)) {
- goto SysFileControlEnd;
- }
- SetFlags = LocalParameters.Flags;
- Flags &= ~FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- if ((SetFlags & FILE_DESCRIPTOR_CLOSE_ON_EXECUTE) != 0) {
- Flags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- SetFlags &= ~FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- }
- if (SetFlags != 0) {
- Status = STATUS_INVALID_PARAMETER;
- } else {
- Status = ObGetSetHandleFlags(Process->HandleTable,
- FileControl->File,
- TRUE,
- &Flags);
- if (!KSUCCESS(Status)) {
- goto SysFileControlEnd;
- }
- }
- break;
- case FileControlCommandGetStatusAndAccess:
- ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
- Flags = (IoHandle->OpenFlags & SYS_OPEN_FLAG_MASK) |
- (IoHandle->Access << SYS_OPEN_ACCESS_SHIFT);
- LocalParameters.Flags = Flags;
- CopyOutSize = sizeof(ULONG);
- break;
- case FileControlCommandSetStatus:
- if (FileControl->Parameters == NULL) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysFileControlEnd;
- }
- Status = MmCopyFromUserMode(&LocalParameters,
- FileControl->Parameters,
- sizeof(ULONG));
- if (!KSUCCESS(Status)) {
- goto SysFileControlEnd;
- }
- //
- // Set the new flags except for the asynchronous flag, which is handled
- // by another function.
- //
- ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
- Mask = SYS_FILE_CONTROL_EDITABLE_STATUS_FLAGS & ~OPEN_FLAG_ASYNCHRONOUS;
- Flags = LocalParameters.Flags & Mask;
- IoHandle->OpenFlags = (IoHandle->OpenFlags & ~Mask) | Flags;
- Status = STATUS_SUCCESS;
- //
- // If the asynchronous flag changed, make adjustments.
- //
- Flags = LocalParameters.Flags;
- if (((Flags ^ IoHandle->OpenFlags) & OPEN_FLAG_ASYNCHRONOUS) != 0) {
- Asynchronous = FALSE;
- if ((Flags & OPEN_FLAG_ASYNCHRONOUS) != 0) {
- Asynchronous = TRUE;
- }
- Status = IoSetHandleAsynchronous(IoHandle,
- FileControl->File,
- Asynchronous);
- }
- break;
- //
- // Return the process ID that gets async IO signals.
- //
- case FileControlCommandGetSignalOwner:
- LocalParameters.Owner = 0;
- IoState = IoHandle->FileObject->IoState;
- if (IoState->Async != NULL) {
- LocalParameters.Owner = IoState->Async->Owner;
- }
- CopyOutSize = sizeof(PROCESS_ID);
- Status = STATUS_SUCCESS;
- break;
- //
- // Set the process ID that gets async IO signals. Also record the user
- // identity and permissions to ensure that IO signals are not sent to
- // processes this process would not ordinarily have been able to send
- // signals to.
- //
- case FileControlCommandSetSignalOwner:
- Status = MmCopyFromUserMode(&LocalParameters,
- FileControl->Parameters,
- sizeof(PROCESS_ID));
- if (!KSUCCESS(Status)) {
- goto SysFileControlEnd;
- }
- IoState = IoHandle->FileObject->IoState;
- //
- // Signaling process groups is currently not supported.
- //
- if (LocalParameters.Owner <= 0) {
- Status = STATUS_NOT_SUPPORTED;
- break;
- }
- AsyncState = IopGetAsyncState(IoState);
- if (AsyncState == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- break;
- }
- Thread = KeGetCurrentThread();
- KeAcquireQueuedLock(AsyncState->Lock);
- AsyncState->Owner = LocalParameters.Owner;
- AsyncState->SetterUserId = Thread->Identity.RealUserId;
- AsyncState->SetterEffectiveUserId = Thread->Identity.EffectiveUserId;
- AsyncState->SetterPermissions = Thread->Permissions.Effective;
- KeReleaseQueuedLock(AsyncState->Lock);
- Status = STATUS_SUCCESS;
- break;
- case FileControlCommandGetLock:
- RtlZeroMemory(&(LocalParameters.FileLock), sizeof(FILE_LOCK));
- Status = IopGetFileLock(IoHandle, &(LocalParameters.FileLock));
- if (KSUCCESS(Status)) {
- CopyOutSize = sizeof(FILE_LOCK);
- }
- break;
- //
- // Toggle the blocking local and fall through to the set lock command.
- //
- case FileControlCommandBlockingSetLock:
- Blocking = TRUE;
- case FileControlCommandSetLock:
- if (FileControl->Parameters == NULL) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysFileControlEnd;
- }
- Status = MmCopyFromUserMode(&LocalParameters,
- FileControl->Parameters,
- sizeof(FILE_LOCK));
- if (!KSUCCESS(Status)) {
- goto SysFileControlEnd;
- }
- Status = IopSetFileLock(IoHandle,
- &(LocalParameters.FileLock),
- Blocking);
- break;
- case FileControlCommandGetFileInformation:
- RtlZeroMemory(&LocalParameters, sizeof(SET_FILE_INFORMATION));
- Status = IoSetFileInformation(
- FALSE,
- IoHandle,
- &(LocalParameters.SetFileInformation));
- if (KSUCCESS(Status)) {
- CopyOutSize = sizeof(SET_FILE_INFORMATION);
- }
- break;
- case FileControlCommandSetFileInformation:
- if (FileControl->Parameters == NULL) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysFileControlEnd;
- }
- Status = MmCopyFromUserMode(&LocalParameters,
- FileControl->Parameters,
- sizeof(SET_FILE_INFORMATION));
- if (!KSUCCESS(Status)) {
- goto SysFileControlEnd;
- }
- Status = IoSetFileInformation(
- FALSE,
- IoHandle,
- &(LocalParameters.SetFileInformation));
- break;
- //
- // Attempt to set the directory flag on the given descriptor so that
- // reads from the directory will succeed. This is used to support the
- // fdopendir C library function.
- //
- case FileControlCommandSetDirectoryFlag:
- Status = STATUS_NOT_A_DIRECTORY;
- FileObject = IoHandle->FileObject;
- if ((FileObject->Properties.Type == IoObjectRegularDirectory) ||
- (FileObject->Properties.Type == IoObjectObjectDirectory)) {
- IoHandle->OpenFlags |= OPEN_FLAG_DIRECTORY;
- Status = STATUS_SUCCESS;
- }
- break;
- case FileControlCommandCloseFrom:
- Status = IoCloseProcessHandles(Process, FileControl->File);
- break;
- //
- // Get the full path of path entry associated with the given I/O handle, if
- // possible.
- //
- case FileControlCommandGetPath:
- KeAcquireQueuedLock(Process->Paths.Lock);
- if (Process->Paths.Root.PathEntry != NULL) {
- IO_COPY_PATH_POINT(&RootPathPoint, &(Process->Paths.Root));
- IO_PATH_POINT_ADD_REFERENCE(&RootPathPoint);
- } else {
- IO_COPY_PATH_POINT(&RootPathPoint, &IoPathPointRoot);
- IO_PATH_POINT_ADD_REFERENCE(&RootPathPoint);
- }
- KeReleaseQueuedLock(Process->Paths.Lock);
- if (FileControl->Parameters == NULL) {
- Status = STATUS_INVALID_PARAMETER;
- goto SysFileControlEnd;
- }
- Status = MmCopyFromUserMode(&LocalParameters,
- FileControl->Parameters,
- sizeof(FILE_PATH));
- if (!KSUCCESS(Status)) {
- goto SysFileControlEnd;
- }
- Status = IopGetUserFilePath(&(IoHandle->PathPoint),
- &RootPathPoint,
- LocalParameters.FilePath.Path,
- &(LocalParameters.FilePath.PathSize));
- IO_PATH_POINT_RELEASE_REFERENCE(&RootPathPoint);
- if (KSUCCESS(Status)) {
- CopyOutSize = sizeof(FILE_PATH);
- }
- break;
- default:
- Status = STATUS_INVALID_PARAMETER;
- break;
- }
- SysFileControlEnd:
- if (CopyOutSize != 0) {
- Status = STATUS_INVALID_PARAMETER;
- if (FileControl->Parameters != NULL) {
- Status = MmCopyToUserMode(FileControl->Parameters,
- &LocalParameters,
- CopyOutSize);
- }
- }
- FileControl->Status = Status;
- if (IoHandle != NULL) {
- IoIoHandleReleaseReference(IoHandle);
- }
- return;
- }
- VOID
- IoSysGetSetFileInformation (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine implements the get/set file information system call.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PIO_HANDLE Directory;
- PIO_HANDLE IoHandle;
- ULONG OpenFlags;
- PSYSTEM_CALL_GET_SET_FILE_INFORMATION Parameters;
- PSTR PathCopy;
- PKPROCESS Process;
- KSTATUS Status;
- Directory = NULL;
- IoHandle = NULL;
- PathCopy = NULL;
- Parameters = (PSYSTEM_CALL_GET_SET_FILE_INFORMATION)SystemCallParameter;
- //
- // Copy the path string out of user mode.
- //
- Status = MmCreateCopyOfUserModeString(Parameters->FilePath,
- Parameters->FilePathSize,
- IO_ALLOCATION_TAG,
- &PathCopy);
- if (!KSUCCESS(Status)) {
- goto SysGetSetFileInformationEnd;
- }
- //
- // Open up the file for getting or setting the information.
- //
- OpenFlags = 0;
- if (Parameters->FollowLink == FALSE) {
- OpenFlags |= OPEN_FLAG_SYMBOLIC_LINK;
- }
- if (Parameters->Directory != INVALID_HANDLE) {
- Process = PsGetCurrentProcess();
- Directory = ObGetHandleValue(Process->HandleTable,
- Parameters->Directory,
- NULL);
- if (Directory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysGetSetFileInformationEnd;
- }
- }
- Status = IoOpen(FALSE,
- Directory,
- PathCopy,
- Parameters->FilePathSize,
- 0,
- OpenFlags,
- FILE_PERMISSION_NONE,
- &IoHandle);
- if (!KSUCCESS(Status)) {
- goto SysGetSetFileInformationEnd;
- }
- Status = IoSetFileInformation(FALSE, IoHandle, &(Parameters->Request));
- SysGetSetFileInformationEnd:
- if (Directory != NULL) {
- IoIoHandleReleaseReference(Directory);
- }
- if (IoHandle != NULL) {
- IoClose(IoHandle);
- }
- if (PathCopy != NULL) {
- MmFreePagedPool(PathCopy);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysSeek (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine implements the file seek system call.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PIO_HANDLE IoHandle;
- PKPROCESS Process;
- PSYSTEM_CALL_SEEK Request;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallSeek);
- Request = (PSYSTEM_CALL_SEEK)SystemCallParameter;
- Process = PsGetCurrentProcess();
- IoHandle = ObGetHandleValue(Process->HandleTable, Request->Handle, NULL);
- if (IoHandle == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysSeekEnd;
- }
- Status = IoSeek(IoHandle,
- Request->Command,
- Request->Offset,
- &(Request->Offset));
- if (!KSUCCESS(Status)) {
- goto SysSeekEnd;
- }
- SysSeekEnd:
- Request->Status = Status;
- if (IoHandle != NULL) {
- IoIoHandleReleaseReference(IoHandle);
- }
- return;
- }
- VOID
- IoSysCreateSymbolicLink (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine creates a symbolic link.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PIO_HANDLE Directory;
- PSTR Link;
- ULONG LinkSize;
- PSTR LinkTarget;
- ULONG LinkTargetSize;
- PSYSTEM_CALL_CREATE_SYMBOLIC_LINK Parameters;
- PKPROCESS Process;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallCreateSymbolicLink);
- Directory = NULL;
- Parameters = (PSYSTEM_CALL_CREATE_SYMBOLIC_LINK)SystemCallParameter;
- Link = NULL;
- LinkTarget = NULL;
- LinkSize = Parameters->PathSize;
- LinkTargetSize = Parameters->LinkDestinationBufferSize;
- Status = MmCreateCopyOfUserModeString(Parameters->Path,
- LinkSize,
- PATH_ALLOCATION_TAG,
- &Link);
- if (!KSUCCESS(Status)) {
- goto SysCreateSymbolicLinkEnd;
- }
- Status = MmCreateCopyOfUserModeString(Parameters->LinkDestinationBuffer,
- LinkTargetSize,
- PATH_ALLOCATION_TAG,
- &LinkTarget);
- if (!KSUCCESS(Status)) {
- goto SysCreateSymbolicLinkEnd;
- }
- if (Parameters->Directory != INVALID_HANDLE) {
- Process = PsGetCurrentProcess();
- Directory = ObGetHandleValue(Process->HandleTable,
- Parameters->Directory,
- NULL);
- if (Directory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysCreateSymbolicLinkEnd;
- }
- }
- Status = IoCreateSymbolicLink(FALSE,
- Directory,
- Link,
- LinkSize,
- LinkTarget,
- LinkTargetSize);
- SysCreateSymbolicLinkEnd:
- if (Directory != NULL) {
- IoIoHandleReleaseReference(Directory);
- }
- if (Link != NULL) {
- MmFreePagedPool(Link);
- }
- if (LinkTarget != NULL) {
- MmFreePagedPool(LinkTarget);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysReadSymbolicLink (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine reads and returns the destination of a symbolic link.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PIO_HANDLE Directory;
- PIO_HANDLE Handle;
- PSTR Link;
- ULONG LinkSize;
- PSTR LinkTarget;
- ULONG LinkTargetSize;
- PSYSTEM_CALL_READ_SYMBOLIC_LINK Parameters;
- PKPROCESS Process;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallReadSymbolicLink);
- Directory = NULL;
- Handle = NULL;
- Link = NULL;
- LinkTarget = NULL;
- LinkTargetSize = 0;
- Parameters = (PSYSTEM_CALL_READ_SYMBOLIC_LINK)SystemCallParameter;
- LinkSize = Parameters->PathSize;
- Status = MmCreateCopyOfUserModeString(Parameters->Path,
- LinkSize,
- PATH_ALLOCATION_TAG,
- &Link);
- if (!KSUCCESS(Status)) {
- goto SysReadSymbolicLinkEnd;
- }
- if (Parameters->Directory != INVALID_HANDLE) {
- Process = PsGetCurrentProcess();
- Directory = ObGetHandleValue(Process->HandleTable,
- Parameters->Directory,
- NULL);
- if (Directory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysReadSymbolicLinkEnd;
- }
- }
- Status = IoOpen(FALSE,
- Directory,
- Link,
- LinkSize,
- IO_ACCESS_READ,
- OPEN_FLAG_SYMBOLIC_LINK,
- FILE_PERMISSION_NONE,
- &Handle);
- if (!KSUCCESS(Status)) {
- goto SysReadSymbolicLinkEnd;
- }
- Status = IoReadSymbolicLink(Handle,
- PATH_ALLOCATION_TAG,
- &LinkTarget,
- &LinkTargetSize);
- if (!KSUCCESS(Status)) {
- goto SysReadSymbolicLinkEnd;
- }
- if (LinkTargetSize != 0) {
- LinkTargetSize -= 1;
- }
- if (Parameters->LinkDestinationBufferSize < LinkTargetSize) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto SysReadSymbolicLinkEnd;
- }
- Status = MmCopyToUserMode(Parameters->LinkDestinationBuffer,
- LinkTarget,
- LinkTargetSize);
- if (!KSUCCESS(Status)) {
- goto SysReadSymbolicLinkEnd;
- }
- SysReadSymbolicLinkEnd:
- if (Directory != NULL) {
- IoIoHandleReleaseReference(Directory);
- }
- if (Handle != NULL) {
- IoClose(Handle);
- }
- if (Link != NULL) {
- MmFreePagedPool(Link);
- }
- if (LinkTarget != NULL) {
- MmFreePagedPool(LinkTarget);
- }
- Parameters->LinkDestinationSize = LinkTargetSize;
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysCreateHardLink (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine creates a hard link.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PSYSTEM_CALL_CREATE_HARD_LINK Parameters;
- ASSERT(SystemCallNumber == SystemCallCreateHardLink);
- Parameters = (PSYSTEM_CALL_CREATE_HARD_LINK)SystemCallParameter;
- //
- // TODO: Add support for creating a hard link.
- //
- Parameters->Status = STATUS_NOT_IMPLEMENTED;
- return;
- }
- VOID
- IoSysDelete (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine deletes an entry from a directory.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- ULONG DeleteFlags;
- PIO_HANDLE Directory;
- PSYSTEM_CALL_DELETE Parameters;
- PSTR PathCopy;
- PKPROCESS Process;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallDelete);
- Directory = NULL;
- Parameters = (PSYSTEM_CALL_DELETE)SystemCallParameter;
- PathCopy = NULL;
- Status = MmCreateCopyOfUserModeString(Parameters->Path,
- Parameters->PathSize,
- IO_ALLOCATION_TAG,
- &PathCopy);
- if (!KSUCCESS(Status)) {
- goto SysDeleteEnd;
- }
- if (Parameters->Directory != INVALID_HANDLE) {
- Process = PsGetCurrentProcess();
- Directory = ObGetHandleValue(Process->HandleTable,
- Parameters->Directory,
- NULL);
- if (Directory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysDeleteEnd;
- }
- }
- DeleteFlags = 0;
- if ((Parameters->Flags & SYS_DELETE_FLAG_SHARED_MEMORY) != 0) {
- DeleteFlags |= DELETE_FLAG_SHARED_MEMORY;
- }
- if ((Parameters->Flags & SYS_DELETE_FLAG_DIRECTORY) != 0) {
- DeleteFlags |= DELETE_FLAG_DIRECTORY;
- }
- Status = IoDelete(FALSE,
- Directory,
- PathCopy,
- Parameters->PathSize,
- DeleteFlags);
- if (!KSUCCESS(Status)) {
- goto SysDeleteEnd;
- }
- SysDeleteEnd:
- if (Directory != NULL) {
- IoIoHandleReleaseReference(Directory);
- }
- if (PathCopy != NULL) {
- MmFreePagedPool(PathCopy);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysRename (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine renames a file or directory.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PSTR DestinationCopy;
- PIO_HANDLE DestinationDirectory;
- PSYSTEM_CALL_RENAME Parameters;
- PKPROCESS Process;
- PSTR SourceCopy;
- PIO_HANDLE SourceDirectory;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallRename);
- DestinationCopy = NULL;
- DestinationDirectory = NULL;
- Parameters = (PSYSTEM_CALL_RENAME)SystemCallParameter;
- Process = PsGetCurrentProcess();
- SourceCopy = NULL;
- SourceDirectory = NULL;
- if (Parameters->SourceDirectory != INVALID_HANDLE) {
- SourceDirectory = ObGetHandleValue(Process->HandleTable,
- Parameters->SourceDirectory,
- NULL);
- if (SourceDirectory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysRenameEnd;
- }
- }
- if (Parameters->DestinationDirectory != INVALID_HANDLE) {
- DestinationDirectory = ObGetHandleValue(
- Process->HandleTable,
- Parameters->DestinationDirectory,
- NULL);
- if (DestinationDirectory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysRenameEnd;
- }
- }
- Status = MmCreateCopyOfUserModeString(Parameters->SourcePath,
- Parameters->SourcePathSize,
- IO_ALLOCATION_TAG,
- &SourceCopy);
- if (!KSUCCESS(Status)) {
- goto SysRenameEnd;
- }
- Status = MmCreateCopyOfUserModeString(Parameters->DestinationPath,
- Parameters->DestinationPathSize,
- IO_ALLOCATION_TAG,
- &DestinationCopy);
- if (!KSUCCESS(Status)) {
- goto SysRenameEnd;
- }
- Status = IoRename(FALSE,
- SourceDirectory,
- SourceCopy,
- Parameters->SourcePathSize,
- DestinationDirectory,
- DestinationCopy,
- Parameters->DestinationPathSize);
- if (!KSUCCESS(Status)) {
- goto SysRenameEnd;
- }
- SysRenameEnd:
- if (SourceCopy != NULL) {
- MmFreePagedPool(SourceCopy);
- }
- if (DestinationCopy != NULL) {
- MmFreePagedPool(DestinationCopy);
- }
- if (SourceDirectory != NULL) {
- IoIoHandleReleaseReference(SourceDirectory);
- }
- if (DestinationDirectory != NULL) {
- IoIoHandleReleaseReference(DestinationDirectory);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysUserControl (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine implements the user control system call.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PIO_HANDLE IoHandle;
- PKPROCESS Process;
- PSYSTEM_CALL_USER_CONTROL Request;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallUserControl);
- Request = (PSYSTEM_CALL_USER_CONTROL)SystemCallParameter;
- Process = PsGetCurrentProcess();
- IoHandle = ObGetHandleValue(Process->HandleTable, Request->Handle, NULL);
- if (IoHandle == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysUserControlEnd;
- }
- Status = IopHandleCommonUserControl(IoHandle,
- Request->Handle,
- Request->RequestCode,
- FALSE,
- Request->Context,
- Request->ContextSize);
- if (Status == STATUS_NOT_SUPPORTED) {
- Status = IoUserControl(IoHandle,
- Request->RequestCode,
- FALSE,
- Request->Context,
- Request->ContextSize);
- }
- if (!KSUCCESS(Status)) {
- goto SysUserControlEnd;
- }
- SysUserControlEnd:
- Request->Status = Status;
- if (IoHandle != NULL) {
- IoIoHandleReleaseReference(IoHandle);
- }
- return;
- }
- VOID
- IoSysMountOrUnmount (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine mounts or unmounts a file, directory, volume, pipe, socket, or
- device.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- ULONG AccessFlags;
- ULONG MountFlags;
- PSTR MountPointCopy;
- PSYSTEM_CALL_MOUNT_UNMOUNT Parameters;
- KSTATUS Status;
- PSTR TargetCopy;
- ASSERT(SystemCallNumber == SystemCallMountOrUnmount);
- AccessFlags = 0;
- MountFlags = 0;
- MountPointCopy = NULL;
- Parameters = (PSYSTEM_CALL_MOUNT_UNMOUNT)SystemCallParameter;
- TargetCopy = NULL;
- //
- // A mount point path is always required. Create a copy.
- //
- Status = MmCreateCopyOfUserModeString(Parameters->MountPointPath,
- Parameters->MountPointPathSize,
- IO_ALLOCATION_TAG,
- &MountPointCopy);
- if (!KSUCCESS(Status)) {
- goto SysMountUnmountEnd;
- }
- //
- // The target path is not required during unmount. Do not copy it.
- //
- if ((Parameters->Flags & SYS_MOUNT_FLAG_UNMOUNT) == 0) {
- Status = MmCreateCopyOfUserModeString(Parameters->TargetPath,
- Parameters->TargetPathSize,
- IO_ALLOCATION_TAG,
- &TargetCopy);
- if (!KSUCCESS(Status)) {
- goto SysMountUnmountEnd;
- }
- }
- //
- // Convert any additional flags.
- //
- if ((Parameters->Flags & SYS_MOUNT_FLAG_READ) != 0) {
- AccessFlags |= IO_ACCESS_READ;
- }
- if ((Parameters->Flags & SYS_MOUNT_FLAG_WRITE) != 0) {
- AccessFlags |= IO_ACCESS_WRITE;
- }
- if ((Parameters->Flags & SYS_MOUNT_FLAG_BIND) != 0) {
- MountFlags |= MOUNT_FLAG_BIND;
- }
- if ((Parameters->Flags & SYS_MOUNT_FLAG_RECURSIVE) != 0) {
- MountFlags |= MOUNT_FLAG_RECURSIVE;
- }
- //
- // A detach call is always recursive.
- //
- if ((Parameters->Flags & SYS_MOUNT_FLAG_DETACH) != 0) {
- MountFlags |= MOUNT_FLAG_DETACH | MOUNT_FLAG_RECURSIVE;
- }
- //
- // Call the appropriate mount or unmount routine.
- //
- if ((Parameters->Flags & SYS_MOUNT_FLAG_UNMOUNT) == 0) {
- Status = IoMount(FALSE,
- MountPointCopy,
- Parameters->MountPointPathSize,
- TargetCopy,
- Parameters->TargetPathSize,
- MountFlags,
- AccessFlags);
- } else {
- Status = IoUnmount(FALSE,
- MountPointCopy,
- Parameters->MountPointPathSize,
- MountFlags,
- AccessFlags);
- }
- if (!KSUCCESS(Status)) {
- goto SysMountUnmountEnd;
- }
- SysMountUnmountEnd:
- if (MountPointCopy != NULL) {
- MmFreePagedPool(MountPointCopy);
- }
- if (TargetCopy != NULL) {
- MmFreePagedPool(TargetCopy);
- }
- Parameters->Status = Status;
- return;
- }
- VOID
- IoSysGetEffectiveAccess (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine implements the system call for getting the current user's
- access permission to a given path.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- PIO_HANDLE Directory;
- FILE_PROPERTIES Information;
- PIO_HANDLE IoHandle;
- PSYSTEM_CALL_GET_EFFECTIVE_ACCESS Parameters;
- PSTR Path;
- PKPROCESS Process;
- KSTATUS Status;
- ASSERT(SystemCallNumber == SystemCallGetEffectiveAccess);
- Directory = NULL;
- IoHandle = NULL;
- Parameters = (PSYSTEM_CALL_GET_EFFECTIVE_ACCESS)SystemCallParameter;
- Parameters->EffectiveAccess = 0;
- Path = NULL;
- Status = MmCreateCopyOfUserModeString(Parameters->FilePath,
- Parameters->FilePathSize,
- FI_ALLOCATION_TAG,
- &Path);
- if (!KSUCCESS(Status)) {
- goto SysGetEffectiveAccessEnd;
- }
- if (Parameters->Directory != INVALID_HANDLE) {
- Process = PsGetCurrentProcess();
- Directory = ObGetHandleValue(Process->HandleTable,
- Parameters->Directory,
- NULL);
- if (Directory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysGetEffectiveAccessEnd;
- }
- }
- Status = IoOpen(FALSE,
- Directory,
- Path,
- Parameters->FilePathSize,
- 0,
- 0,
- FILE_PERMISSION_NONE,
- &IoHandle);
- if (!KSUCCESS(Status)) {
- goto SysGetEffectiveAccessEnd;
- }
- Status = IoGetFileInformation(IoHandle, &Information);
- if (!KSUCCESS(Status)) {
- goto SysGetEffectiveAccessEnd;
- }
- if ((Parameters->DesiredFlags & EFFECTIVE_ACCESS_READ) != 0) {
- Status = IopCheckPermissions(FALSE,
- &(IoHandle->PathPoint),
- IO_ACCESS_READ);
- if (KSUCCESS(Status)) {
- Parameters->EffectiveAccess |= EFFECTIVE_ACCESS_READ;
- }
- }
- if ((Parameters->DesiredFlags & EFFECTIVE_ACCESS_WRITE) != 0) {
- Status = IopCheckPermissions(FALSE,
- &(IoHandle->PathPoint),
- IO_ACCESS_WRITE);
- if (KSUCCESS(Status)) {
- Parameters->EffectiveAccess |= EFFECTIVE_ACCESS_WRITE;
- }
- }
- if ((Parameters->DesiredFlags & EFFECTIVE_ACCESS_EXECUTE) != 0) {
- Status = IopCheckPermissions(FALSE,
- &(IoHandle->PathPoint),
- IO_ACCESS_EXECUTE);
- if (KSUCCESS(Status)) {
- Parameters->EffectiveAccess |= EFFECTIVE_ACCESS_EXECUTE;
- }
- }
- Status = STATUS_SUCCESS;
- SysGetEffectiveAccessEnd:
- if (Directory != NULL) {
- IoIoHandleReleaseReference(Directory);
- }
- if (IoHandle != NULL) {
- IoClose(IoHandle);
- }
- Parameters->Status = Status;
- if (Path != NULL) {
- MmFreePagedPool(Path);
- }
- return;
- }
- VOID
- IoSysCreateTerminal (
- ULONG SystemCallNumber,
- PVOID SystemCallParameter,
- PTRAP_FRAME TrapFrame,
- PULONG ResultSize
- )
- /*++
- Routine Description:
- This routine implements the system call for creating and opening a new
- terminal.
- Arguments:
- SystemCallNumber - Supplies the system call number that was requested.
- SystemCallParameter - Supplies a pointer to the parameters supplied with
- the system call. This structure will be a stack-local copy of the
- actual parameters passed from user-mode.
- TrapFrame - Supplies a pointer to the trap frame generated by this jump
- from user mode to kernel mode.
- ResultSize - Supplies a pointer where the system call routine returns the
- size of the parameter structure to be copied back to user mode. The
- value returned here must be no larger than the original parameter
- structure size. The default is the original size of the parameters.
- Return Value:
- None.
- --*/
- {
- ULONG Access;
- PKPROCESS CurrentProcess;
- ULONG HandleFlags;
- PIO_HANDLE MasterDirectory;
- PIO_HANDLE MasterHandle;
- PSTR MasterPath;
- ULONG OpenFlags;
- PSYSTEM_CALL_CREATE_TERMINAL Parameters;
- PIO_HANDLE SlaveDirectory;
- PSTR SlavePath;
- KSTATUS Status;
- CurrentProcess = PsGetCurrentProcess();
- ASSERT(SystemCallNumber == SystemCallCreateTerminal);
- ASSERT(CurrentProcess != PsGetKernelProcess());
- MasterDirectory = NULL;
- MasterHandle = NULL;
- Parameters = (PSYSTEM_CALL_CREATE_TERMINAL)SystemCallParameter;
- Parameters->MasterHandle = INVALID_HANDLE;
- MasterPath = NULL;
- SlaveDirectory = NULL;
- SlavePath = NULL;
- if (Parameters->MasterPathLength != 0) {
- Status = MmCreateCopyOfUserModeString(Parameters->MasterPath,
- Parameters->MasterPathLength,
- FI_ALLOCATION_TAG,
- &MasterPath);
- if (!KSUCCESS(Status)) {
- goto SysCreateTerminalEnd;
- }
- }
- if (Parameters->SlavePathLength != 0) {
- Status = MmCreateCopyOfUserModeString(Parameters->SlavePath,
- Parameters->SlavePathLength,
- FI_ALLOCATION_TAG,
- &SlavePath);
- if (!KSUCCESS(Status)) {
- goto SysCreateTerminalEnd;
- }
- }
- if (Parameters->MasterDirectory != INVALID_HANDLE) {
- MasterDirectory = ObGetHandleValue(CurrentProcess->HandleTable,
- Parameters->MasterDirectory,
- NULL);
- if (MasterDirectory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysCreateTerminalEnd;
- }
- }
- if (Parameters->SlaveDirectory != INVALID_HANDLE) {
- SlaveDirectory = ObGetHandleValue(CurrentProcess->HandleTable,
- Parameters->SlaveDirectory,
- NULL);
- if (SlaveDirectory == NULL) {
- Status = STATUS_INVALID_HANDLE;
- goto SysCreateTerminalEnd;
- }
- }
- ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
- Access = (Parameters->MasterOpenFlags >> SYS_OPEN_ACCESS_SHIFT) &
- (IO_ACCESS_READ | IO_ACCESS_WRITE);
- OpenFlags = Parameters->MasterOpenFlags & OPEN_FLAG_NO_CONTROLLING_TERMINAL;
- Status = IoCreateTerminal(FALSE,
- MasterDirectory,
- SlaveDirectory,
- MasterPath,
- Parameters->MasterPathLength,
- SlavePath,
- Parameters->SlavePathLength,
- Access,
- OpenFlags,
- Parameters->MasterCreatePermissions,
- Parameters->SlaveCreatePermissions,
- &MasterHandle);
- if (!KSUCCESS(Status)) {
- goto SysCreateTerminalEnd;
- }
- HandleFlags = 0;
- if ((Parameters->MasterOpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
- HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
- }
- Status = ObCreateHandle(CurrentProcess->HandleTable,
- MasterHandle,
- HandleFlags,
- &(Parameters->MasterHandle));
- if (!KSUCCESS(Status)) {
- IoClose(MasterHandle);
- goto SysCreateTerminalEnd;
- }
- SysCreateTerminalEnd:
- if (MasterDirectory != NULL) {
- IoIoHandleReleaseReference(MasterDirectory);
- }
- if (SlaveDirectory != NULL) {
- IoIoHandleReleaseReference(SlaveDirectory);
- }
- if (MasterPath != NULL) {
- MmFreePagedPool(MasterPath);
- }
- if (SlavePath != NULL) {
- MmFreePagedPool(SlavePath);
- }
- Parameters->Status = Status;
- return;
- }
- KSTATUS
- IoCloseProcessHandles (
- PKPROCESS Process,
- HANDLE MinimumHandle
- )
- /*++
- Routine Description:
- This routine closes all remaining open handles in the given process.
- Arguments:
- Process - Supplies a pointer to the process being terminated.
- MinimumHandle - Supplies the lowest handle to clean up to, inclusive.
- Handles below this one will not be closed.
- Return Value:
- Status code.
- --*/
- {
- HANDLE Handle;
- HANDLE PreviousHandle;
- KSTATUS Status;
- KSTATUS TotalStatus;
- //
- // Loop getting the highest numbered handle and closing it until there are
- // no more open handles.
- //
- PreviousHandle = INVALID_HANDLE;
- TotalStatus = STATUS_SUCCESS;
- while (TRUE) {
- Handle = ObGetHighestHandle(Process->HandleTable);
- if (Handle == INVALID_HANDLE) {
- break;
- }
- if (Handle < MinimumHandle) {
- break;
- }
- ASSERT(Handle != PreviousHandle);
- Status = IopSysClose(Process, Handle);
- if (!KSUCCESS(Status)) {
- if (KSUCCESS(TotalStatus)) {
- TotalStatus = Status;
- }
- }
- PreviousHandle = Handle;
- }
- return TotalStatus;
- }
- KSTATUS
- IoCopyProcessHandles (
- PKPROCESS SourceProcess,
- PKPROCESS DestinationProcess
- )
- /*++
- Routine Description:
- This routine copies all handles in the source process to the destination
- process. This is used during process forking.
- Arguments:
- SourceProcess - Supplies a pointer to the process being copied.
- DestinationProcess - Supplies a pointer to the fledgling destination
- process. This process' handle hables must be empty.
- Return Value:
- Status code.
- --*/
- {
- COPY_HANDLES_ITERATION_CONTEXT Context;
- PHANDLE_TABLE DestinationTable;
- PHANDLE_TABLE SourceTable;
- DestinationTable = DestinationProcess->HandleTable;
- SourceTable = SourceProcess->HandleTable;
- Context.DestinationTable = DestinationTable;
- Context.SourceTable = SourceTable;
- Context.Status = STATUS_SUCCESS;
- //
- // Assert that the destination process handle table is empty.
- //
- ASSERT(ObGetHighestHandle(DestinationTable) == INVALID_HANDLE);
- ObHandleTableIterate(SourceTable, IopCopyHandleIterateRoutine, &Context);
- //
- // If the operation was not successful, clean up any partial progress.
- //
- if (!KSUCCESS(Context.Status)) {
- IoCloseProcessHandles(DestinationProcess, 0);
- }
- return Context.Status;
- }
- KSTATUS
- IoCloseHandlesOnExecute (
- PKPROCESS Process
- )
- /*++
- Routine Description:
- This routine closes any handles marked for "close on execute".
- Arguments:
- Process - Supplies a pointer to the process undergoing the execution
- transformation.
- Return Value:
- Status code.
- --*/
- {
- CLOSE_EXECUTE_HANDLES_CONTEXT Context;
- ULONG HandleIndex;
- KSTATUS Status;
- //
- // Get the array of handles to be closed. This can't be done in the
- // iterate routine because the iterate routine needs the tree to stay
- // static while it's cruising around.
- //
- Context.HandleArray = NULL;
- Context.HandleArraySize = 0;
- Context.HandleArrayCapacity = 0;
- Context.Status = STATUS_SUCCESS;
- ObHandleTableIterate(Process->HandleTable,
- IopCloseExecuteHandleIterateRoutine,
- &Context);
- Status = Context.Status;
- if (!KSUCCESS(Status)) {
- goto CloseHandlesOnExecuteEnd;
- }
- for (HandleIndex = 0;
- HandleIndex < Context.HandleArraySize;
- HandleIndex += 1) {
- IopSysClose(Process, Context.HandleArray[HandleIndex]);
- }
- Status = STATUS_SUCCESS;
- CloseHandlesOnExecuteEnd:
- if (Context.HandleArray != NULL) {
- MmFreePagedPool(Context.HandleArray);
- }
- return Status;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- KSTATUS
- IopSysClose (
- PKPROCESS Process,
- HANDLE Handle
- )
- /*++
- Routine Description:
- This routine closes a handle opened in user mode.
- Arguments:
- Process - Supplies a pointer to the process the file handle was opened
- under.
- Handle - Supplies the handle returned during the open system call.
- Return Value:
- Status code.
- --*/
- {
- PVOID HandleValue;
- KSTATUS Status;
- HandleValue = ObGetHandleValue(Process->HandleTable, Handle, NULL);
- if (HandleValue == NULL) {
- return STATUS_INVALID_HANDLE;
- }
- IopRemoveFileLocks(HandleValue, Process);
- Status = IoClose(HandleValue);
- if (!KSUCCESS(Status)) {
- goto SysCloseEnd;
- }
- ObDestroyHandle(Process->HandleTable, Handle);
- SysCloseEnd:
- //
- // Release the handle reference that was added by the get handle value
- // routine.
- //
- IoIoHandleReleaseReference(HandleValue);
- return Status;
- }
- VOID
- IopCopyHandleIterateRoutine (
- PHANDLE_TABLE HandleTable,
- HANDLE Descriptor,
- ULONG Flags,
- PVOID HandleValue,
- PVOID Context
- )
- /*++
- Routine Description:
- This routine is called on each handle in the handle table for which it was
- invoked. It will copy the given handle into the destination table (passed
- via context).
- Arguments:
- HandleTable - Supplies a pointer to the handle table being iterated through.
- Descriptor - Supplies the handle descriptor for the current handle.
- Flags - Supplies the flags associated with this handle.
- HandleValue - Supplies the handle value for the current handle.
- Context - Supplies an opaque pointer of context that was provided when the
- iteration was requested. In this case, a pointer to the copy handles
- iteration context.
- Return Value:
- None.
- --*/
- {
- PCOPY_HANDLES_ITERATION_CONTEXT IterationContext;
- HANDLE NewHandle;
- KSTATUS Status;
- IterationContext = (PCOPY_HANDLES_ITERATION_CONTEXT)Context;
- //
- // If the operation has already failed (on a previous handle), stop trying.
- //
- if (!KSUCCESS(IterationContext->Status)) {
- return;
- }
- NewHandle = Descriptor;
- Status = ObCreateHandle(IterationContext->DestinationTable,
- HandleValue,
- Flags,
- &NewHandle);
- if (!KSUCCESS(Status)) {
- IterationContext->Status = Status;
- return;
- }
- ASSERT(NewHandle == Descriptor);
- IoIoHandleAddReference(HandleValue);
- return;
- }
- VOID
- IopCloseExecuteHandleIterateRoutine (
- PHANDLE_TABLE HandleTable,
- HANDLE Descriptor,
- ULONG Flags,
- PVOID HandleValue,
- PVOID Context
- )
- /*++
- Routine Description:
- This routine is called on each handle in the handle table for which it was
- invoked. It will add the handle to an array stored internally if the
- handle is marked to be close on execute.
- Arguments:
- HandleTable - Supplies a pointer to the handle table being iterated through.
- Descriptor - Supplies the handle descriptor for the current handle.
- Flags - Supplies the flags for this descriptor.
- HandleValue - Supplies the handle value for the current handle.
- Context - Supplies an opaque pointer of context that was provided when the
- iteration was requested. In this case, a pointer to the close execute
- handles iteration context.
- Return Value:
- None.
- --*/
- {
- PCLOSE_EXECUTE_HANDLES_CONTEXT IterationContext;
- PHANDLE NewArray;
- ULONG NewCapacity;
- UINTN OldSize;
- IterationContext = (PCLOSE_EXECUTE_HANDLES_CONTEXT)Context;
- //
- // If the operation has already failed (on a previous handle), stop trying.
- //
- if (!KSUCCESS(IterationContext->Status)) {
- return;
- }
- //
- // If the handle doesn't need to be added to the array, exit early.
- //
- if ((Flags & FILE_DESCRIPTOR_CLOSE_ON_EXECUTE) == 0) {
- return;
- }
- //
- // Expand the array if needed.
- //
- if (IterationContext->HandleArraySize ==
- IterationContext->HandleArrayCapacity) {
- NewCapacity = IterationContext->HandleArrayCapacity * 2;
- if (NewCapacity == 0) {
- NewCapacity = CLOSE_EXECUTE_HANDLE_INITIAL_ARRAY_SIZE;
- }
- NewArray = MmAllocatePagedPool(NewCapacity * sizeof(PHANDLE),
- IO_ALLOCATION_TAG);
- if (NewArray == NULL) {
- IterationContext->Status = STATUS_INSUFFICIENT_RESOURCES;
- return;
- }
- if (IterationContext->HandleArray != NULL) {
- OldSize = IterationContext->HandleArrayCapacity * sizeof(PHANDLE);
- RtlCopyMemory(NewArray, IterationContext->HandleArray, OldSize);
- MmFreePagedPool(IterationContext->HandleArray);
- }
- IterationContext->HandleArray = NewArray;
- IterationContext->HandleArrayCapacity = NewCapacity;
- ASSERT(IterationContext->HandleArrayCapacity >
- IterationContext->HandleArraySize);
- }
- IterationContext->HandleArray[IterationContext->HandleArraySize] =
- Descriptor;
- IterationContext->HandleArraySize += 1;
- return;
- }
- VOID
- IopCheckForDirectoryHandlesIterationRoutine (
- PHANDLE_TABLE HandleTable,
- HANDLE Descriptor,
- ULONG Flags,
- PVOID HandleValue,
- PVOID Context
- )
- /*++
- Routine Description:
- This routine is called on each handle in the handle table checking for an
- open handle to a directory.
- Arguments:
- HandleTable - Supplies a pointer to the handle table being iterated through.
- Descriptor - Supplies the handle descriptor for the current handle.
- Flags - Supplies the flags associated with this handle.
- HandleValue - Supplies the handle value for the current handle.
- Context - Supplies an opaque pointer of context that was provided when the
- iteration was requested.
- Return Value:
- None.
- --*/
- {
- PFILE_OBJECT FileObject;
- PIO_HANDLE IoHandle;
- PSYSTEM_CALL_CHANGE_DIRECTORY Parameters;
- Parameters = Context;
- IoHandle = HandleValue;
- FileObject = IoHandle->FileObject;
- if ((Descriptor != Parameters->Handle) &&
- ((FileObject->Properties.Type == IoObjectRegularDirectory) ||
- (FileObject->Properties.Type == IoObjectObjectDirectory))) {
- Parameters->Status = STATUS_TOO_MANY_HANDLES;
- }
- return;
- }
- KSTATUS
- IopGetUserFilePath (
- PPATH_POINT Entry,
- PPATH_POINT Root,
- PSTR UserBuffer,
- PUINTN UserBufferSize
- )
- /*++
- Routine Description:
- This routine copies the full path of the given path entry (as seen from
- the given root) into the given user mode buffer.
- Arguments:
- Entry - Supplies a pointer to the path point to get the full path of.
- Root - Supplies a pointer to the user's root.
- UserBuffer - Supplies a pointer to the user mode buffer where the full path
- should be returned.
- UserBufferSize - Supplies a pointer that on success contains the size of
- the user mode buffer. Returns the actual size of the file path, even if
- the supplied buffer was too small.
- Return Value:
- STATUS_SUCCESS on success.
- STATUS_PATH_NOT_FOUND if the path entry has no path.
- STATUS_ACCESS_VIOLATION if the buffer was invalid.
- STATUS_BUFFER_TOO_SMALL if the buffer was too small.
- --*/
- {
- PSTR Path;
- UINTN PathSize;
- KSTATUS Status;
- //
- // Create the path.
- //
- Path = NULL;
- PathSize = 0;
- Status = IopGetPathFromRoot(Entry,
- Root,
- &Path,
- &PathSize);
- if (!KSUCCESS(Status)) {
- goto GetUserFilePathEnd;
- }
- //
- // If not enough space was supplied, then return the required size.
- //
- if (*UserBufferSize < PathSize) {
- Status = STATUS_BUFFER_TOO_SMALL;
- goto GetUserFilePathEnd;
- }
- //
- // Copy the path to the supplied buffer.
- //
- if (UserBuffer != NULL) {
- Status = MmCopyToUserMode(UserBuffer, Path, PathSize);
- if (!KSUCCESS(Status)) {
- goto GetUserFilePathEnd;
- }
- }
- GetUserFilePathEnd:
- if (Path != NULL) {
- MmFreePagedPool(Path);
- }
- *UserBufferSize = PathSize;
- return Status;
- }
- KSTATUS
- IopHandleCommonUserControl (
- PIO_HANDLE Handle,
- HANDLE Descriptor,
- ULONG MinorCode,
- BOOL FromKernelMode,
- PVOID ContextBuffer,
- UINTN ContextBufferSize
- )
- /*++
- Routine Description:
- This routine performs user control operations common to many types of
- devices.
- Arguments:
- Handle - Supplies the open file handle.
- Descriptor - Supplies the descriptor corresponding to the handle.
- MinorCode - Supplies the minor code of the request.
- FromKernelMode - Supplies a boolean indicating whether or not this request
- (and the buffer associated with it) originates from user mode (FALSE)
- or kernel mode (TRUE).
- ContextBuffer - Supplies a pointer to the context buffer allocated by the
- caller for the request.
- ContextBufferSize - Supplies the size of the supplied context buffer.
- Return Value:
- Status code.
- --*/
- {
- INT Argument;
- BOOL Asynchronous;
- KSTATUS Status;
- switch (MinorCode) {
- case TerminalControlAsync:
- if (ContextBufferSize < sizeof(INT)) {
- Status = STATUS_DATA_LENGTH_MISMATCH;
- break;
- }
- if (FromKernelMode != FALSE) {
- Argument = *((PULONG)ContextBuffer);
- } else {
- Argument = 0;
- Status = MmCopyFromUserMode(&Argument, ContextBuffer, sizeof(INT));
- if (!KSUCCESS(Status)) {
- break;
- }
- }
- Asynchronous = FALSE;
- if (Argument != 0) {
- Asynchronous = TRUE;
- }
- Status = IoSetHandleAsynchronous(Handle, Descriptor, Asynchronous);
- break;
- default:
- Status = STATUS_NOT_SUPPORTED;
- break;
- }
- return Status;
- }
|