20eec7bb24d913838c8cfbd5c64e666e5c859b01
[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_PROPERTY2 Property,
235 IN ULONG Length
236 )
237 {
238 NTSTATUS Status = STATUS_SUCCESS;
239 BOOLEAN GlobalDataResourceAcquired = FALSE;
240 struct nls_table * PageTable = NULL;
241
242 _SEH2_TRY {
243
244 if (Length < 8 || !IsFlagOn(Property->Flags, EXT2_FLAG_VP_SET_GLOBAL)) {
245 Status = STATUS_INVALID_PARAMETER;
246 _SEH2_LEAVE;
247 }
248
249 /* query Ext2Fsd's version and built date/time*/
250 if (Property->Command == APP_CMD_QUERY_VERSION) {
251 PEXT2_VOLUME_PROPERTY_VERSION PVPV =
252 (PEXT2_VOLUME_PROPERTY_VERSION) Property;
253
254 if (Length < sizeof(EXT2_VOLUME_PROPERTY_VERSION)) {
255 Status = STATUS_INVALID_PARAMETER;
256 _SEH2_LEAVE;
257 }
258
259 RtlZeroMemory(&PVPV->Date[0], 0x20);
260 RtlZeroMemory(&PVPV->Time[0], 0x20);
261 RtlZeroMemory(&PVPV->Version[0],0x1C);
262 strncpy(&PVPV->Version[0], gVersion, 0x1B);
263 strncpy(&PVPV->Date[0], gDate, 0x1F);
264 strncpy(&PVPV->Time[0], gTime, 0x1F);
265 _SEH2_LEAVE;
266 }
267
268 /* must be property query/set commands */
269 if (Property->Command == APP_CMD_SET_PROPERTY) {
270 if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
271 Status = STATUS_INVALID_PARAMETER;
272 _SEH2_LEAVE;
273 }
274 } else if (Property->Command == APP_CMD_SET_PROPERTY2) {
275 if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) {
276 Status = STATUS_INVALID_PARAMETER;
277 _SEH2_LEAVE;
278 }
279 } else if (Property->Command == APP_CMD_SET_PROPERTY3) {
280 if (Length < sizeof(EXT2_VOLUME_PROPERTY3)) {
281 Status = STATUS_INVALID_PARAMETER;
282 _SEH2_LEAVE;
283 }
284 } else {
285 Status = STATUS_INVALID_PARAMETER;
286 _SEH2_LEAVE;
287 }
288
289 ExAcquireResourceExclusiveLite(&Ext2Global->Resource, TRUE);
290 GlobalDataResourceAcquired = TRUE;
291
292 if (Property->bReadonly) {
293 ClearLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
294 ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
295 } else {
296 SetLongFlag(Ext2Global->Flags, EXT2_SUPPORT_WRITING);
297 if (Property->bExt3Writable) {
298 SetLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
299 } else {
300 ClearLongFlag(Ext2Global->Flags, EXT3_FORCE_WRITING);
301 }
302 }
303
304 PageTable = load_nls(Property->Codepage);
305 if (PageTable) {
306 memcpy(Ext2Global->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
307 Ext2Global->Codepage.PageTable = PageTable;
308 }
309
310 if (Property->Command == APP_CMD_SET_PROPERTY2 ||
311 Property->Command == APP_CMD_SET_PROPERTY3 ) {
312
313 RtlZeroMemory(Ext2Global->sHidingPrefix, HIDINGPAT_LEN);
314 if ((Ext2Global->bHidingPrefix = Property->bHidingPrefix)) {
315 RtlCopyMemory( Ext2Global->sHidingPrefix,
316 Property->sHidingPrefix,
317 HIDINGPAT_LEN - 1);
318 }
319 RtlZeroMemory(Ext2Global->sHidingSuffix, HIDINGPAT_LEN);
320 if ((Ext2Global->bHidingSuffix = Property->bHidingSuffix)) {
321 RtlCopyMemory( Ext2Global->sHidingSuffix,
322 Property->sHidingSuffix,
323 HIDINGPAT_LEN - 1);
324 }
325 }
326
327 if (Property->Command == APP_CMD_SET_PROPERTY3) {
328
329 PEXT2_VOLUME_PROPERTY3 Prop3 = (PEXT2_VOLUME_PROPERTY3)Property;
330
331 if (Prop3->Flags & EXT2_VPROP3_AUTOMOUNT) {
332 if (Prop3->AutoMount)
333 SetLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
334 else
335 ClearLongFlag(Ext2Global->Flags, EXT2_AUTO_MOUNT);
336 }
337 }
338
339 } _SEH2_FINALLY {
340
341 if (GlobalDataResourceAcquired) {
342 ExReleaseResourceLite(&Ext2Global->Resource);
343 }
344 } _SEH2_END;
345
346 return Status;
347 }
348
349
350 NTSTATUS
351 Ext2ProcessVolumeProperty(
352 IN PEXT2_VCB Vcb,
353 IN PEXT2_VOLUME_PROPERTY2 Property,
354 IN ULONG Length
355 )
356 {
357 NTSTATUS Status = STATUS_SUCCESS;
358 BOOLEAN VcbResourceAcquired = FALSE;
359 struct nls_table * PageTable = NULL;
360
361 _SEH2_TRY {
362
363 ExAcquireResourceExclusiveLite(&Vcb->MainResource, TRUE);
364 VcbResourceAcquired = TRUE;
365
366 if (Property->Command == APP_CMD_SET_PROPERTY ||
367 Property->Command == APP_CMD_QUERY_PROPERTY) {
368 if (Length < sizeof(EXT2_VOLUME_PROPERTY)) {
369 Status = STATUS_INVALID_PARAMETER;
370 _SEH2_LEAVE;
371 }
372 } else if (Property->Command == APP_CMD_SET_PROPERTY2 ||
373 Property->Command == APP_CMD_QUERY_PROPERTY2) {
374 if (Length < sizeof(EXT2_VOLUME_PROPERTY2)) {
375 Status = STATUS_INVALID_PARAMETER;
376 _SEH2_LEAVE;
377 }
378 }
379
380 switch (Property->Command) {
381
382 case APP_CMD_SET_PROPERTY:
383 case APP_CMD_SET_PROPERTY2:
384
385 if (Property->bReadonly) {
386
387 Ext2FlushFiles(NULL, Vcb, FALSE);
388 Ext2FlushVolume(NULL, Vcb, FALSE);
389 SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
390
391 } else {
392
393 if (Property->bExt3Writable) {
394 SetLongFlag(Vcb->Flags, VCB_FORCE_WRITING);
395 }
396
397 if (!Vcb->IsExt3fs) {
398 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
399 } else if (!Property->bExt3Writable) {
400 SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
401 } else if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) {
402 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
403 Ext2RecoverJournal(NULL, Vcb);
404 if (IsFlagOn(Vcb->Flags, VCB_JOURNAL_RECOVER)) {
405 SetLongFlag(Vcb->Flags, VCB_READ_ONLY);
406 } else {
407 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
408 }
409 } else {
410 ClearLongFlag(Vcb->Flags, VCB_READ_ONLY);
411 }
412 }
413
414 PageTable = load_nls(Property->Codepage);
415 memcpy(Vcb->Codepage.AnsiName, Property->Codepage, CODEPAGE_MAXLEN);
416 Vcb->Codepage.PageTable = PageTable;
417 if (Vcb->Codepage.PageTable) {
418 Ext2InitializeLabel(Vcb, Vcb->SuperBlock);
419 }
420
421 if (Property->Command == APP_CMD_SET_PROPERTY2) {
422
423 RtlZeroMemory(Vcb->sHidingPrefix, HIDINGPAT_LEN);
424 if ((Vcb->bHidingPrefix = Property->bHidingPrefix) != 0) {
425 RtlCopyMemory( Vcb->sHidingPrefix,
426 Property->sHidingPrefix,
427 HIDINGPAT_LEN - 1);
428 }
429
430 RtlZeroMemory(Vcb->sHidingSuffix, HIDINGPAT_LEN);
431 if ((Vcb->bHidingSuffix = Property->bHidingSuffix) != 0) {
432 RtlCopyMemory( Vcb->sHidingSuffix,
433 Property->sHidingSuffix,
434 HIDINGPAT_LEN - 1);
435 }
436
437 Vcb->DrvLetter = Property->DrvLetter;
438 }
439
440 break;
441
442 case APP_CMD_QUERY_PROPERTY:
443 case APP_CMD_QUERY_PROPERTY2:
444
445 Property->bExt2 = TRUE;
446 Property->bExt3 = Vcb->IsExt3fs;
447 Property->bReadonly = IsFlagOn(Vcb->Flags, VCB_READ_ONLY);
448 if (!Property->bReadonly && Vcb->IsExt3fs) {
449 Property->bExt3Writable = TRUE;
450 } else {
451 Property->bExt3Writable = FALSE;
452 }
453
454 RtlZeroMemory(Property->Codepage, CODEPAGE_MAXLEN);
455 if (Vcb->Codepage.PageTable) {
456 strncpy(Property->Codepage, Vcb->Codepage.PageTable->charset, CODEPAGE_MAXLEN);
457 } else {
458 strncpy(Property->Codepage, "default", CODEPAGE_MAXLEN);
459 }
460
461 if (Property->Command == APP_CMD_QUERY_PROPERTY2) {
462
463 RtlCopyMemory(Property->UUID, Vcb->SuperBlock->s_uuid, 16);
464
465 Property->DrvLetter = Vcb->DrvLetter;
466
467 if ((Property->bHidingPrefix = Vcb->bHidingPrefix) != 0) {
468 RtlCopyMemory( Property->sHidingPrefix,
469 Vcb->sHidingPrefix,
470 HIDINGPAT_LEN);
471 } else {
472 RtlZeroMemory( Property->sHidingPrefix,
473 HIDINGPAT_LEN);
474 }
475
476 if ((Property->bHidingSuffix = Vcb->bHidingSuffix) != 0) {
477 RtlCopyMemory( Property->sHidingSuffix,
478 Vcb->sHidingSuffix,
479 HIDINGPAT_LEN);
480 } else {
481 RtlZeroMemory( Property->sHidingSuffix,
482 HIDINGPAT_LEN);
483 }
484 }
485
486 break;
487
488 default:
489 Status = STATUS_INVALID_PARAMETER;
490 break;
491 }
492
493 } _SEH2_FINALLY {
494
495 if (VcbResourceAcquired) {
496 ExReleaseResourceLite(&Vcb->MainResource);
497 }
498 } _SEH2_END;
499
500 return Status;
501 }
502
503 NTSTATUS
504 Ext2ProcessUserProperty(
505 IN PEXT2_IRP_CONTEXT IrpContext,
506 IN PEXT2_VOLUME_PROPERTY2 Property,
507 IN ULONG Length
508 )
509 {
510 NTSTATUS Status = STATUS_SUCCESS;
511 PEXT2_VCB Vcb = NULL;
512 PDEVICE_OBJECT DeviceObject = NULL;
513
514 _SEH2_TRY {
515
516 ASSERT(IrpContext != NULL);
517 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
518 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
519
520 if (Property->Magic != EXT2_VOLUME_PROPERTY_MAGIC) {
521 Status = STATUS_INVALID_PARAMETER;
522 _SEH2_LEAVE;
523 }
524
525 DeviceObject = IrpContext->DeviceObject;
526 if (IsExt2FsDevice(DeviceObject)) {
527 Status = Ext2ProcessGlobalProperty(DeviceObject, Property, Length);
528 } else {
529 Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;
530 if (!((Vcb) && (Vcb->Identifier.Type == EXT2VCB) &&
531 (Vcb->Identifier.Size == sizeof(EXT2_VCB)))) {
532 Status = STATUS_INVALID_PARAMETER;
533 _SEH2_LEAVE;
534 }
535 Status = Ext2ProcessVolumeProperty(Vcb, Property, Length);
536 }
537
538 if (NT_SUCCESS(Status)) {
539 IrpContext->Irp->IoStatus.Information = Length;
540 }
541
542 } _SEH2_FINALLY {
543
544 if (!IrpContext->ExceptionInProgress) {
545 Ext2CompleteIrpContext(IrpContext, Status);
546 }
547 } _SEH2_END;
548
549 return Status;
550 }
551
552 NTSTATUS
553 Ex2ProcessUserPerfStat(
554 IN PEXT2_IRP_CONTEXT IrpContext,
555 IN PEXT2_QUERY_PERFSTAT QueryPerf,
556 IN ULONG Length
557 )
558 {
559
560 #ifndef __REACTOS__
561 PEXT2_VCB Vcb = NULL;
562 #endif
563 PDEVICE_OBJECT DeviceObject = NULL;
564
565 BOOLEAN GlobalDataResourceAcquired = FALSE;
566 NTSTATUS Status = STATUS_SUCCESS;
567
568 _SEH2_TRY {
569
570 ASSERT(IrpContext != NULL);
571 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
572 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
573
574 DeviceObject = IrpContext->DeviceObject;
575 if (IsExt2FsDevice(DeviceObject)) {
576
577 if (QueryPerf->Magic != EXT2_QUERY_PERFSTAT_MAGIC) {
578 Status = STATUS_INVALID_PARAMETER;
579 _SEH2_LEAVE;
580 }
581
582 if (QueryPerf->Command != IOCTL_APP_QUERY_PERFSTAT) {
583 Status = STATUS_INVALID_PARAMETER;
584 _SEH2_LEAVE;
585 }
586
587 if (Length != EXT2_QUERY_PERFSTAT_SZV1 &&
588 Length != EXT2_QUERY_PERFSTAT_SZV2) {
589 Status = STATUS_INVALID_PARAMETER;
590 _SEH2_LEAVE;
591 }
592
593 ExAcquireResourceSharedLite(&Ext2Global->Resource, TRUE);
594 GlobalDataResourceAcquired = TRUE;
595
596 if (Length == EXT2_QUERY_PERFSTAT_SZV2) {
597 QueryPerf->Flags = EXT2_QUERY_PERFSTAT_VER2;
598 QueryPerf->PerfStatV2 = Ext2Global->PerfStat;
599 } else {
600 memcpy(&QueryPerf->PerfStatV1.Irps[0], &Ext2Global->PerfStat.Irps[0],
601 FIELD_OFFSET(EXT2_PERF_STATISTICS_V1, Unit));
602 memcpy(&QueryPerf->PerfStatV1.Unit, &Ext2Global->PerfStat.Unit,
603 sizeof(EXT2_STAT_ARRAY_V1));
604 memcpy(&QueryPerf->PerfStatV1.Current, &Ext2Global->PerfStat.Current,
605 sizeof(EXT2_STAT_ARRAY_V1));
606 memcpy(&QueryPerf->PerfStatV1.Size, &Ext2Global->PerfStat.Size,
607 sizeof(EXT2_STAT_ARRAY_V1));
608 memcpy(&QueryPerf->PerfStatV1.Total, &Ext2Global->PerfStat.Total,
609 sizeof(EXT2_STAT_ARRAY_V1));
610 }
611
612 } else {
613 Status = STATUS_INVALID_PARAMETER;
614 _SEH2_LEAVE;
615 }
616
617 if (NT_SUCCESS(Status)) {
618 IrpContext->Irp->IoStatus.Information = Length;
619 }
620
621 } _SEH2_FINALLY {
622
623 if (GlobalDataResourceAcquired) {
624 ExReleaseResourceLite(&Ext2Global->Resource);
625 }
626
627 if (!IrpContext->ExceptionInProgress) {
628 Ext2CompleteIrpContext(IrpContext, Status);
629 }
630 } _SEH2_END
631
632 return Status;
633 }
634
635 NTSTATUS
636 Ex2ProcessMountPoint(
637 IN PEXT2_IRP_CONTEXT IrpContext,
638 IN PEXT2_MOUNT_POINT MountPoint,
639 IN ULONG Length
640 )
641 {
642 UNICODE_STRING Link;
643 UNICODE_STRING Target;
644 WCHAR Buffer[] = L"\\DosDevices\\Global\\Z:";
645 NTSTATUS status = STATUS_SUCCESS;
646
647 PDEVICE_OBJECT DeviceObject = NULL;
648
649 _SEH2_TRY {
650
651 ASSERT(IrpContext != NULL);
652 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
653 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
654
655 DeviceObject = IrpContext->DeviceObject;
656 if (!IsExt2FsDevice(DeviceObject)) {
657 status = STATUS_INVALID_PARAMETER;
658 _SEH2_LEAVE;
659 }
660
661 if (Length != sizeof(EXT2_MOUNT_POINT) ||
662 MountPoint->Magic != EXT2_APP_MOUNTPOINT_MAGIC) {
663 status = STATUS_INVALID_PARAMETER;
664 _SEH2_LEAVE;
665 }
666
667 RtlInitUnicodeString(&Link, Buffer);
668 Buffer[12] = MountPoint->Link[0];
669
670 switch (MountPoint->Command) {
671
672 case APP_CMD_ADD_DOS_SYMLINK:
673 RtlInitUnicodeString(&Target, &MountPoint->Name[0]);
674 status = IoCreateSymbolicLink(&Link, &Target);
675 break;
676
677 case APP_CMD_DEL_DOS_SYMLINK:
678 status = IoDeleteSymbolicLink(&Link);
679 break;
680
681 default:
682 status = STATUS_INVALID_PARAMETER;
683 }
684
685 } _SEH2_FINALLY {
686
687 if (!IrpContext->ExceptionInProgress) {
688 Ext2CompleteIrpContext(IrpContext, status);
689 }
690 } _SEH2_END;
691
692 return status;
693 }
694
695 NTSTATUS
696 Ext2DeviceControl (IN PEXT2_IRP_CONTEXT IrpContext)
697 {
698 PIRP Irp;
699 PIO_STACK_LOCATION irpSp;
700 ULONG code;
701 ULONG length;
702 NTSTATUS Status;
703
704 ASSERT(IrpContext);
705
706 ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
707 (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
708
709 Irp = IrpContext->Irp;
710
711 irpSp = IoGetCurrentIrpStackLocation(Irp);
712
713 code = irpSp->Parameters.DeviceIoControl.IoControlCode;
714 length = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
715
716 switch (code) {
717
718 case IOCTL_APP_VOLUME_PROPERTY:
719 Status = Ext2ProcessUserProperty(
720 IrpContext,
721 Irp->AssociatedIrp.SystemBuffer,
722 length
723 );
724 break;
725
726 case IOCTL_APP_QUERY_PERFSTAT:
727 Status = Ex2ProcessUserPerfStat(
728 IrpContext,
729 Irp->AssociatedIrp.SystemBuffer,
730 length
731 );
732 break;
733
734 case IOCTL_APP_MOUNT_POINT:
735 Status = Ex2ProcessMountPoint(
736 IrpContext,
737 Irp->AssociatedIrp.SystemBuffer,
738 length
739 );
740 break;
741
742 #if EXT2_UNLOAD
743 case IOCTL_PREPARE_TO_UNLOAD:
744 Status = Ext2PrepareToUnload(IrpContext);
745 break;
746 #endif
747 default:
748 Status = Ext2DeviceControlNormal(IrpContext);
749 }
750
751 return Status;
752 }