userio.c 109 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. userio.c
  5. Abstract:
  6. This module implements support for interfacing the I/O subsystem with
  7. user mode.
  8. Author:
  9. Evan Green 25-Apr-2013
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/kernel.h>
  17. #include "iop.h"
  18. //
  19. // --------------------------------------------------------------------- Macros
  20. //
  21. #define ASSERT_SYS_OPEN_FLAGS_EQUIVALENT() \
  22. ASSERT((SYS_OPEN_FLAG_CREATE == OPEN_FLAG_CREATE) && \
  23. (SYS_OPEN_FLAG_TRUNCATE == OPEN_FLAG_TRUNCATE) && \
  24. (SYS_OPEN_FLAG_FAIL_IF_EXISTS == OPEN_FLAG_FAIL_IF_EXISTS) && \
  25. (SYS_OPEN_FLAG_APPEND == OPEN_FLAG_APPEND) && \
  26. (SYS_OPEN_FLAG_DIRECTORY == OPEN_FLAG_DIRECTORY) && \
  27. (SYS_OPEN_FLAG_NON_BLOCKING == OPEN_FLAG_NON_BLOCKING) && \
  28. (SYS_OPEN_FLAG_SHARED_MEMORY == OPEN_FLAG_SHARED_MEMORY) && \
  29. (SYS_OPEN_FLAG_NO_SYMBOLIC_LINK == OPEN_FLAG_NO_SYMBOLIC_LINK) && \
  30. (SYS_OPEN_FLAG_SYNCHRONIZED == OPEN_FLAG_SYNCHRONIZED) && \
  31. (SYS_OPEN_FLAG_NO_CONTROLLING_TERMINAL == \
  32. OPEN_FLAG_NO_CONTROLLING_TERMINAL) && \
  33. (SYS_OPEN_FLAG_NO_ACCESS_TIME == OPEN_FLAG_NO_ACCESS_TIME) && \
  34. (SYS_OPEN_FLAG_ASYNCHRONOUS == OPEN_FLAG_ASYNCHRONOUS))
  35. //
  36. // ---------------------------------------------------------------- Definitions
  37. //
  38. #define CLOSE_EXECUTE_HANDLE_INITIAL_ARRAY_SIZE 16
  39. //
  40. // ------------------------------------------------------ Data Type Definitions
  41. //
  42. /*++
  43. Structure Description:
  44. This structure stores context during a copy of a handle table.
  45. Members:
  46. DestinationTable - Stores a pointer to the destination handle table.
  47. SourceTable - Stores a pointer to the handle table to be copied.
  48. Status - Stores the current status of the copy operation. Initialize to
  49. STATUS_SUCCESS.
  50. --*/
  51. typedef struct _COPY_HANDLES_ITERATION_CONTEXT {
  52. PHANDLE_TABLE DestinationTable;
  53. PHANDLE_TABLE SourceTable;
  54. KSTATUS Status;
  55. } COPY_HANDLES_ITERATION_CONTEXT, *PCOPY_HANDLES_ITERATION_CONTEXT;
  56. /*++
  57. Structure Description:
  58. This structure stores context during a copy of a handle table.
  59. Members:
  60. HandleArray - Stores the array of handles to close, allocated in paged pool.
  61. HandleArraySize - Stores the number of valid entries in the array.
  62. HandleArrayCapacity - Stores the maximum number of elements in the handle
  63. array.
  64. Status - Stores the current status of the iteration operation. Initialize to
  65. STATUS_SUCCESS.
  66. --*/
  67. typedef struct _CLOSE_EXECUTE_HANDLES_CONTEXT {
  68. PHANDLE HandleArray;
  69. ULONG HandleArraySize;
  70. ULONG HandleArrayCapacity;
  71. KSTATUS Status;
  72. } CLOSE_EXECUTE_HANDLES_CONTEXT, *PCLOSE_EXECUTE_HANDLES_CONTEXT;
  73. //
  74. // ----------------------------------------------- Internal Function Prototypes
  75. //
  76. KSTATUS
  77. IopSysClose (
  78. PKPROCESS Process,
  79. HANDLE Handle
  80. );
  81. VOID
  82. IopCopyHandleIterateRoutine (
  83. PHANDLE_TABLE HandleTable,
  84. HANDLE Descriptor,
  85. ULONG Flags,
  86. PVOID HandleValue,
  87. PVOID Context
  88. );
  89. VOID
  90. IopCloseExecuteHandleIterateRoutine (
  91. PHANDLE_TABLE HandleTable,
  92. HANDLE Descriptor,
  93. ULONG Flags,
  94. PVOID HandleValue,
  95. PVOID Context
  96. );
  97. VOID
  98. IopCheckForDirectoryHandlesIterationRoutine (
  99. PHANDLE_TABLE HandleTable,
  100. HANDLE Descriptor,
  101. ULONG Flags,
  102. PVOID HandleValue,
  103. PVOID Context
  104. );
  105. KSTATUS
  106. IopGetUserFilePath (
  107. PPATH_POINT Entry,
  108. PPATH_POINT Root,
  109. PSTR UserBuffer,
  110. PUINTN UserBufferSize
  111. );
  112. KSTATUS
  113. IopHandleCommonUserControl (
  114. PIO_HANDLE Handle,
  115. HANDLE Descriptor,
  116. ULONG MinorCode,
  117. BOOL FromKernelMode,
  118. PVOID ContextBuffer,
  119. UINTN ContextBufferSize
  120. );
  121. //
  122. // -------------------------------------------------------------------- Globals
  123. //
  124. //
  125. // ------------------------------------------------------------------ Functions
  126. //
  127. VOID
  128. IoSysOpen (
  129. ULONG SystemCallNumber,
  130. PVOID SystemCallParameter,
  131. PTRAP_FRAME TrapFrame,
  132. PULONG ResultSize
  133. )
  134. /*++
  135. Routine Description:
  136. This routine opens a file or other I/O object on behalf of a user mode
  137. application.
  138. Arguments:
  139. SystemCallNumber - Supplies the system call number that was requested.
  140. SystemCallParameter - Supplies a pointer to the parameters supplied with
  141. the system call. This structure will be a stack-local copy of the
  142. actual parameters passed from user-mode.
  143. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  144. from user mode to kernel mode.
  145. ResultSize - Supplies a pointer where the system call routine returns the
  146. size of the parameter structure to be copied back to user mode. The
  147. value returned here must be no larger than the original parameter
  148. structure size. The default is the original size of the parameters.
  149. Return Value:
  150. None.
  151. --*/
  152. {
  153. ULONG Access;
  154. PKPROCESS CurrentProcess;
  155. PIO_HANDLE Directory;
  156. PSTR FileName;
  157. ULONG FileNameLength;
  158. PIO_HANDLE Handle;
  159. ULONG HandleFlags;
  160. ULONG OpenFlags;
  161. PSYSTEM_CALL_OPEN Parameters;
  162. KSTATUS Status;
  163. CurrentProcess = PsGetCurrentProcess();
  164. ASSERT(CurrentProcess != PsGetKernelProcess());
  165. Directory = NULL;
  166. Handle = NULL;
  167. Parameters = (PSYSTEM_CALL_OPEN)SystemCallParameter;
  168. FileName = NULL;
  169. FileNameLength = Parameters->PathBufferLength;
  170. Parameters->Handle = INVALID_HANDLE;
  171. Status = MmCreateCopyOfUserModeString(Parameters->Path,
  172. FileNameLength,
  173. FI_ALLOCATION_TAG,
  174. &FileName);
  175. if (!KSUCCESS(Status)) {
  176. goto SysOpenEnd;
  177. }
  178. //
  179. // Set up the flags.
  180. //
  181. ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
  182. Access = (Parameters->Flags >> SYS_OPEN_ACCESS_SHIFT) & IO_ACCESS_MASK;
  183. OpenFlags = Parameters->Flags & SYS_OPEN_FLAG_MASK;
  184. if (Parameters->Directory != INVALID_HANDLE) {
  185. Directory = ObGetHandleValue(CurrentProcess->HandleTable,
  186. Parameters->Directory,
  187. NULL);
  188. if (Directory == NULL) {
  189. Status = STATUS_INVALID_HANDLE;
  190. goto SysOpenEnd;
  191. }
  192. }
  193. //
  194. // Open up the file.
  195. //
  196. Status = IoOpen(FALSE,
  197. Directory,
  198. FileName,
  199. FileNameLength,
  200. Access,
  201. OpenFlags,
  202. Parameters->CreatePermissions,
  203. &Handle);
  204. if (!KSUCCESS(Status)) {
  205. goto SysOpenEnd;
  206. }
  207. //
  208. // Create a handle table entry for this open file.
  209. //
  210. HandleFlags = 0;
  211. if ((Parameters->Flags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
  212. HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  213. }
  214. Status = ObCreateHandle(CurrentProcess->HandleTable,
  215. Handle,
  216. HandleFlags,
  217. &(Parameters->Handle));
  218. if (!KSUCCESS(Status)) {
  219. goto SysOpenEnd;
  220. }
  221. Status = STATUS_SUCCESS;
  222. SysOpenEnd:
  223. if (Directory != NULL) {
  224. IoIoHandleReleaseReference(Directory);
  225. }
  226. if (FileName != NULL) {
  227. MmFreePagedPool(FileName);
  228. }
  229. if (!KSUCCESS(Status)) {
  230. if (Handle != NULL) {
  231. IoClose(Handle);
  232. }
  233. }
  234. Parameters->Status = Status;
  235. return;
  236. }
  237. VOID
  238. IoSysOpenDevice (
  239. ULONG SystemCallNumber,
  240. PVOID SystemCallParameter,
  241. PTRAP_FRAME TrapFrame,
  242. PULONG ResultSize
  243. )
  244. /*++
  245. Routine Description:
  246. This routine opens a direct handle to a device on behalf of a user mode
  247. application.
  248. Arguments:
  249. SystemCallNumber - Supplies the system call number that was requested.
  250. SystemCallParameter - Supplies a pointer to the parameters supplied with
  251. the system call. This structure will be a stack-local copy of the
  252. actual parameters passed from user-mode.
  253. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  254. from user mode to kernel mode.
  255. ResultSize - Supplies a pointer where the system call routine returns the
  256. size of the parameter structure to be copied back to user mode. The
  257. value returned here must be no larger than the original parameter
  258. structure size. The default is the original size of the parameters.
  259. Return Value:
  260. None.
  261. --*/
  262. {
  263. ULONG Access;
  264. PKPROCESS CurrentProcess;
  265. PDEVICE Device;
  266. PIO_HANDLE Handle;
  267. ULONG HandleFlags;
  268. ULONG OpenFlags;
  269. PSYSTEM_CALL_OPEN_DEVICE Parameters;
  270. KSTATUS Status;
  271. CurrentProcess = PsGetCurrentProcess();
  272. ASSERT(CurrentProcess != PsGetKernelProcess());
  273. Handle = NULL;
  274. Parameters = (PSYSTEM_CALL_OPEN_DEVICE)SystemCallParameter;
  275. Parameters->Handle = INVALID_HANDLE;
  276. //
  277. // Set up the flags.
  278. //
  279. ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
  280. Access = (Parameters->Flags >> SYS_OPEN_ACCESS_SHIFT) & IO_ACCESS_MASK;
  281. OpenFlags = Parameters->Flags & SYS_OPEN_FLAG_MASK;
  282. //
  283. // Look up the device.
  284. //
  285. Device = IoGetDeviceByNumericId(Parameters->DeviceId);
  286. if (Device == NULL) {
  287. Status = STATUS_NO_SUCH_DEVICE;
  288. goto SysOpenDeviceEnd;
  289. }
  290. //
  291. // Open up the device.
  292. //
  293. Status = IoOpenDevice(Device, Access, OpenFlags, &Handle, NULL, NULL, NULL);
  294. ObReleaseReference(Device);
  295. if (!KSUCCESS(Status)) {
  296. goto SysOpenDeviceEnd;
  297. }
  298. //
  299. // Create a handle table entry for this open device.
  300. //
  301. HandleFlags = 0;
  302. if ((Parameters->Flags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
  303. HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  304. }
  305. Status = ObCreateHandle(CurrentProcess->HandleTable,
  306. Handle,
  307. HandleFlags,
  308. &(Parameters->Handle));
  309. if (!KSUCCESS(Status)) {
  310. goto SysOpenDeviceEnd;
  311. }
  312. Status = STATUS_SUCCESS;
  313. SysOpenDeviceEnd:
  314. if (!KSUCCESS(Status)) {
  315. if (Handle != NULL) {
  316. IoClose(Handle);
  317. }
  318. }
  319. Parameters->Status = Status;
  320. return;
  321. }
  322. VOID
  323. IoSysClose (
  324. ULONG SystemCallNumber,
  325. PVOID SystemCallParameter,
  326. PTRAP_FRAME TrapFrame,
  327. PULONG ResultSize
  328. )
  329. /*++
  330. Routine Description:
  331. This routine closes an I/O handle opened in user mode.
  332. Arguments:
  333. SystemCallNumber - Supplies the system call number that was requested.
  334. SystemCallParameter - Supplies a pointer to the parameters supplied with
  335. the system call. This structure will be a stack-local copy of the
  336. actual parameters passed from user-mode.
  337. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  338. from user mode to kernel mode.
  339. ResultSize - Supplies a pointer where the system call routine returns the
  340. size of the parameter structure to be copied back to user mode. The
  341. value returned here must be no larger than the original parameter
  342. structure size. The default is the original size of the parameters.
  343. Return Value:
  344. None.
  345. --*/
  346. {
  347. PKPROCESS CurrentProcess;
  348. PSYSTEM_CALL_CLOSE Parameters;
  349. CurrentProcess = PsGetCurrentProcess();
  350. ASSERT(CurrentProcess != PsGetKernelProcess());
  351. Parameters = (PSYSTEM_CALL_CLOSE)SystemCallParameter;
  352. Parameters->Status = IopSysClose(CurrentProcess, Parameters->Handle);
  353. return;
  354. }
  355. VOID
  356. IoSysPerformIo (
  357. ULONG SystemCallNumber,
  358. PVOID SystemCallParameter,
  359. PTRAP_FRAME TrapFrame,
  360. PULONG ResultSize
  361. )
  362. /*++
  363. Routine Description:
  364. This routine performs I/O for user mode.
  365. Arguments:
  366. SystemCallNumber - Supplies the system call number that was requested.
  367. SystemCallParameter - Supplies a pointer to the parameters supplied with
  368. the system call. This structure will be a stack-local copy of the
  369. actual parameters passed from user-mode.
  370. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  371. from user mode to kernel mode.
  372. ResultSize - Supplies a pointer where the system call routine returns the
  373. size of the parameter structure to be copied back to user mode. The
  374. value returned here must be no larger than the original parameter
  375. structure size. The default is the original size of the parameters.
  376. Return Value:
  377. None.
  378. --*/
  379. {
  380. PKPROCESS CurrentProcess;
  381. PIO_HANDLE HandleValue;
  382. IO_BUFFER IoBuffer;
  383. PSYSTEM_CALL_PERFORM_IO Parameters;
  384. UINTN Size;
  385. KSTATUS Status;
  386. ULONG Timeout;
  387. CurrentProcess = PsGetCurrentProcess();
  388. Parameters = (PSYSTEM_CALL_PERFORM_IO)SystemCallParameter;
  389. Size = Parameters->Size;
  390. Parameters->Size = 0;
  391. HandleValue = ObGetHandleValue(CurrentProcess->HandleTable,
  392. Parameters->Handle,
  393. NULL);
  394. if (HandleValue == NULL) {
  395. Status = STATUS_INVALID_HANDLE;
  396. goto SysPerformIoEnd;
  397. }
  398. if (Size == 0) {
  399. Status = STATUS_SUCCESS;
  400. goto SysPerformIoEnd;
  401. }
  402. if ((Parameters->Buffer + Size > KERNEL_VA_START) ||
  403. (Parameters->Buffer + Size < Parameters->Buffer)) {
  404. Status = STATUS_INVALID_PARAMETER;
  405. goto SysPerformIoEnd;
  406. }
  407. Timeout = Parameters->TimeoutInMilliseconds;
  408. ASSERT(SYS_WAIT_TIME_INDEFINITE == WAIT_TIME_INDEFINITE);
  409. //
  410. // Hopefully this I/O buffer will never reach a driver and only be used by
  411. // the cache. As such, don't pin down the pages just yet, allowing the
  412. // opportunity to stack-allocate the I/O buffer structure. If this buffer
  413. // does make it to a driver, a new I/O buffer structure will be temporarily
  414. // allocated to pin down the pages.
  415. //
  416. Status = MmInitializeIoBuffer(&IoBuffer,
  417. Parameters->Buffer,
  418. INVALID_PHYSICAL_ADDRESS,
  419. Size,
  420. 0);
  421. if (!KSUCCESS(Status)) {
  422. goto SysPerformIoEnd;
  423. }
  424. //
  425. // Perform the file I/O.
  426. //
  427. if ((Parameters->Flags & SYS_IO_FLAG_WRITE) != 0) {
  428. Status = IoWriteAtOffset(HandleValue,
  429. &IoBuffer,
  430. Parameters->Offset,
  431. Size,
  432. 0,
  433. Timeout,
  434. &(Parameters->Size),
  435. NULL);
  436. if (Status == STATUS_BROKEN_PIPE) {
  437. ASSERT(CurrentProcess != PsGetKernelProcess());
  438. PsSignalProcess(CurrentProcess, SIGNAL_BROKEN_PIPE, NULL);
  439. }
  440. } else {
  441. Status = IoReadAtOffset(HandleValue,
  442. &IoBuffer,
  443. Parameters->Offset,
  444. Size,
  445. 0,
  446. Timeout,
  447. &(Parameters->Size),
  448. NULL);
  449. }
  450. if (!KSUCCESS(Status)) {
  451. goto SysPerformIoEnd;
  452. }
  453. SysPerformIoEnd:
  454. if (HandleValue != NULL) {
  455. IoIoHandleReleaseReference(HandleValue);
  456. }
  457. Parameters->Status = Status;
  458. return;
  459. }
  460. VOID
  461. IoSysPerformVectoredIo (
  462. ULONG SystemCallNumber,
  463. PVOID SystemCallParameter,
  464. PTRAP_FRAME TrapFrame,
  465. PULONG ResultSize
  466. )
  467. /*++
  468. Routine Description:
  469. This routine performs vectored I/O for user mode.
  470. Arguments:
  471. SystemCallNumber - Supplies the system call number that was requested.
  472. SystemCallParameter - Supplies a pointer to the parameters supplied with
  473. the system call. This structure will be a stack-local copy of the
  474. actual parameters passed from user-mode.
  475. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  476. from user mode to kernel mode.
  477. ResultSize - Supplies a pointer where the system call routine returns the
  478. size of the parameter structure to be copied back to user mode. The
  479. value returned here must be no larger than the original parameter
  480. structure size. The default is the original size of the parameters.
  481. Return Value:
  482. None.
  483. --*/
  484. {
  485. PKPROCESS CurrentProcess;
  486. PIO_HANDLE HandleValue;
  487. PIO_BUFFER IoBuffer;
  488. PSYSTEM_CALL_PERFORM_VECTORED_IO Parameters;
  489. UINTN Size;
  490. KSTATUS Status;
  491. ULONG Timeout;
  492. CurrentProcess = PsGetCurrentProcess();
  493. Parameters = (PSYSTEM_CALL_PERFORM_VECTORED_IO)SystemCallParameter;
  494. Size = Parameters->Size;
  495. Parameters->Size = 0;
  496. IoBuffer = NULL;
  497. HandleValue = ObGetHandleValue(CurrentProcess->HandleTable,
  498. Parameters->Handle,
  499. NULL);
  500. if (HandleValue == NULL) {
  501. Status = STATUS_INVALID_HANDLE;
  502. goto SysPerformVectoredIoEnd;
  503. }
  504. if (Size == 0) {
  505. Status = STATUS_SUCCESS;
  506. goto SysPerformVectoredIoEnd;
  507. }
  508. Timeout = Parameters->TimeoutInMilliseconds;
  509. ASSERT(SYS_WAIT_TIME_INDEFINITE == WAIT_TIME_INDEFINITE);
  510. //
  511. // Allocate an I/O buffer for this user mode buffer. Keep it in paged-pool,
  512. // and not pinned for now. If the particular I/O requests something more
  513. // serious, it will lock the buffer.
  514. //
  515. Status = MmCreateIoBufferFromVector(Parameters->VectorArray,
  516. FALSE,
  517. Parameters->VectorCount,
  518. &IoBuffer);
  519. if (!KSUCCESS(Status)) {
  520. goto SysPerformVectoredIoEnd;
  521. }
  522. //
  523. // Perform the file I/O.
  524. //
  525. if ((Parameters->Flags & SYS_IO_FLAG_WRITE) != 0) {
  526. Status = IoWriteAtOffset(HandleValue,
  527. IoBuffer,
  528. Parameters->Offset,
  529. Size,
  530. 0,
  531. Timeout,
  532. &(Parameters->Size),
  533. NULL);
  534. if (Status == STATUS_BROKEN_PIPE) {
  535. ASSERT(CurrentProcess != PsGetKernelProcess());
  536. PsSignalProcess(CurrentProcess, SIGNAL_BROKEN_PIPE, NULL);
  537. }
  538. } else {
  539. Status = IoReadAtOffset(HandleValue,
  540. IoBuffer,
  541. Parameters->Offset,
  542. Size,
  543. 0,
  544. Timeout,
  545. &(Parameters->Size),
  546. NULL);
  547. }
  548. if (!KSUCCESS(Status)) {
  549. goto SysPerformVectoredIoEnd;
  550. }
  551. SysPerformVectoredIoEnd:
  552. if (IoBuffer != NULL) {
  553. MmFreeIoBuffer(IoBuffer);
  554. }
  555. if (HandleValue != NULL) {
  556. IoIoHandleReleaseReference(HandleValue);
  557. }
  558. Parameters->Status = Status;
  559. return;
  560. }
  561. VOID
  562. IoSysFlush (
  563. ULONG SystemCallNumber,
  564. PVOID SystemCallParameter,
  565. PTRAP_FRAME TrapFrame,
  566. PULONG ResultSize
  567. )
  568. /*++
  569. Routine Description:
  570. This routine flushes data to its backing device for user mode.
  571. Arguments:
  572. SystemCallNumber - Supplies the system call number that was requested.
  573. SystemCallParameter - Supplies a pointer to the parameters supplied with
  574. the system call. This structure will be a stack-local copy of the
  575. actual parameters passed from user-mode.
  576. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  577. from user mode to kernel mode.
  578. ResultSize - Supplies a pointer where the system call routine returns the
  579. size of the parameter structure to be copied back to user mode. The
  580. value returned here must be no larger than the original parameter
  581. structure size. The default is the original size of the parameters.
  582. Return Value:
  583. None.
  584. --*/
  585. {
  586. PKPROCESS CurrentProcess;
  587. ULONG FlushFlags;
  588. PIO_HANDLE HandleValue;
  589. PSYSTEM_CALL_FLUSH Parameters;
  590. KSTATUS Status;
  591. CurrentProcess = PsGetCurrentProcess();
  592. ASSERT(CurrentProcess != PsGetKernelProcess());
  593. FlushFlags = 0;
  594. Parameters = (PSYSTEM_CALL_FLUSH)SystemCallParameter;
  595. if ((Parameters->Flags & SYS_FLUSH_FLAG_ALL) != 0) {
  596. FlushFlags = FLUSH_FLAG_ALL;
  597. HandleValue = NULL;
  598. } else {
  599. HandleValue = ObGetHandleValue(CurrentProcess->HandleTable,
  600. Parameters->Handle,
  601. NULL);
  602. if (HandleValue == NULL) {
  603. Status = STATUS_INVALID_HANDLE;
  604. goto SysFlushEnd;
  605. }
  606. ASSERT(HandleValue != INVALID_HANDLE);
  607. if ((Parameters->Flags & SYS_FLUSH_FLAG_READ) != 0) {
  608. FlushFlags |= FLUSH_FLAG_READ;
  609. }
  610. if ((Parameters->Flags & SYS_FLUSH_FLAG_WRITE) != 0) {
  611. FlushFlags |= FLUSH_FLAG_WRITE;
  612. }
  613. if ((Parameters->Flags & SYS_FLUSH_FLAG_DISCARD) != 0) {
  614. FlushFlags |= FLUSH_FLAG_DISCARD;
  615. }
  616. }
  617. Status = IoFlush(HandleValue, 0, -1, FlushFlags);
  618. if (!KSUCCESS(Status)) {
  619. goto SysFlushEnd;
  620. }
  621. SysFlushEnd:
  622. if (HandleValue != NULL) {
  623. IoIoHandleReleaseReference(HandleValue);
  624. }
  625. Parameters->Status = Status;
  626. return;
  627. }
  628. VOID
  629. IoSysCreatePipe (
  630. ULONG SystemCallNumber,
  631. PVOID SystemCallParameter,
  632. PTRAP_FRAME TrapFrame,
  633. PULONG ResultSize
  634. )
  635. /*++
  636. Routine Description:
  637. This routine creates a pipe on behalf of a user mode application.
  638. Arguments:
  639. SystemCallNumber - Supplies the system call number that was requested.
  640. SystemCallParameter - Supplies a pointer to the parameters supplied with
  641. the system call. This structure will be a stack-local copy of the
  642. actual parameters passed from user-mode.
  643. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  644. from user mode to kernel mode.
  645. ResultSize - Supplies a pointer where the system call routine returns the
  646. size of the parameter structure to be copied back to user mode. The
  647. value returned here must be no larger than the original parameter
  648. structure size. The default is the original size of the parameters.
  649. Return Value:
  650. None.
  651. --*/
  652. {
  653. PKPROCESS CurrentProcess;
  654. PIO_HANDLE Directory;
  655. ULONG HandleFlags;
  656. ULONG OpenFlags;
  657. PSYSTEM_CALL_CREATE_PIPE Parameters;
  658. PSTR PipePath;
  659. PIO_HANDLE ReadHandle;
  660. KSTATUS Status;
  661. PIO_HANDLE WriteHandle;
  662. CurrentProcess = PsGetCurrentProcess();
  663. ASSERT(CurrentProcess != PsGetKernelProcess());
  664. Directory = NULL;
  665. Parameters = (PSYSTEM_CALL_CREATE_PIPE)SystemCallParameter;
  666. Parameters->ReadHandle = INVALID_HANDLE;
  667. Parameters->WriteHandle = INVALID_HANDLE;
  668. ReadHandle = NULL;
  669. PipePath = NULL;
  670. WriteHandle = NULL;
  671. if (Parameters->PathLength != 0) {
  672. Status = MmCreateCopyOfUserModeString(Parameters->Path,
  673. Parameters->PathLength,
  674. FI_ALLOCATION_TAG,
  675. &PipePath);
  676. if (!KSUCCESS(Status)) {
  677. goto SysCreatePipeEnd;
  678. }
  679. }
  680. if (Parameters->Directory != INVALID_HANDLE) {
  681. Directory = ObGetHandleValue(CurrentProcess->HandleTable,
  682. Parameters->Directory,
  683. NULL);
  684. if (Directory == NULL) {
  685. Status = STATUS_INVALID_HANDLE;
  686. goto SysCreatePipeEnd;
  687. }
  688. }
  689. if ((Parameters->OpenFlags &
  690. ~(SYS_OPEN_FLAG_NON_BLOCKING | SYS_OPEN_FLAG_CLOSE_ON_EXECUTE)) != 0) {
  691. Status = STATUS_INVALID_PARAMETER;
  692. goto SysCreatePipeEnd;
  693. }
  694. OpenFlags = Parameters->OpenFlags & SYS_OPEN_FLAG_NON_BLOCKING;
  695. //
  696. // Create the pipe.
  697. //
  698. Status = IoCreatePipe(FALSE,
  699. Directory,
  700. PipePath,
  701. Parameters->PathLength,
  702. OpenFlags,
  703. Parameters->Permissions,
  704. &ReadHandle,
  705. &WriteHandle);
  706. if (!KSUCCESS(Status)) {
  707. goto SysCreatePipeEnd;
  708. }
  709. //
  710. // Create user mode handles if no path was specified.
  711. //
  712. if (PipePath == NULL) {
  713. //
  714. // Create handle table entries for these handles.
  715. //
  716. HandleFlags = 0;
  717. if ((Parameters->OpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
  718. HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  719. }
  720. Status = ObCreateHandle(CurrentProcess->HandleTable,
  721. ReadHandle,
  722. HandleFlags,
  723. &(Parameters->ReadHandle));
  724. if (!KSUCCESS(Status)) {
  725. goto SysCreatePipeEnd;
  726. }
  727. Status = ObCreateHandle(CurrentProcess->HandleTable,
  728. WriteHandle,
  729. HandleFlags,
  730. &(Parameters->WriteHandle));
  731. if (!KSUCCESS(Status)) {
  732. goto SysCreatePipeEnd;
  733. }
  734. } else {
  735. IoClose(ReadHandle);
  736. IoClose(WriteHandle);
  737. ReadHandle = NULL;
  738. WriteHandle = NULL;
  739. }
  740. Status = STATUS_SUCCESS;
  741. SysCreatePipeEnd:
  742. if (Directory != NULL) {
  743. IoIoHandleReleaseReference(Directory);
  744. }
  745. if (PipePath != NULL) {
  746. MmFreePagedPool(PipePath);
  747. }
  748. if (!KSUCCESS(Status)) {
  749. if (ReadHandle != NULL) {
  750. IoClose(ReadHandle);
  751. }
  752. if (WriteHandle != NULL) {
  753. IoClose(WriteHandle);
  754. }
  755. if (Parameters->ReadHandle != INVALID_HANDLE) {
  756. ObDestroyHandle(CurrentProcess->HandleTable,
  757. Parameters->ReadHandle);
  758. }
  759. if (Parameters->WriteHandle != INVALID_HANDLE) {
  760. ObDestroyHandle(CurrentProcess->HandleTable,
  761. Parameters->WriteHandle);
  762. }
  763. }
  764. Parameters->Status = Status;
  765. return;
  766. }
  767. VOID
  768. IoSysGetCurrentDirectory (
  769. ULONG SystemCallNumber,
  770. PVOID SystemCallParameter,
  771. PTRAP_FRAME TrapFrame,
  772. PULONG ResultSize
  773. )
  774. /*++
  775. Routine Description:
  776. This routine handles the system call requesting the path of the current
  777. working directory.
  778. Arguments:
  779. SystemCallNumber - Supplies the system call number that was requested.
  780. SystemCallParameter - Supplies a pointer to the parameters supplied with
  781. the system call. This structure will be a stack-local copy of the
  782. actual parameters passed from user-mode.
  783. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  784. from user mode to kernel mode.
  785. ResultSize - Supplies a pointer where the system call routine returns the
  786. size of the parameter structure to be copied back to user mode. The
  787. value returned here must be no larger than the original parameter
  788. structure size. The default is the original size of the parameters.
  789. Return Value:
  790. None.
  791. --*/
  792. {
  793. PPATH_POINT CurrentDirectory;
  794. PATH_POINT CurrentDirectoryCopy;
  795. PSYSTEM_CALL_GET_CURRENT_DIRECTORY Parameters;
  796. PPROCESS_PATHS Paths;
  797. PKPROCESS Process;
  798. PPATH_POINT RootDirectory;
  799. PATH_POINT RootDirectoryCopy;
  800. KSTATUS Status;
  801. ASSERT(SystemCallNumber == SystemCallGetCurrentDirectory);
  802. Parameters = (PSYSTEM_CALL_GET_CURRENT_DIRECTORY)SystemCallParameter;
  803. Process = PsGetCurrentProcess();
  804. ASSERT(Process != PsGetKernelProcess());
  805. //
  806. // Get the path entries for this process's current directory and root
  807. // directory.
  808. //
  809. CurrentDirectory = NULL;
  810. RootDirectory = NULL;
  811. Paths = &(Process->Paths);
  812. KeAcquireQueuedLock(Paths->Lock);
  813. if (Parameters->Root != FALSE) {
  814. if (Paths->Root.PathEntry != NULL) {
  815. IO_COPY_PATH_POINT(&CurrentDirectoryCopy, &(Paths->Root));
  816. IO_PATH_POINT_ADD_REFERENCE(&CurrentDirectoryCopy);
  817. CurrentDirectory = &CurrentDirectoryCopy;
  818. }
  819. //
  820. // Leave the root NULL for now (i.e. the real root). It will get set to
  821. // the current directory if the caller does not have permission to
  822. // escape a changed root.
  823. //
  824. } else {
  825. ASSERT(Paths->CurrentDirectory.PathEntry != NULL);
  826. IO_COPY_PATH_POINT(&CurrentDirectoryCopy, &(Paths->CurrentDirectory));
  827. IO_PATH_POINT_ADD_REFERENCE(&CurrentDirectoryCopy);
  828. CurrentDirectory = &CurrentDirectoryCopy;
  829. if (Paths->Root.PathEntry != NULL) {
  830. IO_COPY_PATH_POINT(&RootDirectoryCopy, &(Paths->Root));
  831. IO_PATH_POINT_ADD_REFERENCE(&RootDirectoryCopy);
  832. RootDirectory = &RootDirectoryCopy;
  833. }
  834. }
  835. KeReleaseQueuedLock(Process->Paths.Lock);
  836. //
  837. // If the caller does not have permission to escape a changed root, then
  838. // pretend they're at the real root.
  839. //
  840. if ((Parameters->Root != FALSE) &&
  841. (!KSUCCESS(PsCheckPermission(PERMISSION_ESCAPE_CHROOT)))) {
  842. RootDirectory = CurrentDirectory;
  843. if (RootDirectory != NULL) {
  844. IO_PATH_POINT_ADD_REFERENCE(RootDirectory);
  845. }
  846. }
  847. Status = IopGetUserFilePath(CurrentDirectory,
  848. RootDirectory,
  849. Parameters->Buffer,
  850. &(Parameters->BufferSize));
  851. if (!KSUCCESS(Status)) {
  852. goto SysGetCurrentDirectoryEnd;
  853. }
  854. SysGetCurrentDirectoryEnd:
  855. if (CurrentDirectory != NULL) {
  856. IO_PATH_POINT_RELEASE_REFERENCE(CurrentDirectory);
  857. }
  858. if (RootDirectory != NULL) {
  859. IO_PATH_POINT_RELEASE_REFERENCE(RootDirectory);
  860. }
  861. Parameters->Status = Status;
  862. return;
  863. }
  864. VOID
  865. IoSysChangeDirectory (
  866. ULONG SystemCallNumber,
  867. PVOID SystemCallParameter,
  868. PTRAP_FRAME TrapFrame,
  869. PULONG ResultSize
  870. )
  871. /*++
  872. Routine Description:
  873. This routine handles the system call requesting to change the current
  874. working directory.
  875. Arguments:
  876. SystemCallNumber - Supplies the system call number that was requested.
  877. SystemCallParameter - Supplies a pointer to the parameters supplied with
  878. the system call. This structure will be a stack-local copy of the
  879. actual parameters passed from user-mode.
  880. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  881. from user mode to kernel mode.
  882. ResultSize - Supplies a pointer where the system call routine returns the
  883. size of the parameter structure to be copied back to user mode. The
  884. value returned here must be no larger than the original parameter
  885. structure size. The default is the original size of the parameters.
  886. Return Value:
  887. None.
  888. --*/
  889. {
  890. BOOL EscapeRoot;
  891. PIO_HANDLE ExistingHandle;
  892. PFILE_OBJECT FileObject;
  893. PIO_HANDLE NewHandle;
  894. PSTR NewPath;
  895. ULONG NewPathSize;
  896. PATH_POINT OldPathPoint;
  897. PSYSTEM_CALL_CHANGE_DIRECTORY Parameters;
  898. PPATH_POINT PathPoint;
  899. PKPROCESS Process;
  900. KSTATUS Status;
  901. ASSERT(SystemCallNumber == SystemCallChangeDirectory);
  902. Parameters = (PSYSTEM_CALL_CHANGE_DIRECTORY)SystemCallParameter;
  903. EscapeRoot = FALSE;
  904. ExistingHandle = NULL;
  905. PathPoint = NULL;
  906. NewHandle = NULL;
  907. NewPath = NULL;
  908. Process = PsGetCurrentProcess();
  909. ASSERT(Process != PsGetKernelProcess());
  910. //
  911. // There are a few rules if the caller is trying to change the root. The
  912. // usual way to escape a changed root is to use an open directory
  913. // descriptor outside the changed root. Disallow this by refusing to change
  914. // the root if there's an open directory descriptor. Enforce a thread
  915. // count of one to prevent race conditions where directories are opened
  916. // just as the root changes.
  917. //
  918. if (Parameters->Root != FALSE) {
  919. Status = PsCheckPermission(PERMISSION_CHROOT);
  920. if (!KSUCCESS(Status)) {
  921. goto SysChangeDirectoryEnd;
  922. }
  923. if (Process->ThreadCount != 1) {
  924. Status = STATUS_PERMISSION_DENIED;
  925. goto SysChangeDirectoryEnd;
  926. }
  927. Parameters->Status = STATUS_SUCCESS;
  928. ObHandleTableIterate(Process->HandleTable,
  929. IopCheckForDirectoryHandlesIterationRoutine,
  930. &Status);
  931. if (!KSUCCESS(Parameters->Status)) {
  932. goto SysChangeDirectoryEnd;
  933. }
  934. //
  935. // If all parameters are invalid, the caller is requesting to escape
  936. // the root.
  937. //
  938. if ((Parameters->Handle == INVALID_HANDLE) &&
  939. (Parameters->Buffer == NULL) &&
  940. (Parameters->BufferLength == 0)) {
  941. Status = PsCheckPermission(PERMISSION_ESCAPE_CHROOT);
  942. if (!KSUCCESS(Status)) {
  943. goto SysChangeDirectoryEnd;
  944. }
  945. EscapeRoot = TRUE;
  946. }
  947. }
  948. //
  949. // If a handle was supplied, use the handle.
  950. //
  951. if (Parameters->Handle != INVALID_HANDLE) {
  952. ExistingHandle = ObGetHandleValue(Process->HandleTable,
  953. Parameters->Handle,
  954. NULL);
  955. if (ExistingHandle == NULL) {
  956. Status = STATUS_INVALID_HANDLE;
  957. goto SysChangeDirectoryEnd;
  958. }
  959. PathPoint = &(ExistingHandle->PathPoint);
  960. FileObject = PathPoint->PathEntry->FileObject;
  961. if ((FileObject->Properties.Type != IoObjectRegularDirectory) &&
  962. (FileObject->Properties.Type != IoObjectObjectDirectory)) {
  963. Status = STATUS_NOT_A_DIRECTORY;
  964. goto SysChangeDirectoryEnd;
  965. }
  966. ASSERT(FileObject == ExistingHandle->FileObject);
  967. //
  968. // More commonly a path was supplied, so open the path.
  969. //
  970. } else if (EscapeRoot == FALSE) {
  971. //
  972. // Create a copy of the user mode string so it cannot be manipulated
  973. // during the call.
  974. //
  975. NewPathSize = Parameters->BufferLength;
  976. Status = MmCreateCopyOfUserModeString(Parameters->Buffer,
  977. NewPathSize,
  978. FI_ALLOCATION_TAG,
  979. &NewPath);
  980. if (!KSUCCESS(Status)) {
  981. goto SysChangeDirectoryEnd;
  982. }
  983. //
  984. // Open up the new working directory.
  985. //
  986. Status = IoOpen(FALSE,
  987. NULL,
  988. NewPath,
  989. NewPathSize,
  990. 0,
  991. OPEN_FLAG_DIRECTORY,
  992. FILE_PERMISSION_NONE,
  993. &NewHandle);
  994. if (!KSUCCESS(Status)) {
  995. goto SysChangeDirectoryEnd;
  996. }
  997. PathPoint = &(NewHandle->PathPoint);
  998. //
  999. // The caller is escaping back to the one true root.
  1000. //
  1001. } else {
  1002. PathPoint = &IoPathPointRoot;
  1003. }
  1004. //
  1005. // Replace the current working directory or root directory.
  1006. //
  1007. IO_PATH_POINT_ADD_REFERENCE(PathPoint);
  1008. KeAcquireQueuedLock(Process->Paths.Lock);
  1009. if (Parameters->Root != FALSE) {
  1010. IO_COPY_PATH_POINT(&OldPathPoint, &(Process->Paths.Root));
  1011. IO_COPY_PATH_POINT(&(Process->Paths.Root), PathPoint);
  1012. } else {
  1013. IO_COPY_PATH_POINT(&OldPathPoint, &(Process->Paths.CurrentDirectory));
  1014. IO_COPY_PATH_POINT(&(Process->Paths.CurrentDirectory), PathPoint);
  1015. }
  1016. KeReleaseQueuedLock(Process->Paths.Lock);
  1017. if (OldPathPoint.PathEntry != NULL) {
  1018. IO_PATH_POINT_RELEASE_REFERENCE(&OldPathPoint);
  1019. }
  1020. Status = STATUS_SUCCESS;
  1021. SysChangeDirectoryEnd:
  1022. if (ExistingHandle != NULL) {
  1023. IoIoHandleReleaseReference(ExistingHandle);
  1024. }
  1025. if (NewHandle != NULL) {
  1026. IoClose(NewHandle);
  1027. }
  1028. if (NewPath != NULL) {
  1029. MmFreePagedPool(NewPath);
  1030. }
  1031. Parameters->Status = Status;
  1032. return;
  1033. }
  1034. VOID
  1035. IoSysPoll (
  1036. ULONG SystemCallNumber,
  1037. PVOID SystemCallParameter,
  1038. PTRAP_FRAME TrapFrame,
  1039. PULONG ResultSize
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. This routine handles the poll system call, which waits on several I/O
  1044. handles.
  1045. Arguments:
  1046. SystemCallNumber - Supplies the system call number that was requested.
  1047. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1048. the system call. This structure will be a stack-local copy of the
  1049. actual parameters passed from user-mode.
  1050. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1051. from user mode to kernel mode.
  1052. ResultSize - Supplies a pointer where the system call routine returns the
  1053. size of the parameter structure to be copied back to user mode. The
  1054. value returned here must be no larger than the original parameter
  1055. structure size. The default is the original size of the parameters.
  1056. Return Value:
  1057. None.
  1058. --*/
  1059. {
  1060. ULONG AllocationSize;
  1061. ULONG DescriptorCount;
  1062. ULONG DescriptorIndex;
  1063. PPOLL_DESCRIPTOR Descriptors;
  1064. BOOL ErrorEventsOccurred;
  1065. PFILE_OBJECT FileObject;
  1066. HANDLE Handle;
  1067. BOOL HaveRegularFiles;
  1068. PIO_HANDLE IoHandle;
  1069. PIO_OBJECT_STATE IoObjectState;
  1070. ULONG MaskedEvents;
  1071. ULONGLONG Microseconds;
  1072. ULONGLONG ObjectIndex;
  1073. SIGNAL_SET OldSignalSet;
  1074. PSYSTEM_CALL_POLL PollInformation;
  1075. PKPROCESS Process;
  1076. BOOL RestoreSignalMask;
  1077. ULONG SelectedDescriptors;
  1078. SIGNAL_SET SignalMask;
  1079. KSTATUS Status;
  1080. PKTHREAD Thread;
  1081. PPOLL_DESCRIPTOR UserDescriptors;
  1082. ULONG WaitEvents;
  1083. PVOID *WaitObjects;
  1084. Descriptors = NULL;
  1085. ErrorEventsOccurred = FALSE;
  1086. HaveRegularFiles = FALSE;
  1087. PollInformation = (PSYSTEM_CALL_POLL)SystemCallParameter;
  1088. DescriptorCount = PollInformation->DescriptorCount;
  1089. Thread = KeGetCurrentThread();
  1090. Process = Thread->OwningProcess;
  1091. RestoreSignalMask = FALSE;
  1092. SelectedDescriptors = 0;
  1093. WaitObjects = NULL;
  1094. //
  1095. // Set the signal mask if supplied.
  1096. //
  1097. if (PollInformation->SignalMask != NULL) {
  1098. Status = MmCopyFromUserMode(&SignalMask,
  1099. PollInformation->SignalMask,
  1100. sizeof(SIGNAL_SET));
  1101. if (!KSUCCESS(Status)) {
  1102. goto PollEnd;
  1103. }
  1104. PsSetSignalMask(&SignalMask, &OldSignalSet);
  1105. RestoreSignalMask = TRUE;
  1106. }
  1107. //
  1108. // Polling nothing is easy.
  1109. //
  1110. if ((PollInformation->Descriptors == NULL) || (DescriptorCount == 0)) {
  1111. Microseconds = PollInformation->TimeoutInMilliseconds *
  1112. MICROSECONDS_PER_MILLISECOND;
  1113. Status = KeDelayExecution(TRUE, FALSE, Microseconds);
  1114. goto PollEnd;
  1115. }
  1116. UserDescriptors = PollInformation->Descriptors;
  1117. //
  1118. // Allocate space for a kernel mode array of poll descriptors.
  1119. //
  1120. AllocationSize = sizeof(POLL_DESCRIPTOR) * DescriptorCount;
  1121. Descriptors = MmAllocatePagedPool(AllocationSize, IO_ALLOCATION_TAG);
  1122. if (Descriptors == NULL) {
  1123. Status = STATUS_INSUFFICIENT_RESOURCES;
  1124. goto PollEnd;
  1125. }
  1126. Status = MmCopyFromUserMode(Descriptors, UserDescriptors, AllocationSize);
  1127. if (!KSUCCESS(Status)) {
  1128. RtlZeroMemory(Descriptors, AllocationSize);
  1129. goto PollEnd;
  1130. }
  1131. //
  1132. // Clear the returned events in the array, and translate the user mode
  1133. // handles into kernel mode handles.
  1134. //
  1135. for (DescriptorIndex = 0;
  1136. DescriptorIndex < DescriptorCount;
  1137. DescriptorIndex += 1) {
  1138. Handle = Descriptors[DescriptorIndex].Handle;
  1139. Descriptors[DescriptorIndex].ReturnedEvents = 0;
  1140. if (Handle == INVALID_HANDLE) {
  1141. Descriptors[DescriptorIndex].Handle = NULL;
  1142. continue;
  1143. }
  1144. Descriptors[DescriptorIndex].Handle =
  1145. ObGetHandleValue(Process->HandleTable, Handle, NULL);
  1146. if (Descriptors[DescriptorIndex].Handle == NULL) {
  1147. Descriptors[DescriptorIndex].ReturnedEvents |=
  1148. POLL_EVENT_INVALID_HANDLE;
  1149. ErrorEventsOccurred = TRUE;
  1150. }
  1151. }
  1152. //
  1153. // Allocate space for the wait objects, assuming the worst case that every
  1154. // descriptor wants to wait on error, read, high priority read, write, and
  1155. // high priority write.
  1156. //
  1157. AllocationSize = 5 * DescriptorCount * sizeof(PVOID);
  1158. WaitObjects = MmAllocatePagedPool(AllocationSize, IO_ALLOCATION_TAG);
  1159. if (WaitObjects == NULL) {
  1160. Status = STATUS_INSUFFICIENT_RESOURCES;
  1161. goto PollEnd;
  1162. }
  1163. RtlZeroMemory(WaitObjects, AllocationSize);
  1164. //
  1165. // Add all the qualifying objects to the array of things to wait for.
  1166. //
  1167. ObjectIndex = 0;
  1168. for (DescriptorIndex = 0;
  1169. DescriptorIndex < DescriptorCount;
  1170. DescriptorIndex += 1) {
  1171. WaitEvents = Descriptors[DescriptorIndex].Events;
  1172. IoHandle = Descriptors[DescriptorIndex].Handle;
  1173. if ((WaitEvents == 0) || (IoHandle == NULL)) {
  1174. continue;
  1175. }
  1176. FileObject = IoHandle->FileObject;
  1177. //
  1178. // Regular files and directories always poll TRUE for reading and
  1179. // writing. Only look at the events for non-file descriptors.
  1180. //
  1181. ASSERT(FileObject->Properties.Type != IoObjectSymbolicLink);
  1182. if ((FileObject->Properties.Type == IoObjectRegularFile) ||
  1183. (FileObject->Properties.Type == IoObjectRegularDirectory) ||
  1184. (FileObject->Properties.Type == IoObjectObjectDirectory) ||
  1185. (FileObject->Properties.Type == IoObjectSharedMemoryObject)) {
  1186. HaveRegularFiles = TRUE;
  1187. continue;
  1188. }
  1189. IoObjectState = FileObject->IoState;
  1190. ASSERT(IoObjectState != NULL);
  1191. //
  1192. // Always wait on the error event.
  1193. //
  1194. WaitObjects[ObjectIndex] = IoObjectState->ErrorEvent;
  1195. ObjectIndex += 1;
  1196. if ((WaitEvents & POLL_EVENT_IN) != 0) {
  1197. WaitObjects[ObjectIndex] = IoObjectState->ReadEvent;
  1198. ObjectIndex += 1;
  1199. }
  1200. if (((WaitEvents & POLL_EVENT_IN_HIGH_PRIORITY) != 0) &&
  1201. (IoObjectState->ReadHighPriorityEvent != NULL)) {
  1202. WaitObjects[ObjectIndex] = IoObjectState->ReadHighPriorityEvent;
  1203. ObjectIndex += 1;
  1204. }
  1205. if ((WaitEvents & POLL_EVENT_OUT) != 0) {
  1206. WaitObjects[ObjectIndex] = IoObjectState->WriteEvent;
  1207. ObjectIndex += 1;
  1208. }
  1209. if (((WaitEvents & POLL_EVENT_OUT_HIGH_PRIORITY) != 0) &&
  1210. (IoObjectState->WriteHighPriorityEvent != NULL)) {
  1211. WaitObjects[ObjectIndex] = IoObjectState->WriteHighPriorityEvent;
  1212. ObjectIndex += 1;
  1213. }
  1214. }
  1215. ASSERT(ObjectIndex <= 5 * DescriptorCount);
  1216. //
  1217. // Wait on this list of objects.
  1218. //
  1219. ASSERT((ULONG)ObjectIndex == ObjectIndex);
  1220. if ((ErrorEventsOccurred == FALSE) && (HaveRegularFiles == FALSE)) {
  1221. Status = ObWaitOnObjects(
  1222. WaitObjects,
  1223. ObjectIndex,
  1224. WAIT_FLAG_INTERRUPTIBLE,
  1225. PollInformation->TimeoutInMilliseconds,
  1226. NULL,
  1227. NULL);
  1228. if (!KSUCCESS(Status)) {
  1229. goto PollEnd;
  1230. }
  1231. }
  1232. //
  1233. // Loop through and read out all the poll flags.
  1234. //
  1235. for (DescriptorIndex = 0;
  1236. DescriptorIndex < DescriptorCount;
  1237. DescriptorIndex += 1) {
  1238. WaitEvents = Descriptors[DescriptorIndex].Events;
  1239. IoHandle = Descriptors[DescriptorIndex].Handle;
  1240. if ((IoHandle == NULL) || (WaitEvents == 0)) {
  1241. continue;
  1242. }
  1243. //
  1244. // If this descriptor fits the bill, increment the count of
  1245. // selected descriptors.
  1246. //
  1247. FileObject = IoHandle->FileObject;
  1248. if ((FileObject->Properties.Type == IoObjectRegularFile) ||
  1249. (FileObject->Properties.Type == IoObjectRegularDirectory) ||
  1250. (FileObject->Properties.Type == IoObjectObjectDirectory) ||
  1251. (FileObject->Properties.Type == IoObjectSharedMemoryObject)) {
  1252. MaskedEvents = WaitEvents & POLL_NONMASKABLE_FILE_EVENTS;
  1253. } else {
  1254. IoObjectState = FileObject->IoState;
  1255. ASSERT(IoObjectState != NULL);
  1256. //
  1257. // The I/O object state maintains a bitmask of all the currently
  1258. // signaled poll events. AND this with the requested events to get
  1259. // the returned events for this descriptor.
  1260. //
  1261. MaskedEvents = IoObjectState->Events &
  1262. (WaitEvents | POLL_NONMASKABLE_EVENTS);
  1263. }
  1264. if (MaskedEvents != 0) {
  1265. SelectedDescriptors += 1;
  1266. }
  1267. Descriptors[DescriptorIndex].ReturnedEvents |= MaskedEvents;
  1268. Status = MmUserWrite32(
  1269. &(UserDescriptors[DescriptorIndex].ReturnedEvents),
  1270. Descriptors[DescriptorIndex].ReturnedEvents);
  1271. if (Status == FALSE) {
  1272. Status = STATUS_ACCESS_VIOLATION;
  1273. goto PollEnd;
  1274. }
  1275. }
  1276. Status = STATUS_SUCCESS;
  1277. PollEnd:
  1278. if (RestoreSignalMask != FALSE) {
  1279. //
  1280. // Queue up signals before resetting the mask.
  1281. //
  1282. PsCheckRuntimeTimers(Thread);
  1283. PsDispatchPendingSignals(Thread, TrapFrame);
  1284. PsSetSignalMask(&OldSignalSet, NULL);
  1285. }
  1286. if (WaitObjects != NULL) {
  1287. MmFreePagedPool(WaitObjects);
  1288. }
  1289. if (Descriptors != NULL) {
  1290. //
  1291. // For any handle that was successfully looked up, release the
  1292. // reference that lookup added.
  1293. //
  1294. for (DescriptorIndex = 0;
  1295. DescriptorIndex < DescriptorCount;
  1296. DescriptorIndex += 1) {
  1297. if (Descriptors[DescriptorIndex].Handle != NULL) {
  1298. IoIoHandleReleaseReference(Descriptors[DescriptorIndex].Handle);
  1299. }
  1300. }
  1301. MmFreePagedPool(Descriptors);
  1302. }
  1303. PollInformation->Status = Status;
  1304. PollInformation->DescriptorsSelected = SelectedDescriptors;
  1305. return;
  1306. }
  1307. VOID
  1308. IoSysDuplicateHandle (
  1309. ULONG SystemCallNumber,
  1310. PVOID SystemCallParameter,
  1311. PTRAP_FRAME TrapFrame,
  1312. PULONG ResultSize
  1313. )
  1314. /*++
  1315. Routine Description:
  1316. This routine implements the system call for duplicating a file handle.
  1317. Arguments:
  1318. SystemCallNumber - Supplies the system call number that was requested.
  1319. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1320. the system call. This structure will be a stack-local copy of the
  1321. actual parameters passed from user-mode.
  1322. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1323. from user mode to kernel mode.
  1324. ResultSize - Supplies a pointer where the system call routine returns the
  1325. size of the parameter structure to be copied back to user mode. The
  1326. value returned here must be no larger than the original parameter
  1327. structure size. The default is the original size of the parameters.
  1328. Return Value:
  1329. None.
  1330. --*/
  1331. {
  1332. ULONG HandleFlags;
  1333. PIO_HANDLE IoHandle;
  1334. PVOID OldValue;
  1335. PSYSTEM_CALL_DUPLICATE_HANDLE Parameters;
  1336. PKPROCESS Process;
  1337. KSTATUS Status;
  1338. Parameters = (PSYSTEM_CALL_DUPLICATE_HANDLE)SystemCallParameter;
  1339. Process = PsGetCurrentProcess();
  1340. //
  1341. // First check to see if the old handle is valid (and take a reference on
  1342. // it).
  1343. //
  1344. IoHandle = ObGetHandleValue(Process->HandleTable,
  1345. Parameters->OldHandle,
  1346. NULL);
  1347. if (IoHandle == NULL) {
  1348. Status = STATUS_INVALID_HANDLE;
  1349. goto SysDuplicateHandleEnd;
  1350. }
  1351. HandleFlags = 0;
  1352. if ((Parameters->OpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
  1353. HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  1354. }
  1355. //
  1356. // If the new handle and the old handle are the same, then just return
  1357. // success. That is unless the caller was trying to set the close on
  1358. // execute flag, which is an illegal way to try and do that.
  1359. //
  1360. if (Parameters->OldHandle == Parameters->NewHandle) {
  1361. Status = STATUS_SUCCESS;
  1362. if (HandleFlags != 0) {
  1363. Status = STATUS_INVALID_PARAMETER;
  1364. }
  1365. goto SysDuplicateHandleEnd;
  1366. }
  1367. //
  1368. // If the caller doesn't care where the handle comes from, then allocate
  1369. // any handle.
  1370. //
  1371. if (Parameters->NewHandle == INVALID_HANDLE) {
  1372. Status = ObCreateHandle(Process->HandleTable,
  1373. IoHandle,
  1374. HandleFlags,
  1375. &(Parameters->NewHandle));
  1376. if (!KSUCCESS(Status)) {
  1377. goto SysDuplicateHandleEnd;
  1378. }
  1379. //
  1380. // Replace a specific handle value.
  1381. //
  1382. } else {
  1383. Status = ObReplaceHandleValue(Process->HandleTable,
  1384. Parameters->NewHandle,
  1385. IoHandle,
  1386. HandleFlags,
  1387. &OldValue,
  1388. NULL);
  1389. if (!KSUCCESS(Status)) {
  1390. goto SysDuplicateHandleEnd;
  1391. }
  1392. //
  1393. // Close the old handle.
  1394. //
  1395. if (OldValue != NULL) {
  1396. IopRemoveFileLocks(OldValue, Process);
  1397. IoClose(OldValue);
  1398. }
  1399. }
  1400. //
  1401. // The reference taken during lookup is given to the new handle, so
  1402. // NULL out the I/O handle so it doesn't get released at the end.
  1403. //
  1404. IoHandle = NULL;
  1405. Status = STATUS_SUCCESS;
  1406. SysDuplicateHandleEnd:
  1407. if (IoHandle != NULL) {
  1408. IoIoHandleReleaseReference(IoHandle);
  1409. }
  1410. Parameters->Status = Status;
  1411. }
  1412. VOID
  1413. IoSysFileControl (
  1414. ULONG SystemCallNumber,
  1415. PVOID SystemCallParameter,
  1416. PTRAP_FRAME TrapFrame,
  1417. PULONG ResultSize
  1418. )
  1419. /*++
  1420. Routine Description:
  1421. This routine implements the file control system call.
  1422. Arguments:
  1423. SystemCallNumber - Supplies the system call number that was requested.
  1424. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1425. the system call. This structure will be a stack-local copy of the
  1426. actual parameters passed from user-mode.
  1427. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1428. from user mode to kernel mode.
  1429. ResultSize - Supplies a pointer where the system call routine returns the
  1430. size of the parameter structure to be copied back to user mode. The
  1431. value returned here must be no larger than the original parameter
  1432. structure size. The default is the original size of the parameters.
  1433. Return Value:
  1434. None.
  1435. --*/
  1436. {
  1437. BOOL Asynchronous;
  1438. PIO_ASYNC_STATE AsyncState;
  1439. BOOL Blocking;
  1440. UINTN CopyOutSize;
  1441. PSYSTEM_CALL_FILE_CONTROL FileControl;
  1442. PFILE_OBJECT FileObject;
  1443. ULONG Flags;
  1444. PIO_HANDLE IoHandle;
  1445. PIO_OBJECT_STATE IoState;
  1446. FILE_CONTROL_PARAMETERS_UNION LocalParameters;
  1447. ULONG Mask;
  1448. PKPROCESS Process;
  1449. PATH_POINT RootPathPoint;
  1450. ULONG SetFlags;
  1451. KSTATUS Status;
  1452. PKTHREAD Thread;
  1453. ASSERT(SystemCallNumber == SystemCallFileControl);
  1454. Blocking = FALSE;
  1455. CopyOutSize = 0;
  1456. Flags = 0;
  1457. FileControl = (PSYSTEM_CALL_FILE_CONTROL)SystemCallParameter;
  1458. Process = PsGetCurrentProcess();
  1459. IoHandle = NULL;
  1460. //
  1461. // Get the handle and the flags. The "close from" operation is the only
  1462. // exception, it doesn't actually need a valid handle.
  1463. //
  1464. if (FileControl->Command != FileControlCommandCloseFrom) {
  1465. IoHandle = ObGetHandleValue(Process->HandleTable,
  1466. FileControl->File,
  1467. &Flags);
  1468. if (IoHandle == NULL) {
  1469. Status = STATUS_INVALID_HANDLE;
  1470. goto SysFileControlEnd;
  1471. }
  1472. }
  1473. switch (FileControl->Command) {
  1474. case FileControlCommandDuplicate:
  1475. if (FileControl->Parameters == NULL) {
  1476. Status = STATUS_INVALID_PARAMETER;
  1477. goto SysFileControlEnd;
  1478. }
  1479. Status = MmCopyFromUserMode(&LocalParameters,
  1480. FileControl->Parameters,
  1481. sizeof(HANDLE));
  1482. if (!KSUCCESS(Status)) {
  1483. goto SysFileControlEnd;
  1484. }
  1485. if (LocalParameters.DuplicateDescriptor >= (HANDLE)OB_MAX_HANDLES) {
  1486. Status = STATUS_INVALID_PARAMETER;
  1487. goto SysFileControlEnd;
  1488. }
  1489. Flags &= ~FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  1490. //
  1491. // Increment the reference count on the I/O handle first, since as soon
  1492. // as the new descriptor is created user mode could come in on a
  1493. // different thread and close it.
  1494. //
  1495. IoIoHandleAddReference(IoHandle);
  1496. Status = ObCreateHandle(Process->HandleTable,
  1497. IoHandle,
  1498. Flags,
  1499. &(LocalParameters.DuplicateDescriptor));
  1500. if (KSUCCESS(Status)) {
  1501. CopyOutSize = sizeof(HANDLE);
  1502. } else {
  1503. IoIoHandleReleaseReference(IoHandle);
  1504. }
  1505. break;
  1506. case FileControlCommandGetFlags:
  1507. LocalParameters.Flags = Flags;
  1508. CopyOutSize = sizeof(ULONG);
  1509. break;
  1510. case FileControlCommandSetFlags:
  1511. if (FileControl->Parameters == NULL) {
  1512. Status = STATUS_INVALID_PARAMETER;
  1513. goto SysFileControlEnd;
  1514. }
  1515. Status = MmCopyFromUserMode(&LocalParameters,
  1516. FileControl->Parameters,
  1517. sizeof(ULONG));
  1518. if (!KSUCCESS(Status)) {
  1519. goto SysFileControlEnd;
  1520. }
  1521. SetFlags = LocalParameters.Flags;
  1522. Flags &= ~FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  1523. if ((SetFlags & FILE_DESCRIPTOR_CLOSE_ON_EXECUTE) != 0) {
  1524. Flags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  1525. SetFlags &= ~FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  1526. }
  1527. if (SetFlags != 0) {
  1528. Status = STATUS_INVALID_PARAMETER;
  1529. } else {
  1530. Status = ObGetSetHandleFlags(Process->HandleTable,
  1531. FileControl->File,
  1532. TRUE,
  1533. &Flags);
  1534. if (!KSUCCESS(Status)) {
  1535. goto SysFileControlEnd;
  1536. }
  1537. }
  1538. break;
  1539. case FileControlCommandGetStatusAndAccess:
  1540. ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
  1541. Flags = (IoHandle->OpenFlags & SYS_OPEN_FLAG_MASK) |
  1542. (IoHandle->Access << SYS_OPEN_ACCESS_SHIFT);
  1543. LocalParameters.Flags = Flags;
  1544. CopyOutSize = sizeof(ULONG);
  1545. break;
  1546. case FileControlCommandSetStatus:
  1547. if (FileControl->Parameters == NULL) {
  1548. Status = STATUS_INVALID_PARAMETER;
  1549. goto SysFileControlEnd;
  1550. }
  1551. Status = MmCopyFromUserMode(&LocalParameters,
  1552. FileControl->Parameters,
  1553. sizeof(ULONG));
  1554. if (!KSUCCESS(Status)) {
  1555. goto SysFileControlEnd;
  1556. }
  1557. //
  1558. // Set the new flags except for the asynchronous flag, which is handled
  1559. // by another function.
  1560. //
  1561. ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
  1562. Mask = SYS_FILE_CONTROL_EDITABLE_STATUS_FLAGS & ~OPEN_FLAG_ASYNCHRONOUS;
  1563. Flags = LocalParameters.Flags & Mask;
  1564. IoHandle->OpenFlags = (IoHandle->OpenFlags & ~Mask) | Flags;
  1565. Status = STATUS_SUCCESS;
  1566. //
  1567. // If the asynchronous flag changed, make adjustments.
  1568. //
  1569. Flags = LocalParameters.Flags;
  1570. if (((Flags ^ IoHandle->OpenFlags) & OPEN_FLAG_ASYNCHRONOUS) != 0) {
  1571. Asynchronous = FALSE;
  1572. if ((Flags & OPEN_FLAG_ASYNCHRONOUS) != 0) {
  1573. Asynchronous = TRUE;
  1574. }
  1575. Status = IoSetHandleAsynchronous(IoHandle,
  1576. FileControl->File,
  1577. Asynchronous);
  1578. }
  1579. break;
  1580. //
  1581. // Return the process ID that gets async IO signals.
  1582. //
  1583. case FileControlCommandGetSignalOwner:
  1584. LocalParameters.Owner = 0;
  1585. IoState = IoHandle->FileObject->IoState;
  1586. if (IoState->Async != NULL) {
  1587. LocalParameters.Owner = IoState->Async->Owner;
  1588. }
  1589. CopyOutSize = sizeof(PROCESS_ID);
  1590. Status = STATUS_SUCCESS;
  1591. break;
  1592. //
  1593. // Set the process ID that gets async IO signals. Also record the user
  1594. // identity and permissions to ensure that IO signals are not sent to
  1595. // processes this process would not ordinarily have been able to send
  1596. // signals to.
  1597. //
  1598. case FileControlCommandSetSignalOwner:
  1599. Status = MmCopyFromUserMode(&LocalParameters,
  1600. FileControl->Parameters,
  1601. sizeof(PROCESS_ID));
  1602. if (!KSUCCESS(Status)) {
  1603. goto SysFileControlEnd;
  1604. }
  1605. IoState = IoHandle->FileObject->IoState;
  1606. //
  1607. // Signaling process groups is currently not supported.
  1608. //
  1609. if (LocalParameters.Owner <= 0) {
  1610. Status = STATUS_NOT_SUPPORTED;
  1611. break;
  1612. }
  1613. AsyncState = IopGetAsyncState(IoState);
  1614. if (AsyncState == NULL) {
  1615. Status = STATUS_INSUFFICIENT_RESOURCES;
  1616. break;
  1617. }
  1618. Thread = KeGetCurrentThread();
  1619. KeAcquireQueuedLock(AsyncState->Lock);
  1620. AsyncState->Owner = LocalParameters.Owner;
  1621. AsyncState->SetterUserId = Thread->Identity.RealUserId;
  1622. AsyncState->SetterEffectiveUserId = Thread->Identity.EffectiveUserId;
  1623. AsyncState->SetterPermissions = Thread->Permissions.Effective;
  1624. KeReleaseQueuedLock(AsyncState->Lock);
  1625. Status = STATUS_SUCCESS;
  1626. break;
  1627. case FileControlCommandGetLock:
  1628. RtlZeroMemory(&(LocalParameters.FileLock), sizeof(FILE_LOCK));
  1629. Status = IopGetFileLock(IoHandle, &(LocalParameters.FileLock));
  1630. if (KSUCCESS(Status)) {
  1631. CopyOutSize = sizeof(FILE_LOCK);
  1632. }
  1633. break;
  1634. //
  1635. // Toggle the blocking local and fall through to the set lock command.
  1636. //
  1637. case FileControlCommandBlockingSetLock:
  1638. Blocking = TRUE;
  1639. case FileControlCommandSetLock:
  1640. if (FileControl->Parameters == NULL) {
  1641. Status = STATUS_INVALID_PARAMETER;
  1642. goto SysFileControlEnd;
  1643. }
  1644. Status = MmCopyFromUserMode(&LocalParameters,
  1645. FileControl->Parameters,
  1646. sizeof(FILE_LOCK));
  1647. if (!KSUCCESS(Status)) {
  1648. goto SysFileControlEnd;
  1649. }
  1650. Status = IopSetFileLock(IoHandle,
  1651. &(LocalParameters.FileLock),
  1652. Blocking);
  1653. break;
  1654. case FileControlCommandGetFileInformation:
  1655. RtlZeroMemory(&LocalParameters, sizeof(SET_FILE_INFORMATION));
  1656. Status = IoSetFileInformation(
  1657. FALSE,
  1658. IoHandle,
  1659. &(LocalParameters.SetFileInformation));
  1660. if (KSUCCESS(Status)) {
  1661. CopyOutSize = sizeof(SET_FILE_INFORMATION);
  1662. }
  1663. break;
  1664. case FileControlCommandSetFileInformation:
  1665. if (FileControl->Parameters == NULL) {
  1666. Status = STATUS_INVALID_PARAMETER;
  1667. goto SysFileControlEnd;
  1668. }
  1669. Status = MmCopyFromUserMode(&LocalParameters,
  1670. FileControl->Parameters,
  1671. sizeof(SET_FILE_INFORMATION));
  1672. if (!KSUCCESS(Status)) {
  1673. goto SysFileControlEnd;
  1674. }
  1675. Status = IoSetFileInformation(
  1676. FALSE,
  1677. IoHandle,
  1678. &(LocalParameters.SetFileInformation));
  1679. break;
  1680. //
  1681. // Attempt to set the directory flag on the given descriptor so that
  1682. // reads from the directory will succeed. This is used to support the
  1683. // fdopendir C library function.
  1684. //
  1685. case FileControlCommandSetDirectoryFlag:
  1686. Status = STATUS_NOT_A_DIRECTORY;
  1687. FileObject = IoHandle->FileObject;
  1688. if ((FileObject->Properties.Type == IoObjectRegularDirectory) ||
  1689. (FileObject->Properties.Type == IoObjectObjectDirectory)) {
  1690. IoHandle->OpenFlags |= OPEN_FLAG_DIRECTORY;
  1691. Status = STATUS_SUCCESS;
  1692. }
  1693. break;
  1694. case FileControlCommandCloseFrom:
  1695. Status = IoCloseProcessHandles(Process, FileControl->File);
  1696. break;
  1697. //
  1698. // Get the full path of path entry associated with the given I/O handle, if
  1699. // possible.
  1700. //
  1701. case FileControlCommandGetPath:
  1702. KeAcquireQueuedLock(Process->Paths.Lock);
  1703. if (Process->Paths.Root.PathEntry != NULL) {
  1704. IO_COPY_PATH_POINT(&RootPathPoint, &(Process->Paths.Root));
  1705. IO_PATH_POINT_ADD_REFERENCE(&RootPathPoint);
  1706. } else {
  1707. IO_COPY_PATH_POINT(&RootPathPoint, &IoPathPointRoot);
  1708. IO_PATH_POINT_ADD_REFERENCE(&RootPathPoint);
  1709. }
  1710. KeReleaseQueuedLock(Process->Paths.Lock);
  1711. if (FileControl->Parameters == NULL) {
  1712. Status = STATUS_INVALID_PARAMETER;
  1713. goto SysFileControlEnd;
  1714. }
  1715. Status = MmCopyFromUserMode(&LocalParameters,
  1716. FileControl->Parameters,
  1717. sizeof(FILE_PATH));
  1718. if (!KSUCCESS(Status)) {
  1719. goto SysFileControlEnd;
  1720. }
  1721. Status = IopGetUserFilePath(&(IoHandle->PathPoint),
  1722. &RootPathPoint,
  1723. LocalParameters.FilePath.Path,
  1724. &(LocalParameters.FilePath.PathSize));
  1725. IO_PATH_POINT_RELEASE_REFERENCE(&RootPathPoint);
  1726. if (KSUCCESS(Status)) {
  1727. CopyOutSize = sizeof(FILE_PATH);
  1728. }
  1729. break;
  1730. default:
  1731. Status = STATUS_INVALID_PARAMETER;
  1732. break;
  1733. }
  1734. SysFileControlEnd:
  1735. if (CopyOutSize != 0) {
  1736. Status = STATUS_INVALID_PARAMETER;
  1737. if (FileControl->Parameters != NULL) {
  1738. Status = MmCopyToUserMode(FileControl->Parameters,
  1739. &LocalParameters,
  1740. CopyOutSize);
  1741. }
  1742. }
  1743. FileControl->Status = Status;
  1744. if (IoHandle != NULL) {
  1745. IoIoHandleReleaseReference(IoHandle);
  1746. }
  1747. return;
  1748. }
  1749. VOID
  1750. IoSysGetSetFileInformation (
  1751. ULONG SystemCallNumber,
  1752. PVOID SystemCallParameter,
  1753. PTRAP_FRAME TrapFrame,
  1754. PULONG ResultSize
  1755. )
  1756. /*++
  1757. Routine Description:
  1758. This routine implements the get/set file information system call.
  1759. Arguments:
  1760. SystemCallNumber - Supplies the system call number that was requested.
  1761. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1762. the system call. This structure will be a stack-local copy of the
  1763. actual parameters passed from user-mode.
  1764. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1765. from user mode to kernel mode.
  1766. ResultSize - Supplies a pointer where the system call routine returns the
  1767. size of the parameter structure to be copied back to user mode. The
  1768. value returned here must be no larger than the original parameter
  1769. structure size. The default is the original size of the parameters.
  1770. Return Value:
  1771. None.
  1772. --*/
  1773. {
  1774. PIO_HANDLE Directory;
  1775. PIO_HANDLE IoHandle;
  1776. ULONG OpenFlags;
  1777. PSYSTEM_CALL_GET_SET_FILE_INFORMATION Parameters;
  1778. PSTR PathCopy;
  1779. PKPROCESS Process;
  1780. KSTATUS Status;
  1781. Directory = NULL;
  1782. IoHandle = NULL;
  1783. PathCopy = NULL;
  1784. Parameters = (PSYSTEM_CALL_GET_SET_FILE_INFORMATION)SystemCallParameter;
  1785. //
  1786. // Copy the path string out of user mode.
  1787. //
  1788. Status = MmCreateCopyOfUserModeString(Parameters->FilePath,
  1789. Parameters->FilePathSize,
  1790. IO_ALLOCATION_TAG,
  1791. &PathCopy);
  1792. if (!KSUCCESS(Status)) {
  1793. goto SysGetSetFileInformationEnd;
  1794. }
  1795. //
  1796. // Open up the file for getting or setting the information.
  1797. //
  1798. OpenFlags = 0;
  1799. if (Parameters->FollowLink == FALSE) {
  1800. OpenFlags |= OPEN_FLAG_SYMBOLIC_LINK;
  1801. }
  1802. if (Parameters->Directory != INVALID_HANDLE) {
  1803. Process = PsGetCurrentProcess();
  1804. Directory = ObGetHandleValue(Process->HandleTable,
  1805. Parameters->Directory,
  1806. NULL);
  1807. if (Directory == NULL) {
  1808. Status = STATUS_INVALID_HANDLE;
  1809. goto SysGetSetFileInformationEnd;
  1810. }
  1811. }
  1812. Status = IoOpen(FALSE,
  1813. Directory,
  1814. PathCopy,
  1815. Parameters->FilePathSize,
  1816. 0,
  1817. OpenFlags,
  1818. FILE_PERMISSION_NONE,
  1819. &IoHandle);
  1820. if (!KSUCCESS(Status)) {
  1821. goto SysGetSetFileInformationEnd;
  1822. }
  1823. Status = IoSetFileInformation(FALSE, IoHandle, &(Parameters->Request));
  1824. SysGetSetFileInformationEnd:
  1825. if (Directory != NULL) {
  1826. IoIoHandleReleaseReference(Directory);
  1827. }
  1828. if (IoHandle != NULL) {
  1829. IoClose(IoHandle);
  1830. }
  1831. if (PathCopy != NULL) {
  1832. MmFreePagedPool(PathCopy);
  1833. }
  1834. Parameters->Status = Status;
  1835. return;
  1836. }
  1837. VOID
  1838. IoSysSeek (
  1839. ULONG SystemCallNumber,
  1840. PVOID SystemCallParameter,
  1841. PTRAP_FRAME TrapFrame,
  1842. PULONG ResultSize
  1843. )
  1844. /*++
  1845. Routine Description:
  1846. This routine implements the file seek system call.
  1847. Arguments:
  1848. SystemCallNumber - Supplies the system call number that was requested.
  1849. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1850. the system call. This structure will be a stack-local copy of the
  1851. actual parameters passed from user-mode.
  1852. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1853. from user mode to kernel mode.
  1854. ResultSize - Supplies a pointer where the system call routine returns the
  1855. size of the parameter structure to be copied back to user mode. The
  1856. value returned here must be no larger than the original parameter
  1857. structure size. The default is the original size of the parameters.
  1858. Return Value:
  1859. None.
  1860. --*/
  1861. {
  1862. PIO_HANDLE IoHandle;
  1863. PKPROCESS Process;
  1864. PSYSTEM_CALL_SEEK Request;
  1865. KSTATUS Status;
  1866. ASSERT(SystemCallNumber == SystemCallSeek);
  1867. Request = (PSYSTEM_CALL_SEEK)SystemCallParameter;
  1868. Process = PsGetCurrentProcess();
  1869. IoHandle = ObGetHandleValue(Process->HandleTable, Request->Handle, NULL);
  1870. if (IoHandle == NULL) {
  1871. Status = STATUS_INVALID_HANDLE;
  1872. goto SysSeekEnd;
  1873. }
  1874. Status = IoSeek(IoHandle,
  1875. Request->Command,
  1876. Request->Offset,
  1877. &(Request->Offset));
  1878. if (!KSUCCESS(Status)) {
  1879. goto SysSeekEnd;
  1880. }
  1881. SysSeekEnd:
  1882. Request->Status = Status;
  1883. if (IoHandle != NULL) {
  1884. IoIoHandleReleaseReference(IoHandle);
  1885. }
  1886. return;
  1887. }
  1888. VOID
  1889. IoSysCreateSymbolicLink (
  1890. ULONG SystemCallNumber,
  1891. PVOID SystemCallParameter,
  1892. PTRAP_FRAME TrapFrame,
  1893. PULONG ResultSize
  1894. )
  1895. /*++
  1896. Routine Description:
  1897. This routine creates a symbolic link.
  1898. Arguments:
  1899. SystemCallNumber - Supplies the system call number that was requested.
  1900. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1901. the system call. This structure will be a stack-local copy of the
  1902. actual parameters passed from user-mode.
  1903. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1904. from user mode to kernel mode.
  1905. ResultSize - Supplies a pointer where the system call routine returns the
  1906. size of the parameter structure to be copied back to user mode. The
  1907. value returned here must be no larger than the original parameter
  1908. structure size. The default is the original size of the parameters.
  1909. Return Value:
  1910. None.
  1911. --*/
  1912. {
  1913. PIO_HANDLE Directory;
  1914. PSTR Link;
  1915. ULONG LinkSize;
  1916. PSTR LinkTarget;
  1917. ULONG LinkTargetSize;
  1918. PSYSTEM_CALL_CREATE_SYMBOLIC_LINK Parameters;
  1919. PKPROCESS Process;
  1920. KSTATUS Status;
  1921. ASSERT(SystemCallNumber == SystemCallCreateSymbolicLink);
  1922. Directory = NULL;
  1923. Parameters = (PSYSTEM_CALL_CREATE_SYMBOLIC_LINK)SystemCallParameter;
  1924. Link = NULL;
  1925. LinkTarget = NULL;
  1926. LinkSize = Parameters->PathSize;
  1927. LinkTargetSize = Parameters->LinkDestinationBufferSize;
  1928. Status = MmCreateCopyOfUserModeString(Parameters->Path,
  1929. LinkSize,
  1930. PATH_ALLOCATION_TAG,
  1931. &Link);
  1932. if (!KSUCCESS(Status)) {
  1933. goto SysCreateSymbolicLinkEnd;
  1934. }
  1935. Status = MmCreateCopyOfUserModeString(Parameters->LinkDestinationBuffer,
  1936. LinkTargetSize,
  1937. PATH_ALLOCATION_TAG,
  1938. &LinkTarget);
  1939. if (!KSUCCESS(Status)) {
  1940. goto SysCreateSymbolicLinkEnd;
  1941. }
  1942. if (Parameters->Directory != INVALID_HANDLE) {
  1943. Process = PsGetCurrentProcess();
  1944. Directory = ObGetHandleValue(Process->HandleTable,
  1945. Parameters->Directory,
  1946. NULL);
  1947. if (Directory == NULL) {
  1948. Status = STATUS_INVALID_HANDLE;
  1949. goto SysCreateSymbolicLinkEnd;
  1950. }
  1951. }
  1952. Status = IoCreateSymbolicLink(FALSE,
  1953. Directory,
  1954. Link,
  1955. LinkSize,
  1956. LinkTarget,
  1957. LinkTargetSize);
  1958. SysCreateSymbolicLinkEnd:
  1959. if (Directory != NULL) {
  1960. IoIoHandleReleaseReference(Directory);
  1961. }
  1962. if (Link != NULL) {
  1963. MmFreePagedPool(Link);
  1964. }
  1965. if (LinkTarget != NULL) {
  1966. MmFreePagedPool(LinkTarget);
  1967. }
  1968. Parameters->Status = Status;
  1969. return;
  1970. }
  1971. VOID
  1972. IoSysReadSymbolicLink (
  1973. ULONG SystemCallNumber,
  1974. PVOID SystemCallParameter,
  1975. PTRAP_FRAME TrapFrame,
  1976. PULONG ResultSize
  1977. )
  1978. /*++
  1979. Routine Description:
  1980. This routine reads and returns the destination of a symbolic link.
  1981. Arguments:
  1982. SystemCallNumber - Supplies the system call number that was requested.
  1983. SystemCallParameter - Supplies a pointer to the parameters supplied with
  1984. the system call. This structure will be a stack-local copy of the
  1985. actual parameters passed from user-mode.
  1986. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  1987. from user mode to kernel mode.
  1988. ResultSize - Supplies a pointer where the system call routine returns the
  1989. size of the parameter structure to be copied back to user mode. The
  1990. value returned here must be no larger than the original parameter
  1991. structure size. The default is the original size of the parameters.
  1992. Return Value:
  1993. None.
  1994. --*/
  1995. {
  1996. PIO_HANDLE Directory;
  1997. PIO_HANDLE Handle;
  1998. PSTR Link;
  1999. ULONG LinkSize;
  2000. PSTR LinkTarget;
  2001. ULONG LinkTargetSize;
  2002. PSYSTEM_CALL_READ_SYMBOLIC_LINK Parameters;
  2003. PKPROCESS Process;
  2004. KSTATUS Status;
  2005. ASSERT(SystemCallNumber == SystemCallReadSymbolicLink);
  2006. Directory = NULL;
  2007. Handle = NULL;
  2008. Link = NULL;
  2009. LinkTarget = NULL;
  2010. LinkTargetSize = 0;
  2011. Parameters = (PSYSTEM_CALL_READ_SYMBOLIC_LINK)SystemCallParameter;
  2012. LinkSize = Parameters->PathSize;
  2013. Status = MmCreateCopyOfUserModeString(Parameters->Path,
  2014. LinkSize,
  2015. PATH_ALLOCATION_TAG,
  2016. &Link);
  2017. if (!KSUCCESS(Status)) {
  2018. goto SysReadSymbolicLinkEnd;
  2019. }
  2020. if (Parameters->Directory != INVALID_HANDLE) {
  2021. Process = PsGetCurrentProcess();
  2022. Directory = ObGetHandleValue(Process->HandleTable,
  2023. Parameters->Directory,
  2024. NULL);
  2025. if (Directory == NULL) {
  2026. Status = STATUS_INVALID_HANDLE;
  2027. goto SysReadSymbolicLinkEnd;
  2028. }
  2029. }
  2030. Status = IoOpen(FALSE,
  2031. Directory,
  2032. Link,
  2033. LinkSize,
  2034. IO_ACCESS_READ,
  2035. OPEN_FLAG_SYMBOLIC_LINK,
  2036. FILE_PERMISSION_NONE,
  2037. &Handle);
  2038. if (!KSUCCESS(Status)) {
  2039. goto SysReadSymbolicLinkEnd;
  2040. }
  2041. Status = IoReadSymbolicLink(Handle,
  2042. PATH_ALLOCATION_TAG,
  2043. &LinkTarget,
  2044. &LinkTargetSize);
  2045. if (!KSUCCESS(Status)) {
  2046. goto SysReadSymbolicLinkEnd;
  2047. }
  2048. if (LinkTargetSize != 0) {
  2049. LinkTargetSize -= 1;
  2050. }
  2051. if (Parameters->LinkDestinationBufferSize < LinkTargetSize) {
  2052. Status = STATUS_BUFFER_TOO_SMALL;
  2053. goto SysReadSymbolicLinkEnd;
  2054. }
  2055. Status = MmCopyToUserMode(Parameters->LinkDestinationBuffer,
  2056. LinkTarget,
  2057. LinkTargetSize);
  2058. if (!KSUCCESS(Status)) {
  2059. goto SysReadSymbolicLinkEnd;
  2060. }
  2061. SysReadSymbolicLinkEnd:
  2062. if (Directory != NULL) {
  2063. IoIoHandleReleaseReference(Directory);
  2064. }
  2065. if (Handle != NULL) {
  2066. IoClose(Handle);
  2067. }
  2068. if (Link != NULL) {
  2069. MmFreePagedPool(Link);
  2070. }
  2071. if (LinkTarget != NULL) {
  2072. MmFreePagedPool(LinkTarget);
  2073. }
  2074. Parameters->LinkDestinationSize = LinkTargetSize;
  2075. Parameters->Status = Status;
  2076. return;
  2077. }
  2078. VOID
  2079. IoSysCreateHardLink (
  2080. ULONG SystemCallNumber,
  2081. PVOID SystemCallParameter,
  2082. PTRAP_FRAME TrapFrame,
  2083. PULONG ResultSize
  2084. )
  2085. /*++
  2086. Routine Description:
  2087. This routine creates a hard link.
  2088. Arguments:
  2089. SystemCallNumber - Supplies the system call number that was requested.
  2090. SystemCallParameter - Supplies a pointer to the parameters supplied with
  2091. the system call. This structure will be a stack-local copy of the
  2092. actual parameters passed from user-mode.
  2093. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  2094. from user mode to kernel mode.
  2095. ResultSize - Supplies a pointer where the system call routine returns the
  2096. size of the parameter structure to be copied back to user mode. The
  2097. value returned here must be no larger than the original parameter
  2098. structure size. The default is the original size of the parameters.
  2099. Return Value:
  2100. None.
  2101. --*/
  2102. {
  2103. PSYSTEM_CALL_CREATE_HARD_LINK Parameters;
  2104. ASSERT(SystemCallNumber == SystemCallCreateHardLink);
  2105. Parameters = (PSYSTEM_CALL_CREATE_HARD_LINK)SystemCallParameter;
  2106. //
  2107. // TODO: Add support for creating a hard link.
  2108. //
  2109. Parameters->Status = STATUS_NOT_IMPLEMENTED;
  2110. return;
  2111. }
  2112. VOID
  2113. IoSysDelete (
  2114. ULONG SystemCallNumber,
  2115. PVOID SystemCallParameter,
  2116. PTRAP_FRAME TrapFrame,
  2117. PULONG ResultSize
  2118. )
  2119. /*++
  2120. Routine Description:
  2121. This routine deletes an entry from a directory.
  2122. Arguments:
  2123. SystemCallNumber - Supplies the system call number that was requested.
  2124. SystemCallParameter - Supplies a pointer to the parameters supplied with
  2125. the system call. This structure will be a stack-local copy of the
  2126. actual parameters passed from user-mode.
  2127. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  2128. from user mode to kernel mode.
  2129. ResultSize - Supplies a pointer where the system call routine returns the
  2130. size of the parameter structure to be copied back to user mode. The
  2131. value returned here must be no larger than the original parameter
  2132. structure size. The default is the original size of the parameters.
  2133. Return Value:
  2134. None.
  2135. --*/
  2136. {
  2137. ULONG DeleteFlags;
  2138. PIO_HANDLE Directory;
  2139. PSYSTEM_CALL_DELETE Parameters;
  2140. PSTR PathCopy;
  2141. PKPROCESS Process;
  2142. KSTATUS Status;
  2143. ASSERT(SystemCallNumber == SystemCallDelete);
  2144. Directory = NULL;
  2145. Parameters = (PSYSTEM_CALL_DELETE)SystemCallParameter;
  2146. PathCopy = NULL;
  2147. Status = MmCreateCopyOfUserModeString(Parameters->Path,
  2148. Parameters->PathSize,
  2149. IO_ALLOCATION_TAG,
  2150. &PathCopy);
  2151. if (!KSUCCESS(Status)) {
  2152. goto SysDeleteEnd;
  2153. }
  2154. if (Parameters->Directory != INVALID_HANDLE) {
  2155. Process = PsGetCurrentProcess();
  2156. Directory = ObGetHandleValue(Process->HandleTable,
  2157. Parameters->Directory,
  2158. NULL);
  2159. if (Directory == NULL) {
  2160. Status = STATUS_INVALID_HANDLE;
  2161. goto SysDeleteEnd;
  2162. }
  2163. }
  2164. DeleteFlags = 0;
  2165. if ((Parameters->Flags & SYS_DELETE_FLAG_SHARED_MEMORY) != 0) {
  2166. DeleteFlags |= DELETE_FLAG_SHARED_MEMORY;
  2167. }
  2168. if ((Parameters->Flags & SYS_DELETE_FLAG_DIRECTORY) != 0) {
  2169. DeleteFlags |= DELETE_FLAG_DIRECTORY;
  2170. }
  2171. Status = IoDelete(FALSE,
  2172. Directory,
  2173. PathCopy,
  2174. Parameters->PathSize,
  2175. DeleteFlags);
  2176. if (!KSUCCESS(Status)) {
  2177. goto SysDeleteEnd;
  2178. }
  2179. SysDeleteEnd:
  2180. if (Directory != NULL) {
  2181. IoIoHandleReleaseReference(Directory);
  2182. }
  2183. if (PathCopy != NULL) {
  2184. MmFreePagedPool(PathCopy);
  2185. }
  2186. Parameters->Status = Status;
  2187. return;
  2188. }
  2189. VOID
  2190. IoSysRename (
  2191. ULONG SystemCallNumber,
  2192. PVOID SystemCallParameter,
  2193. PTRAP_FRAME TrapFrame,
  2194. PULONG ResultSize
  2195. )
  2196. /*++
  2197. Routine Description:
  2198. This routine renames a file or directory.
  2199. Arguments:
  2200. SystemCallNumber - Supplies the system call number that was requested.
  2201. SystemCallParameter - Supplies a pointer to the parameters supplied with
  2202. the system call. This structure will be a stack-local copy of the
  2203. actual parameters passed from user-mode.
  2204. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  2205. from user mode to kernel mode.
  2206. ResultSize - Supplies a pointer where the system call routine returns the
  2207. size of the parameter structure to be copied back to user mode. The
  2208. value returned here must be no larger than the original parameter
  2209. structure size. The default is the original size of the parameters.
  2210. Return Value:
  2211. None.
  2212. --*/
  2213. {
  2214. PSTR DestinationCopy;
  2215. PIO_HANDLE DestinationDirectory;
  2216. PSYSTEM_CALL_RENAME Parameters;
  2217. PKPROCESS Process;
  2218. PSTR SourceCopy;
  2219. PIO_HANDLE SourceDirectory;
  2220. KSTATUS Status;
  2221. ASSERT(SystemCallNumber == SystemCallRename);
  2222. DestinationCopy = NULL;
  2223. DestinationDirectory = NULL;
  2224. Parameters = (PSYSTEM_CALL_RENAME)SystemCallParameter;
  2225. Process = PsGetCurrentProcess();
  2226. SourceCopy = NULL;
  2227. SourceDirectory = NULL;
  2228. if (Parameters->SourceDirectory != INVALID_HANDLE) {
  2229. SourceDirectory = ObGetHandleValue(Process->HandleTable,
  2230. Parameters->SourceDirectory,
  2231. NULL);
  2232. if (SourceDirectory == NULL) {
  2233. Status = STATUS_INVALID_HANDLE;
  2234. goto SysRenameEnd;
  2235. }
  2236. }
  2237. if (Parameters->DestinationDirectory != INVALID_HANDLE) {
  2238. DestinationDirectory = ObGetHandleValue(
  2239. Process->HandleTable,
  2240. Parameters->DestinationDirectory,
  2241. NULL);
  2242. if (DestinationDirectory == NULL) {
  2243. Status = STATUS_INVALID_HANDLE;
  2244. goto SysRenameEnd;
  2245. }
  2246. }
  2247. Status = MmCreateCopyOfUserModeString(Parameters->SourcePath,
  2248. Parameters->SourcePathSize,
  2249. IO_ALLOCATION_TAG,
  2250. &SourceCopy);
  2251. if (!KSUCCESS(Status)) {
  2252. goto SysRenameEnd;
  2253. }
  2254. Status = MmCreateCopyOfUserModeString(Parameters->DestinationPath,
  2255. Parameters->DestinationPathSize,
  2256. IO_ALLOCATION_TAG,
  2257. &DestinationCopy);
  2258. if (!KSUCCESS(Status)) {
  2259. goto SysRenameEnd;
  2260. }
  2261. Status = IoRename(FALSE,
  2262. SourceDirectory,
  2263. SourceCopy,
  2264. Parameters->SourcePathSize,
  2265. DestinationDirectory,
  2266. DestinationCopy,
  2267. Parameters->DestinationPathSize);
  2268. if (!KSUCCESS(Status)) {
  2269. goto SysRenameEnd;
  2270. }
  2271. SysRenameEnd:
  2272. if (SourceCopy != NULL) {
  2273. MmFreePagedPool(SourceCopy);
  2274. }
  2275. if (DestinationCopy != NULL) {
  2276. MmFreePagedPool(DestinationCopy);
  2277. }
  2278. if (SourceDirectory != NULL) {
  2279. IoIoHandleReleaseReference(SourceDirectory);
  2280. }
  2281. if (DestinationDirectory != NULL) {
  2282. IoIoHandleReleaseReference(DestinationDirectory);
  2283. }
  2284. Parameters->Status = Status;
  2285. return;
  2286. }
  2287. VOID
  2288. IoSysUserControl (
  2289. ULONG SystemCallNumber,
  2290. PVOID SystemCallParameter,
  2291. PTRAP_FRAME TrapFrame,
  2292. PULONG ResultSize
  2293. )
  2294. /*++
  2295. Routine Description:
  2296. This routine implements the user control system call.
  2297. Arguments:
  2298. SystemCallNumber - Supplies the system call number that was requested.
  2299. SystemCallParameter - Supplies a pointer to the parameters supplied with
  2300. the system call. This structure will be a stack-local copy of the
  2301. actual parameters passed from user-mode.
  2302. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  2303. from user mode to kernel mode.
  2304. ResultSize - Supplies a pointer where the system call routine returns the
  2305. size of the parameter structure to be copied back to user mode. The
  2306. value returned here must be no larger than the original parameter
  2307. structure size. The default is the original size of the parameters.
  2308. Return Value:
  2309. None.
  2310. --*/
  2311. {
  2312. PIO_HANDLE IoHandle;
  2313. PKPROCESS Process;
  2314. PSYSTEM_CALL_USER_CONTROL Request;
  2315. KSTATUS Status;
  2316. ASSERT(SystemCallNumber == SystemCallUserControl);
  2317. Request = (PSYSTEM_CALL_USER_CONTROL)SystemCallParameter;
  2318. Process = PsGetCurrentProcess();
  2319. IoHandle = ObGetHandleValue(Process->HandleTable, Request->Handle, NULL);
  2320. if (IoHandle == NULL) {
  2321. Status = STATUS_INVALID_HANDLE;
  2322. goto SysUserControlEnd;
  2323. }
  2324. Status = IopHandleCommonUserControl(IoHandle,
  2325. Request->Handle,
  2326. Request->RequestCode,
  2327. FALSE,
  2328. Request->Context,
  2329. Request->ContextSize);
  2330. if (Status == STATUS_NOT_SUPPORTED) {
  2331. Status = IoUserControl(IoHandle,
  2332. Request->RequestCode,
  2333. FALSE,
  2334. Request->Context,
  2335. Request->ContextSize);
  2336. }
  2337. if (!KSUCCESS(Status)) {
  2338. goto SysUserControlEnd;
  2339. }
  2340. SysUserControlEnd:
  2341. Request->Status = Status;
  2342. if (IoHandle != NULL) {
  2343. IoIoHandleReleaseReference(IoHandle);
  2344. }
  2345. return;
  2346. }
  2347. VOID
  2348. IoSysMountOrUnmount (
  2349. ULONG SystemCallNumber,
  2350. PVOID SystemCallParameter,
  2351. PTRAP_FRAME TrapFrame,
  2352. PULONG ResultSize
  2353. )
  2354. /*++
  2355. Routine Description:
  2356. This routine mounts or unmounts a file, directory, volume, pipe, socket, or
  2357. device.
  2358. Arguments:
  2359. SystemCallNumber - Supplies the system call number that was requested.
  2360. SystemCallParameter - Supplies a pointer to the parameters supplied with
  2361. the system call. This structure will be a stack-local copy of the
  2362. actual parameters passed from user-mode.
  2363. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  2364. from user mode to kernel mode.
  2365. ResultSize - Supplies a pointer where the system call routine returns the
  2366. size of the parameter structure to be copied back to user mode. The
  2367. value returned here must be no larger than the original parameter
  2368. structure size. The default is the original size of the parameters.
  2369. Return Value:
  2370. None.
  2371. --*/
  2372. {
  2373. ULONG AccessFlags;
  2374. ULONG MountFlags;
  2375. PSTR MountPointCopy;
  2376. PSYSTEM_CALL_MOUNT_UNMOUNT Parameters;
  2377. KSTATUS Status;
  2378. PSTR TargetCopy;
  2379. ASSERT(SystemCallNumber == SystemCallMountOrUnmount);
  2380. AccessFlags = 0;
  2381. MountFlags = 0;
  2382. MountPointCopy = NULL;
  2383. Parameters = (PSYSTEM_CALL_MOUNT_UNMOUNT)SystemCallParameter;
  2384. TargetCopy = NULL;
  2385. //
  2386. // A mount point path is always required. Create a copy.
  2387. //
  2388. Status = MmCreateCopyOfUserModeString(Parameters->MountPointPath,
  2389. Parameters->MountPointPathSize,
  2390. IO_ALLOCATION_TAG,
  2391. &MountPointCopy);
  2392. if (!KSUCCESS(Status)) {
  2393. goto SysMountUnmountEnd;
  2394. }
  2395. //
  2396. // The target path is not required during unmount. Do not copy it.
  2397. //
  2398. if ((Parameters->Flags & SYS_MOUNT_FLAG_UNMOUNT) == 0) {
  2399. Status = MmCreateCopyOfUserModeString(Parameters->TargetPath,
  2400. Parameters->TargetPathSize,
  2401. IO_ALLOCATION_TAG,
  2402. &TargetCopy);
  2403. if (!KSUCCESS(Status)) {
  2404. goto SysMountUnmountEnd;
  2405. }
  2406. }
  2407. //
  2408. // Convert any additional flags.
  2409. //
  2410. if ((Parameters->Flags & SYS_MOUNT_FLAG_READ) != 0) {
  2411. AccessFlags |= IO_ACCESS_READ;
  2412. }
  2413. if ((Parameters->Flags & SYS_MOUNT_FLAG_WRITE) != 0) {
  2414. AccessFlags |= IO_ACCESS_WRITE;
  2415. }
  2416. if ((Parameters->Flags & SYS_MOUNT_FLAG_BIND) != 0) {
  2417. MountFlags |= MOUNT_FLAG_BIND;
  2418. }
  2419. if ((Parameters->Flags & SYS_MOUNT_FLAG_RECURSIVE) != 0) {
  2420. MountFlags |= MOUNT_FLAG_RECURSIVE;
  2421. }
  2422. //
  2423. // A detach call is always recursive.
  2424. //
  2425. if ((Parameters->Flags & SYS_MOUNT_FLAG_DETACH) != 0) {
  2426. MountFlags |= MOUNT_FLAG_DETACH | MOUNT_FLAG_RECURSIVE;
  2427. }
  2428. //
  2429. // Call the appropriate mount or unmount routine.
  2430. //
  2431. if ((Parameters->Flags & SYS_MOUNT_FLAG_UNMOUNT) == 0) {
  2432. Status = IoMount(FALSE,
  2433. MountPointCopy,
  2434. Parameters->MountPointPathSize,
  2435. TargetCopy,
  2436. Parameters->TargetPathSize,
  2437. MountFlags,
  2438. AccessFlags);
  2439. } else {
  2440. Status = IoUnmount(FALSE,
  2441. MountPointCopy,
  2442. Parameters->MountPointPathSize,
  2443. MountFlags,
  2444. AccessFlags);
  2445. }
  2446. if (!KSUCCESS(Status)) {
  2447. goto SysMountUnmountEnd;
  2448. }
  2449. SysMountUnmountEnd:
  2450. if (MountPointCopy != NULL) {
  2451. MmFreePagedPool(MountPointCopy);
  2452. }
  2453. if (TargetCopy != NULL) {
  2454. MmFreePagedPool(TargetCopy);
  2455. }
  2456. Parameters->Status = Status;
  2457. return;
  2458. }
  2459. VOID
  2460. IoSysGetEffectiveAccess (
  2461. ULONG SystemCallNumber,
  2462. PVOID SystemCallParameter,
  2463. PTRAP_FRAME TrapFrame,
  2464. PULONG ResultSize
  2465. )
  2466. /*++
  2467. Routine Description:
  2468. This routine implements the system call for getting the current user's
  2469. access permission to a given path.
  2470. Arguments:
  2471. SystemCallNumber - Supplies the system call number that was requested.
  2472. SystemCallParameter - Supplies a pointer to the parameters supplied with
  2473. the system call. This structure will be a stack-local copy of the
  2474. actual parameters passed from user-mode.
  2475. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  2476. from user mode to kernel mode.
  2477. ResultSize - Supplies a pointer where the system call routine returns the
  2478. size of the parameter structure to be copied back to user mode. The
  2479. value returned here must be no larger than the original parameter
  2480. structure size. The default is the original size of the parameters.
  2481. Return Value:
  2482. None.
  2483. --*/
  2484. {
  2485. PIO_HANDLE Directory;
  2486. FILE_PROPERTIES Information;
  2487. PIO_HANDLE IoHandle;
  2488. PSYSTEM_CALL_GET_EFFECTIVE_ACCESS Parameters;
  2489. PSTR Path;
  2490. PKPROCESS Process;
  2491. KSTATUS Status;
  2492. ASSERT(SystemCallNumber == SystemCallGetEffectiveAccess);
  2493. Directory = NULL;
  2494. IoHandle = NULL;
  2495. Parameters = (PSYSTEM_CALL_GET_EFFECTIVE_ACCESS)SystemCallParameter;
  2496. Parameters->EffectiveAccess = 0;
  2497. Path = NULL;
  2498. Status = MmCreateCopyOfUserModeString(Parameters->FilePath,
  2499. Parameters->FilePathSize,
  2500. FI_ALLOCATION_TAG,
  2501. &Path);
  2502. if (!KSUCCESS(Status)) {
  2503. goto SysGetEffectiveAccessEnd;
  2504. }
  2505. if (Parameters->Directory != INVALID_HANDLE) {
  2506. Process = PsGetCurrentProcess();
  2507. Directory = ObGetHandleValue(Process->HandleTable,
  2508. Parameters->Directory,
  2509. NULL);
  2510. if (Directory == NULL) {
  2511. Status = STATUS_INVALID_HANDLE;
  2512. goto SysGetEffectiveAccessEnd;
  2513. }
  2514. }
  2515. Status = IoOpen(FALSE,
  2516. Directory,
  2517. Path,
  2518. Parameters->FilePathSize,
  2519. 0,
  2520. 0,
  2521. FILE_PERMISSION_NONE,
  2522. &IoHandle);
  2523. if (!KSUCCESS(Status)) {
  2524. goto SysGetEffectiveAccessEnd;
  2525. }
  2526. Status = IoGetFileInformation(IoHandle, &Information);
  2527. if (!KSUCCESS(Status)) {
  2528. goto SysGetEffectiveAccessEnd;
  2529. }
  2530. if ((Parameters->DesiredFlags & EFFECTIVE_ACCESS_READ) != 0) {
  2531. Status = IopCheckPermissions(FALSE,
  2532. &(IoHandle->PathPoint),
  2533. IO_ACCESS_READ);
  2534. if (KSUCCESS(Status)) {
  2535. Parameters->EffectiveAccess |= EFFECTIVE_ACCESS_READ;
  2536. }
  2537. }
  2538. if ((Parameters->DesiredFlags & EFFECTIVE_ACCESS_WRITE) != 0) {
  2539. Status = IopCheckPermissions(FALSE,
  2540. &(IoHandle->PathPoint),
  2541. IO_ACCESS_WRITE);
  2542. if (KSUCCESS(Status)) {
  2543. Parameters->EffectiveAccess |= EFFECTIVE_ACCESS_WRITE;
  2544. }
  2545. }
  2546. if ((Parameters->DesiredFlags & EFFECTIVE_ACCESS_EXECUTE) != 0) {
  2547. Status = IopCheckPermissions(FALSE,
  2548. &(IoHandle->PathPoint),
  2549. IO_ACCESS_EXECUTE);
  2550. if (KSUCCESS(Status)) {
  2551. Parameters->EffectiveAccess |= EFFECTIVE_ACCESS_EXECUTE;
  2552. }
  2553. }
  2554. Status = STATUS_SUCCESS;
  2555. SysGetEffectiveAccessEnd:
  2556. if (Directory != NULL) {
  2557. IoIoHandleReleaseReference(Directory);
  2558. }
  2559. if (IoHandle != NULL) {
  2560. IoClose(IoHandle);
  2561. }
  2562. Parameters->Status = Status;
  2563. if (Path != NULL) {
  2564. MmFreePagedPool(Path);
  2565. }
  2566. return;
  2567. }
  2568. VOID
  2569. IoSysCreateTerminal (
  2570. ULONG SystemCallNumber,
  2571. PVOID SystemCallParameter,
  2572. PTRAP_FRAME TrapFrame,
  2573. PULONG ResultSize
  2574. )
  2575. /*++
  2576. Routine Description:
  2577. This routine implements the system call for creating and opening a new
  2578. terminal.
  2579. Arguments:
  2580. SystemCallNumber - Supplies the system call number that was requested.
  2581. SystemCallParameter - Supplies a pointer to the parameters supplied with
  2582. the system call. This structure will be a stack-local copy of the
  2583. actual parameters passed from user-mode.
  2584. TrapFrame - Supplies a pointer to the trap frame generated by this jump
  2585. from user mode to kernel mode.
  2586. ResultSize - Supplies a pointer where the system call routine returns the
  2587. size of the parameter structure to be copied back to user mode. The
  2588. value returned here must be no larger than the original parameter
  2589. structure size. The default is the original size of the parameters.
  2590. Return Value:
  2591. None.
  2592. --*/
  2593. {
  2594. ULONG Access;
  2595. PKPROCESS CurrentProcess;
  2596. ULONG HandleFlags;
  2597. PIO_HANDLE MasterDirectory;
  2598. PIO_HANDLE MasterHandle;
  2599. PSTR MasterPath;
  2600. ULONG OpenFlags;
  2601. PSYSTEM_CALL_CREATE_TERMINAL Parameters;
  2602. PIO_HANDLE SlaveDirectory;
  2603. PSTR SlavePath;
  2604. KSTATUS Status;
  2605. CurrentProcess = PsGetCurrentProcess();
  2606. ASSERT(SystemCallNumber == SystemCallCreateTerminal);
  2607. ASSERT(CurrentProcess != PsGetKernelProcess());
  2608. MasterDirectory = NULL;
  2609. MasterHandle = NULL;
  2610. Parameters = (PSYSTEM_CALL_CREATE_TERMINAL)SystemCallParameter;
  2611. Parameters->MasterHandle = INVALID_HANDLE;
  2612. MasterPath = NULL;
  2613. SlaveDirectory = NULL;
  2614. SlavePath = NULL;
  2615. if (Parameters->MasterPathLength != 0) {
  2616. Status = MmCreateCopyOfUserModeString(Parameters->MasterPath,
  2617. Parameters->MasterPathLength,
  2618. FI_ALLOCATION_TAG,
  2619. &MasterPath);
  2620. if (!KSUCCESS(Status)) {
  2621. goto SysCreateTerminalEnd;
  2622. }
  2623. }
  2624. if (Parameters->SlavePathLength != 0) {
  2625. Status = MmCreateCopyOfUserModeString(Parameters->SlavePath,
  2626. Parameters->SlavePathLength,
  2627. FI_ALLOCATION_TAG,
  2628. &SlavePath);
  2629. if (!KSUCCESS(Status)) {
  2630. goto SysCreateTerminalEnd;
  2631. }
  2632. }
  2633. if (Parameters->MasterDirectory != INVALID_HANDLE) {
  2634. MasterDirectory = ObGetHandleValue(CurrentProcess->HandleTable,
  2635. Parameters->MasterDirectory,
  2636. NULL);
  2637. if (MasterDirectory == NULL) {
  2638. Status = STATUS_INVALID_HANDLE;
  2639. goto SysCreateTerminalEnd;
  2640. }
  2641. }
  2642. if (Parameters->SlaveDirectory != INVALID_HANDLE) {
  2643. SlaveDirectory = ObGetHandleValue(CurrentProcess->HandleTable,
  2644. Parameters->SlaveDirectory,
  2645. NULL);
  2646. if (SlaveDirectory == NULL) {
  2647. Status = STATUS_INVALID_HANDLE;
  2648. goto SysCreateTerminalEnd;
  2649. }
  2650. }
  2651. ASSERT_SYS_OPEN_FLAGS_EQUIVALENT();
  2652. Access = (Parameters->MasterOpenFlags >> SYS_OPEN_ACCESS_SHIFT) &
  2653. (IO_ACCESS_READ | IO_ACCESS_WRITE);
  2654. OpenFlags = Parameters->MasterOpenFlags & OPEN_FLAG_NO_CONTROLLING_TERMINAL;
  2655. Status = IoCreateTerminal(FALSE,
  2656. MasterDirectory,
  2657. SlaveDirectory,
  2658. MasterPath,
  2659. Parameters->MasterPathLength,
  2660. SlavePath,
  2661. Parameters->SlavePathLength,
  2662. Access,
  2663. OpenFlags,
  2664. Parameters->MasterCreatePermissions,
  2665. Parameters->SlaveCreatePermissions,
  2666. &MasterHandle);
  2667. if (!KSUCCESS(Status)) {
  2668. goto SysCreateTerminalEnd;
  2669. }
  2670. HandleFlags = 0;
  2671. if ((Parameters->MasterOpenFlags & SYS_OPEN_FLAG_CLOSE_ON_EXECUTE) != 0) {
  2672. HandleFlags |= FILE_DESCRIPTOR_CLOSE_ON_EXECUTE;
  2673. }
  2674. Status = ObCreateHandle(CurrentProcess->HandleTable,
  2675. MasterHandle,
  2676. HandleFlags,
  2677. &(Parameters->MasterHandle));
  2678. if (!KSUCCESS(Status)) {
  2679. IoClose(MasterHandle);
  2680. goto SysCreateTerminalEnd;
  2681. }
  2682. SysCreateTerminalEnd:
  2683. if (MasterDirectory != NULL) {
  2684. IoIoHandleReleaseReference(MasterDirectory);
  2685. }
  2686. if (SlaveDirectory != NULL) {
  2687. IoIoHandleReleaseReference(SlaveDirectory);
  2688. }
  2689. if (MasterPath != NULL) {
  2690. MmFreePagedPool(MasterPath);
  2691. }
  2692. if (SlavePath != NULL) {
  2693. MmFreePagedPool(SlavePath);
  2694. }
  2695. Parameters->Status = Status;
  2696. return;
  2697. }
  2698. KSTATUS
  2699. IoCloseProcessHandles (
  2700. PKPROCESS Process,
  2701. HANDLE MinimumHandle
  2702. )
  2703. /*++
  2704. Routine Description:
  2705. This routine closes all remaining open handles in the given process.
  2706. Arguments:
  2707. Process - Supplies a pointer to the process being terminated.
  2708. MinimumHandle - Supplies the lowest handle to clean up to, inclusive.
  2709. Handles below this one will not be closed.
  2710. Return Value:
  2711. Status code.
  2712. --*/
  2713. {
  2714. HANDLE Handle;
  2715. HANDLE PreviousHandle;
  2716. KSTATUS Status;
  2717. KSTATUS TotalStatus;
  2718. //
  2719. // Loop getting the highest numbered handle and closing it until there are
  2720. // no more open handles.
  2721. //
  2722. PreviousHandle = INVALID_HANDLE;
  2723. TotalStatus = STATUS_SUCCESS;
  2724. while (TRUE) {
  2725. Handle = ObGetHighestHandle(Process->HandleTable);
  2726. if (Handle == INVALID_HANDLE) {
  2727. break;
  2728. }
  2729. if (Handle < MinimumHandle) {
  2730. break;
  2731. }
  2732. ASSERT(Handle != PreviousHandle);
  2733. Status = IopSysClose(Process, Handle);
  2734. if (!KSUCCESS(Status)) {
  2735. if (KSUCCESS(TotalStatus)) {
  2736. TotalStatus = Status;
  2737. }
  2738. }
  2739. PreviousHandle = Handle;
  2740. }
  2741. return TotalStatus;
  2742. }
  2743. KSTATUS
  2744. IoCopyProcessHandles (
  2745. PKPROCESS SourceProcess,
  2746. PKPROCESS DestinationProcess
  2747. )
  2748. /*++
  2749. Routine Description:
  2750. This routine copies all handles in the source process to the destination
  2751. process. This is used during process forking.
  2752. Arguments:
  2753. SourceProcess - Supplies a pointer to the process being copied.
  2754. DestinationProcess - Supplies a pointer to the fledgling destination
  2755. process. This process' handle hables must be empty.
  2756. Return Value:
  2757. Status code.
  2758. --*/
  2759. {
  2760. COPY_HANDLES_ITERATION_CONTEXT Context;
  2761. PHANDLE_TABLE DestinationTable;
  2762. PHANDLE_TABLE SourceTable;
  2763. DestinationTable = DestinationProcess->HandleTable;
  2764. SourceTable = SourceProcess->HandleTable;
  2765. Context.DestinationTable = DestinationTable;
  2766. Context.SourceTable = SourceTable;
  2767. Context.Status = STATUS_SUCCESS;
  2768. //
  2769. // Assert that the destination process handle table is empty.
  2770. //
  2771. ASSERT(ObGetHighestHandle(DestinationTable) == INVALID_HANDLE);
  2772. ObHandleTableIterate(SourceTable, IopCopyHandleIterateRoutine, &Context);
  2773. //
  2774. // If the operation was not successful, clean up any partial progress.
  2775. //
  2776. if (!KSUCCESS(Context.Status)) {
  2777. IoCloseProcessHandles(DestinationProcess, 0);
  2778. }
  2779. return Context.Status;
  2780. }
  2781. KSTATUS
  2782. IoCloseHandlesOnExecute (
  2783. PKPROCESS Process
  2784. )
  2785. /*++
  2786. Routine Description:
  2787. This routine closes any handles marked for "close on execute".
  2788. Arguments:
  2789. Process - Supplies a pointer to the process undergoing the execution
  2790. transformation.
  2791. Return Value:
  2792. Status code.
  2793. --*/
  2794. {
  2795. CLOSE_EXECUTE_HANDLES_CONTEXT Context;
  2796. ULONG HandleIndex;
  2797. KSTATUS Status;
  2798. //
  2799. // Get the array of handles to be closed. This can't be done in the
  2800. // iterate routine because the iterate routine needs the tree to stay
  2801. // static while it's cruising around.
  2802. //
  2803. Context.HandleArray = NULL;
  2804. Context.HandleArraySize = 0;
  2805. Context.HandleArrayCapacity = 0;
  2806. Context.Status = STATUS_SUCCESS;
  2807. ObHandleTableIterate(Process->HandleTable,
  2808. IopCloseExecuteHandleIterateRoutine,
  2809. &Context);
  2810. Status = Context.Status;
  2811. if (!KSUCCESS(Status)) {
  2812. goto CloseHandlesOnExecuteEnd;
  2813. }
  2814. for (HandleIndex = 0;
  2815. HandleIndex < Context.HandleArraySize;
  2816. HandleIndex += 1) {
  2817. IopSysClose(Process, Context.HandleArray[HandleIndex]);
  2818. }
  2819. Status = STATUS_SUCCESS;
  2820. CloseHandlesOnExecuteEnd:
  2821. if (Context.HandleArray != NULL) {
  2822. MmFreePagedPool(Context.HandleArray);
  2823. }
  2824. return Status;
  2825. }
  2826. //
  2827. // --------------------------------------------------------- Internal Functions
  2828. //
  2829. KSTATUS
  2830. IopSysClose (
  2831. PKPROCESS Process,
  2832. HANDLE Handle
  2833. )
  2834. /*++
  2835. Routine Description:
  2836. This routine closes a handle opened in user mode.
  2837. Arguments:
  2838. Process - Supplies a pointer to the process the file handle was opened
  2839. under.
  2840. Handle - Supplies the handle returned during the open system call.
  2841. Return Value:
  2842. Status code.
  2843. --*/
  2844. {
  2845. PVOID HandleValue;
  2846. KSTATUS Status;
  2847. HandleValue = ObGetHandleValue(Process->HandleTable, Handle, NULL);
  2848. if (HandleValue == NULL) {
  2849. return STATUS_INVALID_HANDLE;
  2850. }
  2851. IopRemoveFileLocks(HandleValue, Process);
  2852. Status = IoClose(HandleValue);
  2853. if (!KSUCCESS(Status)) {
  2854. goto SysCloseEnd;
  2855. }
  2856. ObDestroyHandle(Process->HandleTable, Handle);
  2857. SysCloseEnd:
  2858. //
  2859. // Release the handle reference that was added by the get handle value
  2860. // routine.
  2861. //
  2862. IoIoHandleReleaseReference(HandleValue);
  2863. return Status;
  2864. }
  2865. VOID
  2866. IopCopyHandleIterateRoutine (
  2867. PHANDLE_TABLE HandleTable,
  2868. HANDLE Descriptor,
  2869. ULONG Flags,
  2870. PVOID HandleValue,
  2871. PVOID Context
  2872. )
  2873. /*++
  2874. Routine Description:
  2875. This routine is called on each handle in the handle table for which it was
  2876. invoked. It will copy the given handle into the destination table (passed
  2877. via context).
  2878. Arguments:
  2879. HandleTable - Supplies a pointer to the handle table being iterated through.
  2880. Descriptor - Supplies the handle descriptor for the current handle.
  2881. Flags - Supplies the flags associated with this handle.
  2882. HandleValue - Supplies the handle value for the current handle.
  2883. Context - Supplies an opaque pointer of context that was provided when the
  2884. iteration was requested. In this case, a pointer to the copy handles
  2885. iteration context.
  2886. Return Value:
  2887. None.
  2888. --*/
  2889. {
  2890. PCOPY_HANDLES_ITERATION_CONTEXT IterationContext;
  2891. HANDLE NewHandle;
  2892. KSTATUS Status;
  2893. IterationContext = (PCOPY_HANDLES_ITERATION_CONTEXT)Context;
  2894. //
  2895. // If the operation has already failed (on a previous handle), stop trying.
  2896. //
  2897. if (!KSUCCESS(IterationContext->Status)) {
  2898. return;
  2899. }
  2900. NewHandle = Descriptor;
  2901. Status = ObCreateHandle(IterationContext->DestinationTable,
  2902. HandleValue,
  2903. Flags,
  2904. &NewHandle);
  2905. if (!KSUCCESS(Status)) {
  2906. IterationContext->Status = Status;
  2907. return;
  2908. }
  2909. ASSERT(NewHandle == Descriptor);
  2910. IoIoHandleAddReference(HandleValue);
  2911. return;
  2912. }
  2913. VOID
  2914. IopCloseExecuteHandleIterateRoutine (
  2915. PHANDLE_TABLE HandleTable,
  2916. HANDLE Descriptor,
  2917. ULONG Flags,
  2918. PVOID HandleValue,
  2919. PVOID Context
  2920. )
  2921. /*++
  2922. Routine Description:
  2923. This routine is called on each handle in the handle table for which it was
  2924. invoked. It will add the handle to an array stored internally if the
  2925. handle is marked to be close on execute.
  2926. Arguments:
  2927. HandleTable - Supplies a pointer to the handle table being iterated through.
  2928. Descriptor - Supplies the handle descriptor for the current handle.
  2929. Flags - Supplies the flags for this descriptor.
  2930. HandleValue - Supplies the handle value for the current handle.
  2931. Context - Supplies an opaque pointer of context that was provided when the
  2932. iteration was requested. In this case, a pointer to the close execute
  2933. handles iteration context.
  2934. Return Value:
  2935. None.
  2936. --*/
  2937. {
  2938. PCLOSE_EXECUTE_HANDLES_CONTEXT IterationContext;
  2939. PHANDLE NewArray;
  2940. ULONG NewCapacity;
  2941. UINTN OldSize;
  2942. IterationContext = (PCLOSE_EXECUTE_HANDLES_CONTEXT)Context;
  2943. //
  2944. // If the operation has already failed (on a previous handle), stop trying.
  2945. //
  2946. if (!KSUCCESS(IterationContext->Status)) {
  2947. return;
  2948. }
  2949. //
  2950. // If the handle doesn't need to be added to the array, exit early.
  2951. //
  2952. if ((Flags & FILE_DESCRIPTOR_CLOSE_ON_EXECUTE) == 0) {
  2953. return;
  2954. }
  2955. //
  2956. // Expand the array if needed.
  2957. //
  2958. if (IterationContext->HandleArraySize ==
  2959. IterationContext->HandleArrayCapacity) {
  2960. NewCapacity = IterationContext->HandleArrayCapacity * 2;
  2961. if (NewCapacity == 0) {
  2962. NewCapacity = CLOSE_EXECUTE_HANDLE_INITIAL_ARRAY_SIZE;
  2963. }
  2964. NewArray = MmAllocatePagedPool(NewCapacity * sizeof(PHANDLE),
  2965. IO_ALLOCATION_TAG);
  2966. if (NewArray == NULL) {
  2967. IterationContext->Status = STATUS_INSUFFICIENT_RESOURCES;
  2968. return;
  2969. }
  2970. if (IterationContext->HandleArray != NULL) {
  2971. OldSize = IterationContext->HandleArrayCapacity * sizeof(PHANDLE);
  2972. RtlCopyMemory(NewArray, IterationContext->HandleArray, OldSize);
  2973. MmFreePagedPool(IterationContext->HandleArray);
  2974. }
  2975. IterationContext->HandleArray = NewArray;
  2976. IterationContext->HandleArrayCapacity = NewCapacity;
  2977. ASSERT(IterationContext->HandleArrayCapacity >
  2978. IterationContext->HandleArraySize);
  2979. }
  2980. IterationContext->HandleArray[IterationContext->HandleArraySize] =
  2981. Descriptor;
  2982. IterationContext->HandleArraySize += 1;
  2983. return;
  2984. }
  2985. VOID
  2986. IopCheckForDirectoryHandlesIterationRoutine (
  2987. PHANDLE_TABLE HandleTable,
  2988. HANDLE Descriptor,
  2989. ULONG Flags,
  2990. PVOID HandleValue,
  2991. PVOID Context
  2992. )
  2993. /*++
  2994. Routine Description:
  2995. This routine is called on each handle in the handle table checking for an
  2996. open handle to a directory.
  2997. Arguments:
  2998. HandleTable - Supplies a pointer to the handle table being iterated through.
  2999. Descriptor - Supplies the handle descriptor for the current handle.
  3000. Flags - Supplies the flags associated with this handle.
  3001. HandleValue - Supplies the handle value for the current handle.
  3002. Context - Supplies an opaque pointer of context that was provided when the
  3003. iteration was requested.
  3004. Return Value:
  3005. None.
  3006. --*/
  3007. {
  3008. PFILE_OBJECT FileObject;
  3009. PIO_HANDLE IoHandle;
  3010. PSYSTEM_CALL_CHANGE_DIRECTORY Parameters;
  3011. Parameters = Context;
  3012. IoHandle = HandleValue;
  3013. FileObject = IoHandle->FileObject;
  3014. if ((Descriptor != Parameters->Handle) &&
  3015. ((FileObject->Properties.Type == IoObjectRegularDirectory) ||
  3016. (FileObject->Properties.Type == IoObjectObjectDirectory))) {
  3017. Parameters->Status = STATUS_TOO_MANY_HANDLES;
  3018. }
  3019. return;
  3020. }
  3021. KSTATUS
  3022. IopGetUserFilePath (
  3023. PPATH_POINT Entry,
  3024. PPATH_POINT Root,
  3025. PSTR UserBuffer,
  3026. PUINTN UserBufferSize
  3027. )
  3028. /*++
  3029. Routine Description:
  3030. This routine copies the full path of the given path entry (as seen from
  3031. the given root) into the given user mode buffer.
  3032. Arguments:
  3033. Entry - Supplies a pointer to the path point to get the full path of.
  3034. Root - Supplies a pointer to the user's root.
  3035. UserBuffer - Supplies a pointer to the user mode buffer where the full path
  3036. should be returned.
  3037. UserBufferSize - Supplies a pointer that on success contains the size of
  3038. the user mode buffer. Returns the actual size of the file path, even if
  3039. the supplied buffer was too small.
  3040. Return Value:
  3041. STATUS_SUCCESS on success.
  3042. STATUS_PATH_NOT_FOUND if the path entry has no path.
  3043. STATUS_ACCESS_VIOLATION if the buffer was invalid.
  3044. STATUS_BUFFER_TOO_SMALL if the buffer was too small.
  3045. --*/
  3046. {
  3047. PSTR Path;
  3048. UINTN PathSize;
  3049. KSTATUS Status;
  3050. //
  3051. // Create the path.
  3052. //
  3053. Path = NULL;
  3054. PathSize = 0;
  3055. Status = IopGetPathFromRoot(Entry,
  3056. Root,
  3057. &Path,
  3058. &PathSize);
  3059. if (!KSUCCESS(Status)) {
  3060. goto GetUserFilePathEnd;
  3061. }
  3062. //
  3063. // If not enough space was supplied, then return the required size.
  3064. //
  3065. if (*UserBufferSize < PathSize) {
  3066. Status = STATUS_BUFFER_TOO_SMALL;
  3067. goto GetUserFilePathEnd;
  3068. }
  3069. //
  3070. // Copy the path to the supplied buffer.
  3071. //
  3072. if (UserBuffer != NULL) {
  3073. Status = MmCopyToUserMode(UserBuffer, Path, PathSize);
  3074. if (!KSUCCESS(Status)) {
  3075. goto GetUserFilePathEnd;
  3076. }
  3077. }
  3078. GetUserFilePathEnd:
  3079. if (Path != NULL) {
  3080. MmFreePagedPool(Path);
  3081. }
  3082. *UserBufferSize = PathSize;
  3083. return Status;
  3084. }
  3085. KSTATUS
  3086. IopHandleCommonUserControl (
  3087. PIO_HANDLE Handle,
  3088. HANDLE Descriptor,
  3089. ULONG MinorCode,
  3090. BOOL FromKernelMode,
  3091. PVOID ContextBuffer,
  3092. UINTN ContextBufferSize
  3093. )
  3094. /*++
  3095. Routine Description:
  3096. This routine performs user control operations common to many types of
  3097. devices.
  3098. Arguments:
  3099. Handle - Supplies the open file handle.
  3100. Descriptor - Supplies the descriptor corresponding to the handle.
  3101. MinorCode - Supplies the minor code of the request.
  3102. FromKernelMode - Supplies a boolean indicating whether or not this request
  3103. (and the buffer associated with it) originates from user mode (FALSE)
  3104. or kernel mode (TRUE).
  3105. ContextBuffer - Supplies a pointer to the context buffer allocated by the
  3106. caller for the request.
  3107. ContextBufferSize - Supplies the size of the supplied context buffer.
  3108. Return Value:
  3109. Status code.
  3110. --*/
  3111. {
  3112. INT Argument;
  3113. BOOL Asynchronous;
  3114. KSTATUS Status;
  3115. switch (MinorCode) {
  3116. case TerminalControlAsync:
  3117. if (ContextBufferSize < sizeof(INT)) {
  3118. Status = STATUS_DATA_LENGTH_MISMATCH;
  3119. break;
  3120. }
  3121. if (FromKernelMode != FALSE) {
  3122. Argument = *((PULONG)ContextBuffer);
  3123. } else {
  3124. Argument = 0;
  3125. Status = MmCopyFromUserMode(&Argument, ContextBuffer, sizeof(INT));
  3126. if (!KSUCCESS(Status)) {
  3127. break;
  3128. }
  3129. }
  3130. Asynchronous = FALSE;
  3131. if (Argument != 0) {
  3132. Asynchronous = TRUE;
  3133. }
  3134. Status = IoSetHandleAsynchronous(Handle, Descriptor, Asynchronous);
  3135. break;
  3136. default:
  3137. Status = STATUS_NOT_SUPPORTED;
  3138. break;
  3139. }
  3140. return Status;
  3141. }