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