6 struct pnp_context
* context
;
19 static NTSTATUS STDCALL
pnp_completion(PDEVICE_OBJECT DeviceObject
, PIRP Irp
, PVOID conptr
) {
20 pnp_stripe
* stripe
= conptr
;
21 pnp_context
* context
= (pnp_context
*)stripe
->context
;
23 stripe
->Status
= Irp
->IoStatus
.Status
;
25 InterlockedDecrement(&context
->left
);
27 if (context
->left
== 0)
28 KeSetEvent(&context
->Event
, 0, FALSE
);
30 return STATUS_MORE_PROCESSING_REQUIRED
;
33 static NTSTATUS
send_disks_pnp_message(device_extension
* Vcb
, UCHAR minor
) {
35 UINT64 num_devices
, i
;
38 context
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(pnp_context
), ALLOC_TAG
);
40 ERR("out of memory\n");
41 return STATUS_INSUFFICIENT_RESOURCES
;
44 RtlZeroMemory(context
, sizeof(pnp_context
));
45 KeInitializeEvent(&context
->Event
, NotificationEvent
, FALSE
);
47 num_devices
= Vcb
->superblock
.num_devices
;
49 context
->stripes
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(pnp_stripe
) * num_devices
, ALLOC_TAG
);
50 if (!context
->stripes
) {
51 ERR("out of memory\n");
53 return STATUS_INSUFFICIENT_RESOURCES
;
56 RtlZeroMemory(context
->stripes
, sizeof(pnp_stripe
) * num_devices
);
58 for (i
= 0; i
< num_devices
; i
++) {
59 PIO_STACK_LOCATION IrpSp
;
61 if (Vcb
->devices
[i
].devobj
) {
62 context
->stripes
[i
].context
= (struct pnp_context
*)context
;
64 context
->stripes
[i
].Irp
= IoAllocateIrp(Vcb
->devices
[i
].devobj
->StackSize
, FALSE
);
66 if (!context
->stripes
[i
].Irp
) {
69 ERR("IoAllocateIrp failed\n");
71 for (j
= 0; j
< i
; j
++) {
72 if (Vcb
->devices
[j
].devobj
) {
73 IoFreeIrp(context
->stripes
[j
].Irp
);
76 ExFreePool(context
->stripes
);
79 return STATUS_INSUFFICIENT_RESOURCES
;
82 IrpSp
= IoGetNextIrpStackLocation(context
->stripes
[i
].Irp
);
83 IrpSp
->MajorFunction
= IRP_MJ_PNP
;
84 IrpSp
->MinorFunction
= minor
;
86 context
->stripes
[i
].Irp
->UserIosb
= &context
->stripes
[i
].iosb
;
88 IoSetCompletionRoutine(context
->stripes
[i
].Irp
, pnp_completion
, &context
->stripes
[i
], TRUE
, TRUE
, TRUE
);
90 context
->stripes
[i
].Irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
96 if (context
->left
== 0) {
97 Status
= STATUS_SUCCESS
;
101 for (i
= 0; i
< num_devices
; i
++) {
102 if (context
->stripes
[i
].Irp
) {
103 IoCallDriver(Vcb
->devices
[i
].devobj
, context
->stripes
[i
].Irp
);
107 KeWaitForSingleObject(&context
->Event
, Executive
, KernelMode
, FALSE
, NULL
);
109 Status
= STATUS_SUCCESS
;
111 for (i
= 0; i
< num_devices
; i
++) {
112 if (context
->stripes
[i
].Irp
) {
113 if (context
->stripes
[i
].Status
!= STATUS_SUCCESS
)
114 Status
= context
->stripes
[i
].Status
;
119 for (i
= 0; i
< num_devices
; i
++) {
120 if (context
->stripes
[i
].Irp
) {
121 IoFreeIrp(context
->stripes
[i
].Irp
);
125 ExFreePool(context
->stripes
);
131 static NTSTATUS
pnp_cancel_remove_device(PDEVICE_OBJECT DeviceObject
, PIRP Irp
) {
132 device_extension
* Vcb
= DeviceObject
->DeviceExtension
;
135 ExAcquireResourceExclusiveLite(&Vcb
->fcb_lock
, TRUE
);
137 if (Vcb
->root_fileref
&& Vcb
->root_fileref
->fcb
&& (Vcb
->root_fileref
->fcb
->open_count
> 0 || has_open_children(Vcb
->root_fileref
))) {
138 Status
= STATUS_ACCESS_DENIED
;
142 Status
= send_disks_pnp_message(Vcb
, IRP_MN_CANCEL_REMOVE_DEVICE
);
143 if (!NT_SUCCESS(Status
)) {
144 WARN("send_disks_pnp_message returned %08x\n", Status
);
148 Vcb
->removing
= FALSE
;
150 ExReleaseResourceLite(&Vcb
->fcb_lock
);
152 return STATUS_SUCCESS
;
155 static NTSTATUS
pnp_query_remove_device(PDEVICE_OBJECT DeviceObject
, PIRP Irp
) {
156 device_extension
* Vcb
= DeviceObject
->DeviceExtension
;
160 ExAcquireResourceExclusiveLite(&Vcb
->fcb_lock
, TRUE
);
162 if (Vcb
->root_fileref
&& Vcb
->root_fileref
->fcb
&& (Vcb
->root_fileref
->fcb
->open_count
> 0 || has_open_children(Vcb
->root_fileref
))) {
163 Status
= STATUS_ACCESS_DENIED
;
167 Status
= send_disks_pnp_message(Vcb
, IRP_MN_QUERY_REMOVE_DEVICE
);
168 if (!NT_SUCCESS(Status
)) {
169 WARN("send_disks_pnp_message returned %08x\n", Status
);
173 Vcb
->removing
= TRUE
;
175 InitializeListHead(&rollback
);
177 ExAcquireResourceExclusiveLite(&Vcb
->tree_lock
, TRUE
);
180 do_write(Vcb
, &rollback
);
182 clear_rollback(&rollback
);
184 ExReleaseResourceLite(&Vcb
->tree_lock
);
186 Status
= STATUS_SUCCESS
;
188 ExReleaseResourceLite(&Vcb
->fcb_lock
);
193 static NTSTATUS
pnp_remove_device(PDEVICE_OBJECT DeviceObject
, PIRP Irp
) {
194 device_extension
* Vcb
= DeviceObject
->DeviceExtension
;
197 Status
= send_disks_pnp_message(Vcb
, IRP_MN_REMOVE_DEVICE
);
198 if (!NT_SUCCESS(Status
)) {
199 WARN("send_disks_pnp_message returned %08x\n", Status
);
202 if (DeviceObject
->Vpb
->Flags
& VPB_MOUNTED
) {
203 Status
= FsRtlNotifyVolumeEvent(Vcb
->root_file
, FSRTL_VOLUME_DISMOUNT
);
204 if (!NT_SUCCESS(Status
)) {
205 WARN("FsRtlNotifyVolumeEvent returned %08x\n", Status
);
209 Vcb
->Vpb
->Flags
&= ~VPB_MOUNTED
;
212 return STATUS_SUCCESS
;
215 static NTSTATUS
pnp_start_device(PDEVICE_OBJECT DeviceObject
, PIRP Irp
) {
218 return STATUS_NOT_IMPLEMENTED
;
221 static NTSTATUS
pnp_surprise_removal(PDEVICE_OBJECT DeviceObject
, PIRP Irp
) {
224 return STATUS_SUCCESS
;
227 NTSTATUS STDCALL
drv_pnp(PDEVICE_OBJECT DeviceObject
, PIRP Irp
) {
228 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
229 device_extension
* Vcb
= DeviceObject
->DeviceExtension
;
233 FsRtlEnterFileSystem();
235 top_level
= is_top_level(Irp
);
237 if (Vcb
&& Vcb
->type
== VCB_TYPE_PARTITION0
) {
238 Status
= part0_passthrough(DeviceObject
, Irp
);
242 Status
= STATUS_NOT_IMPLEMENTED
;
244 switch (IrpSp
->MinorFunction
) {
245 case IRP_MN_CANCEL_REMOVE_DEVICE
:
246 Status
= pnp_cancel_remove_device(DeviceObject
, Irp
);
249 case IRP_MN_QUERY_REMOVE_DEVICE
:
250 Status
= pnp_query_remove_device(DeviceObject
, Irp
);
253 case IRP_MN_REMOVE_DEVICE
:
254 Status
= pnp_remove_device(DeviceObject
, Irp
);
257 case IRP_MN_START_DEVICE
:
258 Status
= pnp_start_device(DeviceObject
, Irp
);
261 case IRP_MN_SURPRISE_REMOVAL
:
262 Status
= pnp_surprise_removal(DeviceObject
, Irp
);
266 TRACE("passing minor function 0x%x on\n", IrpSp
->MinorFunction
);
268 IoSkipCurrentIrpStackLocation(Irp
);
269 Status
= IoCallDriver(Vcb
->devices
[0].devobj
, Irp
);
273 // // Irp->IoStatus.Status = Status;
274 // // Irp->IoStatus.Information = 0;
276 // IoSkipCurrentIrpStackLocation(Irp);
278 // Status = IoCallDriver(Vcb->devices[0].devobj, Irp);
280 // // IoCompleteRequest(Irp, IO_NO_INCREMENT);
282 Irp
->IoStatus
.Status
= Status
;
284 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
288 IoSetTopLevelIrp(NULL
);
290 FsRtlExitFileSystem();