1 /*
2 * COPYRIGHT: See COPYRIGHT.TXT
3 * PROJECT: Ext2 File System Driver for WinNT/2K/XP
4 * FILE: devctl.c
5 * PROGRAMMER: Matt Wu <mattwu@163.com>
6 * HOMEPAGE: http://www.ext2fsd.com
7 * UPDATE HISTORY:
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include "ext2fs.h"
13
14 /* GLOBALS ***************************************************************/
15
16 extern PEXT2_GLOBAL Ext2Global;
17
18 /* DEFINITIONS *************************************************************/
19
20 #ifdef __REACTOS__
21 NTSTATUS NTAPI
22 #else
23 NTSTATUS
24 #endif
25 Ext2DeviceControlCompletion (
26 IN PDEVICE_OBJECT DeviceObject,
27 IN PIRP Irp,
28 IN PVOID Context);
29
30
31 #ifdef ALLOC_PRAGMA
32 #pragma alloc_text(PAGE, Ext2DeviceControl)
33 #pragma alloc_text(PAGE, Ext2DeviceControlNormal)
34 #pragma alloc_text(PAGE, Ext2ProcessVolumeProperty)
35 #pragma alloc_text(PAGE, Ext2ProcessUserProperty)
36 #pragma alloc_text(PAGE, Ext2ProcessGlobalProperty)
37 #pragma alloc_text(PAGE, Ex2ProcessUserPerfStat)
38 #pragma alloc_text(PAGE, Ex2ProcessMountPoint)
39 #if EXT2_UNLOAD
40 #pragma alloc_text(PAGE, Ext2PrepareToUnload)
41 #endif
42 #endif
43
44
45 #ifdef __REACTOS__
46 NTSTATUS NTAPI
47 #else
48 NTSTATUS
49 #endif
Ext2DeviceControlCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)50 Ext2DeviceControlCompletion (
51 IN PDEVICE_OBJECT DeviceObject,
52 IN PIRP Irp,
53 IN PVOID Context
54 )
55 {
56 if (Irp->PendingReturned) {
57 IoMarkIrpPending(Irp);
58 }
59
60 return STATUS_SUCCESS;
61 }
62
63
64 NTSTATUS
Ext2DeviceControlNormal(IN PEXT2_IRP_CONTEXT IrpContext)65 Ext2DeviceControlNormal (IN PEXT2_IRP_CONTEXT IrpContext)
66 {
67 PDEVICE_OBJECT DeviceObject;
68 BOOLEAN CompleteRequest = TRUE;
69 NTSTATUS Status = STATUS_UNSUCCESSFUL;
70
71 PEXT2_VCB Vcb;
72
73 PIRP Irp;
74 PIO_STACK_LOCATION IrpSp;
75 PIO_STACK_LOCATION NextIrpSp;
76
77 PDEVICE_OBJECT TargetDeviceObject;
78
79 _SEH2_TRY {
80
81 ASSERT(IrpContext != NULL);
82
83 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
84 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
85
86 CompleteRequest = TRUE;
87
88 DeviceObject = IrpContext->DeviceObject;
89
90 if (IsExt2FsDevice(DeviceObject)) {
91 Status = STATUS_INVALID_DEVICE_REQUEST;
92 _SEH2_LEAVE;
93 }
94
95 Irp = IrpContext->Irp;
96 IrpSp = IoGetCurrentIrpStackLocation(Irp);
97
98 Vcb = (PEXT2_VCB) IrpSp->FileObject->FsContext;
99
100 if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) &&
101 (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) {
102 Status = STATUS_INVALID_PARAMETER;
103 _SEH2_LEAVE;
104 }
105
106 TargetDeviceObject = Vcb->TargetDeviceObject;
107
108 //
109 // Pass on the IOCTL to the driver below
110 //
111
112 CompleteRequest = FALSE;
113
114 NextIrpSp = IoGetNextIrpStackLocation( Irp );
115 *NextIrpSp = *IrpSp;
116
117 IoSetCompletionRoutine(
118 Irp,
119 Ext2DeviceControlCompletion,
120 NULL,
121 FALSE,
122 TRUE,
123 TRUE );
124
125 Status = IoCallDriver(TargetDeviceObject, Irp);
126
127 } _SEH2_FINALLY {
128
129 if (!IrpContext->ExceptionInProgress) {
130 if (IrpContext) {
131 if (!CompleteRequest) {
132 IrpContext->Irp = NULL;
133 }
134
135 Ext2CompleteIrpContext(IrpContext, Status);
136 }
137 }
138 } _SEH2_END;
139
140 return Status;
141 }
142
143
144 #if EXT2_UNLOAD
145
146 NTSTATUS
Ext2PrepareToUnload(IN PEXT2_IRP_CONTEXT IrpContext)147 Ext2PrepareToUnload (IN PEXT2_IRP_CONTEXT IrpContext)
148 {
149 PDEVICE_OBJECT DeviceObject;
150 NTSTATUS Status = STATUS_UNSUCCESSFUL;
151 BOOLEAN GlobalDataResourceAcquired = FALSE;
152
153 _SEH2_TRY {
154
155 ASSERT(IrpContext != NULL);
156
157 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
158 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
159
160 DeviceObject = IrpContext->DeviceObject;
161
162 if (IsExt2FsDevice(DeviceObject)) {
163 Status = STATUS_INVALID_DEVICE_REQUEST;
164 _SEH2_LEAVE;
165 }
166
167 ExAcquireResourceExclusiveLite(
168 &Ext2Global->Resource,
169 TRUE );
170
171 GlobalDataResourceAcquired = TRUE;
172
173 if (FlagOn(Ext2Global->Flags, EXT2_UNLOAD_PENDING)) {
174 DEBUG(DL_ERR, ( "Ext2PrepareUnload: Already ready to unload.\n"));
175
176 Status = STATUS_ACCESS_DENIED;
177
178 _SEH2_LEAVE;
179 }
180
181 {
182 PEXT2_VCB Vcb;
183 PLIST_ENTRY ListEntry;
184
185 ListEntry = Ext2Global->VcbList.Flink;
186
187 while (ListEntry != &(Ext2Global->VcbList)) {
188
189 Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);
190 ListEntry = ListEntry->Flink;
191
192 if (Vcb && (!Vcb->ReferenceCount) &&
193 IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
194 Ext2RemoveVcb(Vcb);
195 Ext2ClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);
196
197 Ext2DestroyVcb(Vcb);
198 }
199 }
200 }
201
202 if (!IsListEmpty(&(Ext2Global->VcbList))) {
203
204 DEBUG(DL_ERR, ( "Ext2PrepareUnload: Mounted volumes exists.\n"));
205
206 Status = STATUS_ACCESS_DENIED;
207
208 _SEH2_LEAVE;
209 }
210
211 IoUnregisterFileSystem(Ext2Global->DiskdevObject);
212 IoUnregisterFileSystem(Ext2Global->CdromdevObject);
213 Ext2Global->DriverObject->DriverUnload = DriverUnload;
214 SetLongFlag(Ext2Global->Flags ,EXT2_UNLOAD_PENDING);
215 Status = STATUS_SUCCESS;
216
217 DEBUG(DL_INF, ( "Ext2PrepareToUnload: Driver is ready to unload.\n"));
218
219 } _SEH2_FINALLY {
220
221 if (GlobalDataResourceAcquired) {
222 ExReleaseResourceLite(&Ext2Global->Resource);
223 }
224
225 if (!IrpContext->ExceptionInProgress) {
226 Ext2CompleteIrpContext(IrpContext, Status);
227 }
228 } _SEH2_END;
229
230 return Status;
231 }
232
233 #endif
234
235 extern CHAR gVersion[];
236 extern CHAR gTime[];
237 extern CHAR gDate[];
238
239 NTSTATUS
Ext2ProcessGlobalProperty(IN PDEVICE_OBJECT DeviceObject,IN PEXT2_VOLUME_PROPERTY3 Property3,IN ULONG Length)240 Ext2ProcessGlobalProperty(
241 IN PDEVICE_OBJECT DeviceObject,
242 IN PEXT2_VOLUME_PROPERTY3 Property3,
243 IN ULONG Length
244 )
245 {
246 PEXT2_VOLUME_PROPERTY3 Property2 = (PVOID)Property3;
247 PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3;
248 struct nls_table * PageTable = NULL;
249
250 NTSTATUS Status = STATUS_SUCCESS;
251 BOOLEAN GlobalDataResourceAcquired = FALSE;
252
253 _SEH2_TRY {
254
255 if (Length < 8 || !IsFlagOn(Property->Flags, EXT2_FLAG_VP_SET_GLOBAL)) {
256 Status = STATUS_INVALID_PARAMETER;
257 _SEH2_LEAVE;
258 }
259
260 /* query Ext2Fsd's version and built date/time*/
261 if (Property->Command == APP_CMD_QUERY_VERSION) {
262 PEXT2_VOLUME_PROPERTY_VERSION PVPV =
263 (PEXT2_VOLUME_PROPERTY_VERSION) Property;
264
265 if (Length < sizeof(EXT2_VOLUME_PROPERTY_VERSION)) {
266 Status = STATUS_INVALID_PARAMETER;
267 _SEH2_LEAVE;
268 }
269
270 RtlZeroMemory(&PVPV->Date[0], 0x20);
271 RtlZeroMemory(&PVPV->Time[0], 0x20);
272 RtlZeroMemory(&PVPV->Version[0],0x1C);
273 strncpy(&PVPV->Version[0], gVersion, 0x1B);
274 strncpy(&PVPV->Date[0], gDate, 0x1F);
275 strncpy(&PVPV->Time[0], gTime, 0x1F);
276 _SEH2_LEAVE;
277 }
278
279 /* must be property query/set commands */
280 if (Property->Command == APP_CMD_SET_PROPERTY) {
281 if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
282 Status = STATUS_INVALID_PARAMETER;
283 _SEH2_LEAVE;
284 }
285 } else if (Property->Command == APP_CMD_SET_PROPERTY2) {
286 if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) {
287 Status = STATUS_INVALID_PARAMETER;
288 _SEH2_LEAVE;
289 }
290 } else if (Property->Command == APP_CMD_SET_PROPERTY3) {
291 if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) {
292 Status = STATUS_INVALID_PARAMETER;
293 _SEH2_LEAVE;
294 }
295 } else {
296 Status = STATUS_INVALID_PARAMETER;
297 _SEH2_LEAVE;
298 }
299
300 ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE);
301 GlobalDataResourceAcquired = TRUE;
302
303
304 switch (Property->Command) {
305
306 case APP_CMD_SET_PROPERTY3:
307
308 if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) {
309 if (Property3->AutoMount)
310 SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
311 else
312 ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
313 }
314
315 case APP_CMD_SET_PROPERTY2:
316
317 RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN);
318 if ((Ext2Global->bHidingPrefix = Property2->bHidingPrefix)) {
319 RtlCopyMemory( Ext2Global->sHidingPrefix,
320 Property2->sHidingPrefix,
321 HIDINGPAT_LEN - 1);
322 }
323 RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN);
324 if ((Ext2Global->bHidingSuffix = Property2->bHidingSuffix)) {
325 RtlCopyMemory( Ext2Global->sHidingSuffix,
326 Property2->sHidingSuffix,
327 HIDINGPAT_LEN - 1);
328 }
329
330 case APP_CMD_SET_PROPERTY:
331
332 if (Property->bReadonly) {
333 ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
334 ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
335 } else {
336 SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
337 if (Property->bExt3Writable) {
338 SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
339 } else {
340 ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
341 }
342 }
343
344 PageTable = load_nls(Property->Codepage);
345 if (PageTable) {
346 memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
347 Ext2Global->Codepage.PageTable = PageTable;
348 }
349
350 break;
351
352 default:
353 break;
354 }
355
356 } _SEH2_FINALLY {
357
358 if (GlobalDataResourceAcquired) {
359 ExReleaseResourceLite(&Ext2Global->Resource);
360 }
361 } _SEH2_END;
362
363 return Status;
364 }
365
366
367 NTSTATUS
Ext2ProcessVolumeProperty(IN PEXT2_VCB Vcb,IN PEXT2_VOLUME_PROPERTY3 Property3,IN ULONG Length)368 Ext2ProcessVolumeProperty(
369 IN PEXT2_VCB Vcb,
370 IN PEXT2_VOLUME_PROPERTY3 Property3,
371 IN ULONG Length
372 )
373 {
374 struct nls_table * PageTable = NULL;
375 PEXT2_VOLUME_PROPERTY2 Property2 = (PVOID)Property3;
376 PEXT2_VOLUME_PROPERTY Property = (PVOID)Property3;
377 NTSTATUS Status = STATUS_SUCCESS;
378 BOOLEAN VcbResourceAcquired = FALSE;
379
380 _SEH2_TRY {
381
382 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
383 VcbResourceAcquired = TRUE;
384
385 if (Property->Command == APP_CMD_SET_PROPERTY ||
386 Property->Command == APP_CMD_QUERY_PROPERTY) {
387 if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
388 Status = STATUS_INVALID_PARAMETER;
389 _SEH2_LEAVE;
390 }
391 } else if (Property->Command == APP_CMD_SET_PROPERTY2 ||
392 Property->Command == APP_CMD_QUERY_PROPERTY2) {
393 if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) {
394 Status = STATUS_INVALID_PARAMETER;
395 _SEH2_LEAVE;
396 }
397 } else if (Property->Command == APP_CMD_SET_PROPERTY3 ||
398 Property->Command == APP_CMD_QUERY_PROPERTY3) {
399 if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) {
400 Status = STATUS_INVALID_PARAMETER;
401 _SEH2_LEAVE;
402 }
403 }
404
405 switch (Property->Command) {
406
407 case APP_CMD_SET_PROPERTY3:
408
409 if (Property3->Flags2 & EXT2_VPROP3_AUTOMOUNT) {
410 if (Property3->AutoMount)
411 SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
412 else
413 ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
414 }
415 if (Property3->Flags2 & EXT2_VPROP3_USERIDS) {
416 SetFlag(Vcb->Flags, VCB_USER_IDS);
417 Vcb->uid = Property3->uid;
418 Vcb->gid = Property3->gid;
419 if (Property3->EIDS) {
420 Vcb->euid = Property3->euid;
421 Vcb->egid = Property3->egid;
422 SetFlag(Vcb->Flags, VCB_USER_EIDS);
423 } else {
424 Vcb->euid = Vcb->egid = 0;
425 ClearFlag(Vcb->Flags, VCB_USER_EIDS);
426 }
427 } else {
428 ClearFlag(Vcb->Flags, VCB_USER_IDS);
429 ClearFlag(Vcb->Flags, VCB_USER_EIDS);
430 Vcb->uid = Vcb->gid = 0;
431 Vcb->euid = Vcb->egid = 0;
432 }
433
434 case APP_CMD_SET_PROPERTY2:
435
436 RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN);
437 #ifdef __REACTOS__
438 if (Vcb->bHidingPrefix == Property2->bHidingPrefix) {
439 #else
440 if (Vcb->bHidingPrefix = Property2->bHidingPrefix) {
441 #endif
442 RtlCopyMemory( Vcb->sHidingPrefix,
443 Property2->sHidingPrefix,
444 HIDINGPAT_LEN - 1);
445 }
446
447 RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN);
448 #ifdef __REACTOS__
449 if (Vcb->bHidingSuffix == Property2->bHidingSuffix) {
450 #else
451 if (Vcb->bHidingSuffix = Property2->bHidingSuffix) {
452 #endif
453 RtlCopyMemory( Vcb->sHidingSuffix,
454 Property2->sHidingSuffix,
455 HIDINGPAT_LEN - 1);
456 }
457 Vcb->DrvLetter = Property2->DrvLetter;
458
459 case APP_CMD_SET_PROPERTY:
460
461 if (Property->bReadonly) {
462 if (IsFlagOn(Vcb->Flags, VCB_INITIALIZED)) {
463 Ext2FlushFiles(NULL, Vcb, FALSE);
464 Ext2FlushVolume(NULL, Vcb, FALSE);
465 }
466 SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
467
468 } else {
469
470 if (Property->bExt3Writable) {
471 SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING);
472 }
473
474 if (!Vcb->IsExt3fs) {
475 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
476 } else if (!Property->bExt3Writable) {
477 SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
478 } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) {
479 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
480 Ext2RecoverJournal(NULL, Vcb);
481 if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) {
482 SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
483 } else {
484 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
485 }
486 } else {
487 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
488 }
489 }
490
491 PageTable = load_nls(Property->Codepage);
492 memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
493 Vcb->Codepage.PageTable = PageTable;
494 if (Vcb->Codepage.PageTable) {
495 Ext2InitializeLabel(Vcb, Vcb->SuperBlock);
496 }
497
498 break;
499
500 case APP_CMD_QUERY_PROPERTY3:
501
502 if (IsFlagOn(Ext2Global->Flags, EXT2_AUTO_MOUNT)) {
503 SetFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT);
504 Property3->AutoMount = TRUE;
505 } else {
506 ClearFlag(Property3->Flags2, EXT2_VPROP3_AUTOMOUNT);
507 Property3->AutoMount = FALSE;
508 }
509
510 if (IsFlagOn(Vcb->Flags, VCB_USER_IDS)) {
511 SetFlag(Property3->Flags2, EXT2_VPROP3_USERIDS);
512 Property3->uid = Vcb->uid;
513 Property3->gid = Vcb->gid;
514 if (IsFlagOn(Vcb->Flags, VCB_USER_EIDS)) {
515 Property3->EIDS = TRUE;
516 Property3->euid = Vcb->euid;
517 Property3->egid = Vcb->egid;
518 } else {
519 Property3->EIDS = FALSE;
520 }
521 } else {
522 ClearFlag(Property3->Flags2, EXT2_VPROP3_USERIDS);
523 }
524
525 case APP_CMD_QUERY_PROPERTY2:
526
527 RtlCopyMemory(Property2->UUID, Vcb->SuperBlock->s_uuid, 16);
528 Property2->DrvLetter = Vcb->DrvLetter;
529
530 #ifdef __REACTOS__
531 if (Property2->bHidingPrefix == Vcb->bHidingPrefix) {
532 #else
533 if (Property2->bHidingPrefix = Vcb->bHidingPrefix) {
534 #endif
535 RtlCopyMemory( Property2->sHidingPrefix,
536 Vcb->sHidingPrefix,
537 HIDINGPAT_LEN);
538 } else {
539 RtlZeroMemory( Property2->sHidingPrefix,
540 HIDINGPAT_LEN);
541 }
542
543 #ifdef __REACTOS__
544 if (Property2->bHidingSuffix == Vcb->bHidingSuffix) {
545 #else
546 if (Property2->bHidingSuffix = Vcb->bHidingSuffix) {
547 #endif
548 RtlCopyMemory( Property2->sHidingSuffix,
549 Vcb->sHidingSuffix,
550 HIDINGPAT_LEN);
551 } else {
552 RtlZeroMemory( Property2->sHidingSuffix,
553 HIDINGPAT_LEN);
554 }
555
556 case APP_CMD_QUERY_PROPERTY:
557
558 Property->bExt2 = TRUE;
559 Property->bExt3 = Vcb->IsExt3fs;
560 Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY);
561 if (!Property->bReadonly && Vcb->IsExt3fs) {
562 Property->bExt3Writable = TRUE;
563 } else {
564 Property->bExt3Writable = FALSE;
565 }
566
567 RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN);
568 if (Vcb->Codepage.PageTable) {
569 strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN);
570 } else {
571 strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN);
572 }
573 break;
574
575 default:
576 Status = STATUS_INVALID_PARAMETER;
577 break;
578 }
579
580 } _SEH2_FINALLY {
581
582 if (VcbResourceAcquired) {
583 ExReleaseResourceLite(&Vcb->MainResource);
584 }
585 } _SEH2_END;
586
587 return Status;
588 }
589
590 NTSTATUS
591 Ext2ProcessUserProperty(
592 IN PEXT2_IRP_CONTEXT IrpContext,
593 IN PEXT2_VOLUME_PROPERTY3 Property,
594 IN ULONG Length
595 )
596 {
597 NTSTATUS Status = STATUS_SUCCESS;
598 PEXT2_VCB Vcb = NULL;
599 PDEVICE_OBJECT DeviceObject = NULL;
600
601 _SEH2_TRY {
602
603 ASSERT(IrpContext != NULL);
604 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
605 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
606
607 if (Property->Magic != EXT2_VOLUME_PROPERTY_MAGIC) {
608 Status = STATUS_INVALID_PARAMETER;
609 _SEH2_LEAVE;
610 }
611
612 DeviceObject = IrpContext->DeviceObject;
613 if (IsExt2FsDevice(DeviceObject)) {
614 Status = Ext2ProcessGlobalProperty(DeviceObject, Property, Length);
615 } else {
616 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
617 if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) &&
618 (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) {
619 Status = STATUS_INVALID_PARAMETER;
620 _SEH2_LEAVE;
621 }
622 Status = Ext2ProcessVolumeProperty(Vcb, Property, Length);
623 }
624
625 if (NT_SUCCESS(Status)) {
626 IrpContext->Irp->IoStatus.Information = Length;
627 }
628
629 } _SEH2_FINALLY {
630
631 if (!IrpContext->ExceptionInProgress) {
632 Ext2CompleteIrpContext(IrpContext, Status);
633 }
634 } _SEH2_END;
635
636 return Status;
637 }
638
639 NTSTATUS
640 Ex2ProcessUserPerfStat(
641 IN PEXT2_IRP_CONTEXT IrpContext,
642 IN PEXT2_QUERY_PERFSTAT QueryPerf,
643 IN ULONG Length
644 )
645 {
646
647 #ifndef __REACTOS__
648 PEXT2_VCB Vcb = NULL;
649 #endif
650 PDEVICE_OBJECT DeviceObject = NULL;
651
652 BOOLEAN GlobalDataResourceAcquired = FALSE;
653 NTSTATUS Status = STATUS_SUCCESS;
654
655 _SEH2_TRY {
656
657 ASSERT(IrpContext != NULL);
658 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
659 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
660
661 DeviceObject = IrpContext->DeviceObject;
662 if (IsExt2FsDevice(DeviceObject)) {
663
664 if (QueryPerf->Magic != EXT2_QUERY_PERFSTAT_MAGIC) {
665 Status = STATUS_INVALID_PARAMETER;
666 _SEH2_LEAVE;
667 }
668
669 if (QueryPerf->Command != IOCTL_APP_QUERY_PERFSTAT) {
670 Status = STATUS_INVALID_PARAMETER;
671 _SEH2_LEAVE;
672 }
673
674 if (Length != EXT2_QUERY_PERFSTAT_SZV1 &&
675 Length != EXT2_QUERY_PERFSTAT_SZV2) {
676 Status = STATUS_INVALID_PARAMETER;
677 _SEH2_LEAVE;
678 }
679
680 ExAcquireResourceSharedLite(&Ext2Global->Resource, TRUE);
681 GlobalDataResourceAcquired = TRUE;
682
683 if (Length == EXT2_QUERY_PERFSTAT_SZV2) {
684 QueryPerf->Flags = EXT2_QUERY_PERFSTAT_VER2;
685 QueryPerf->PerfStatV2 = Ext2Global->PerfStat;
686 } else {
687 memcpy(&QueryPerf->PerfStatV1.Irps[0], &Ext2Global->PerfStat.Irps[0],
688 FIELD_OFFSET(EXT2_PERF_STATISTICS_V1, Unit));
689 memcpy(&QueryPerf->PerfStatV1.Unit, &Ext2Global->PerfStat.Unit,
690 sizeof(EXT2_STAT_ARRAY_V1));
691 memcpy(&QueryPerf->PerfStatV1.Current, &Ext2Global->PerfStat.Current,
692 sizeof(EXT2_STAT_ARRAY_V1));
693 memcpy(&QueryPerf->PerfStatV1.Size, &Ext2Global->PerfStat.Size,
694 sizeof(EXT2_STAT_ARRAY_V1));
695 memcpy(&QueryPerf->PerfStatV1.Total, &Ext2Global->PerfStat.Total,
696 sizeof(EXT2_STAT_ARRAY_V1));
697 }
698
699 } else {
700 Status = STATUS_INVALID_PARAMETER;
701 _SEH2_LEAVE;
702 }
703
704 if (NT_SUCCESS(Status)) {
705 IrpContext->Irp->IoStatus.Information = Length;
706 }
707
708 } _SEH2_FINALLY {
709
710 if (GlobalDataResourceAcquired) {
711 ExReleaseResourceLite(&Ext2Global->Resource);
712 }
713
714 if (!IrpContext->ExceptionInProgress) {
715 Ext2CompleteIrpContext(IrpContext, Status);
716 }
717 } _SEH2_END
718
719 return Status;
720 }
721
722 NTSTATUS
723 Ex2ProcessMountPoint(
724 IN PEXT2_IRP_CONTEXT IrpContext,
725 IN PEXT2_MOUNT_POINT MountPoint,
726 IN ULONG Length
727 )
728 {
729 UNICODE_STRING Link;
730 UNICODE_STRING Target;
731 WCHAR Buffer[] = L"\\DosDevices\\Global\\Z:";
732 NTSTATUS status = STATUS_SUCCESS;
733
734 PDEVICE_OBJECT DeviceObject = NULL;
735
736 _SEH2_TRY {
737
738 ASSERT(IrpContext != NULL);
739 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
740 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
741
742 DeviceObject = IrpContext->DeviceObject;
743 if (!IsExt2FsDevice(DeviceObject)) {
744 status = STATUS_INVALID_PARAMETER;
745 _SEH2_LEAVE;
746 }
747
748 if (Length != sizeof(EXT2_MOUNT_POINT) ||
749 MountPoint->Magic != EXT2_APP_MOUNTPOINT_MAGIC) {
750 status = STATUS_INVALID_PARAMETER;
751 _SEH2_LEAVE;
752 }
753
754 RtlInitUnicodeString(&Link, Buffer);
755 Buffer[12] = MountPoint->Link[0];
756
757 switch (MountPoint->Command) {
758
759 case APP_CMD_ADD_DOS_SYMLINK:
760 RtlInitUnicodeString(&Target, &MountPoint->Name[0]);
761 status = IoCreateSymbolicLink(&Link, &Target);
762 break;
763
764 case APP_CMD_DEL_DOS_SYMLINK:
765 status = IoDeleteSymbolicLink(&Link);
766 break;
767
768 default:
769 status = STATUS_INVALID_PARAMETER;
770 }
771
772 } _SEH2_FINALLY {
773
774 if (!IrpContext->ExceptionInProgress) {
775 Ext2CompleteIrpContext(IrpContext, status);
776 }
777 } _SEH2_END;
778
779 return status;
780 }
781
782 NTSTATUS
783 Ext2DeviceControl (IN PEXT2_IRP_CONTEXT IrpContext)
784 {
785 PIRP Irp;
786 PIO_STACK_LOCATION irpSp;
787 ULONG code;
788 ULONG length;
789 NTSTATUS Status;
790
791 ASSERT(IrpContext);
792
793 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
794 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
795
796 Irp = IrpContext->Irp;
797
798 irpSp = IoGetCurrentIrpStackLocation(Irp);
799
800 code = irpSp->Parameters.DeviceIoControl.IoControlCode;
801 length = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
802
803 switch (code) {
804
805 case IOCTL_APP_VOLUME_PROPERTY:
806 Status = Ext2ProcessUserProperty(
807 IrpContext,
808 Irp->AssociatedIrp.SystemBuffer,
809 length
810 );
811 break;
812
813 case IOCTL_APP_QUERY_PERFSTAT:
814 Status = Ex2ProcessUserPerfStat(
815 IrpContext,
816 Irp->AssociatedIrp.SystemBuffer,
817 length
818 );
819 break;
820
821 case IOCTL_APP_MOUNT_POINT:
822 Status = Ex2ProcessMountPoint(
823 IrpContext,
824 Irp->AssociatedIrp.SystemBuffer,
825 length
826 );
827 break;
828
829 #if EXT2_UNLOAD
830 case IOCTL_PREPARE_TO_UNLOAD:
831 Status = Ext2PrepareToUnload(IrpContext);
832 break;
833 #endif
834 default:
835 Status = Ext2DeviceControlNormal(IrpContext);
836 }
837
838 return Status;
839 }
840