Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / drivers / filesystems / reiserfs / src / devctl.c
1 /*
2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
4 * FILE: devctl.c
5 * PURPOSE:
6 * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
7 * HOMEPAGE:
8 * UPDATE HISTORY:
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include "rfsd.h"
14
15 /* GLOBALS ***************************************************************/
16
17 extern PRFSD_GLOBAL RfsdGlobal;
18
19 /* DEFINITIONS *************************************************************/
20
21 #ifdef _PREFAST_
22 IO_COMPLETION_ROUTINE RfsdDeviceControlCompletion;
23 #endif // _PREFAST_
24
25 NTSTATUS NTAPI
26 RfsdDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject,
27 IN PIRP Irp,
28 IN PVOID Context);
29
30 #ifdef ALLOC_PRAGMA
31 //#pragma alloc_text(PAGE, RfsdDeviceControlCompletion)
32 #pragma alloc_text(PAGE, RfsdDeviceControl)
33 #pragma alloc_text(PAGE, RfsdDeviceControlNormal)
34 #if RFSD_UNLOAD
35 #pragma alloc_text(PAGE, RfsdPrepareToUnload)
36 #endif
37 #endif
38
39 NTSTATUS NTAPI
40 RfsdDeviceControlCompletion (IN PDEVICE_OBJECT DeviceObject,
41 IN PIRP Irp,
42 IN PVOID Context)
43 {
44 if (Irp->PendingReturned) {
45 IoMarkIrpPending(Irp);
46 }
47
48 return STATUS_SUCCESS;
49 }
50
51 NTSTATUS
52 RfsdDeviceControlNormal (IN PRFSD_IRP_CONTEXT IrpContext)
53 {
54 PDEVICE_OBJECT DeviceObject;
55 BOOLEAN CompleteRequest = TRUE;
56 NTSTATUS Status = STATUS_UNSUCCESSFUL;
57
58 PRFSD_VCB Vcb;
59
60 PIRP Irp;
61 PIO_STACK_LOCATION IrpSp;
62 PIO_STACK_LOCATION NextIrpSp;
63
64 PDEVICE_OBJECT TargetDeviceObject;
65
66 PAGED_CODE();
67
68 _SEH2_TRY {
69
70 ASSERT(IrpContext != NULL);
71
72 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
73 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
74
75 CompleteRequest = TRUE;
76
77 DeviceObject = IrpContext->DeviceObject;
78
79 if (DeviceObject == RfsdGlobal->DeviceObject) {
80 Status = STATUS_INVALID_DEVICE_REQUEST;
81 _SEH2_LEAVE;
82 }
83
84 Irp = IrpContext->Irp;
85 IrpSp = IoGetCurrentIrpStackLocation(Irp);
86
87 Vcb = (PRFSD_VCB) IrpSp->FileObject->FsContext;
88
89 if (!((Vcb) && (Vcb->Identifier.Type == RFSDVCB) &&
90 (Vcb->Identifier.Size == sizeof(RFSD_VCB)))) {
91 Status = STATUS_INVALID_PARAMETER;
92 _SEH2_LEAVE;
93 }
94
95 TargetDeviceObject = Vcb->TargetDeviceObject;
96
97 //
98 // Pass on the IOCTL to the driver below
99 //
100
101 CompleteRequest = FALSE;
102
103 NextIrpSp = IoGetNextIrpStackLocation( Irp );
104 *NextIrpSp = *IrpSp;
105
106 IoSetCompletionRoutine(
107 Irp,
108 RfsdDeviceControlCompletion,
109 NULL,
110 FALSE,
111 TRUE,
112 TRUE );
113
114 Status = IoCallDriver(TargetDeviceObject, Irp);
115
116 } _SEH2_FINALLY {
117
118 if (!IrpContext->ExceptionInProgress) {
119 if (IrpContext) {
120 if (!CompleteRequest) {
121 IrpContext->Irp = NULL;
122 }
123
124 RfsdCompleteIrpContext(IrpContext, Status);
125 }
126 }
127 } _SEH2_END;
128
129 return Status;
130 }
131
132 #if RFSD_UNLOAD
133
134 __drv_mustHoldCriticalRegion
135 NTSTATUS
136 RfsdPrepareToUnload (IN PRFSD_IRP_CONTEXT IrpContext)
137 {
138 PDEVICE_OBJECT DeviceObject;
139 NTSTATUS Status = STATUS_UNSUCCESSFUL;
140 BOOLEAN GlobalDataResourceAcquired = FALSE;
141
142 PAGED_CODE();
143
144 _SEH2_TRY {
145
146 ASSERT(IrpContext != NULL);
147
148 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
149 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
150
151 DeviceObject = IrpContext->DeviceObject;
152
153 if (DeviceObject != RfsdGlobal->DeviceObject) {
154 Status = STATUS_INVALID_DEVICE_REQUEST;
155 _SEH2_LEAVE;
156 }
157
158 ExAcquireResourceExclusiveLite(
159 &RfsdGlobal->Resource,
160 TRUE );
161
162 GlobalDataResourceAcquired = TRUE;
163
164 if (FlagOn(RfsdGlobal->Flags, RFSD_UNLOAD_PENDING)) {
165 RfsdPrint((DBG_ERROR, "RfsdPrepareUnload: Already ready to unload.\n"));
166
167 Status = STATUS_ACCESS_DENIED;
168
169 _SEH2_LEAVE;
170 }
171
172 {
173 PRFSD_VCB Vcb;
174 PLIST_ENTRY ListEntry;
175
176 ListEntry = RfsdGlobal->VcbList.Flink;
177
178 while (ListEntry != &(RfsdGlobal->VcbList)) {
179
180 Vcb = CONTAINING_RECORD(ListEntry, RFSD_VCB, Next);
181 ListEntry = ListEntry->Flink;
182
183 if (Vcb && (!Vcb->ReferenceCount) &&
184 IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
185 RfsdRemoveVcb(Vcb);
186 RfsdClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);
187
188 RfsdFreeVcb(Vcb);
189 }
190 }
191 }
192
193 if (!IsListEmpty(&(RfsdGlobal->VcbList))) {
194
195 RfsdPrint((DBG_ERROR, "RfsdPrepareUnload: Mounted volumes exists.\n"));
196
197 Status = STATUS_ACCESS_DENIED;
198
199 _SEH2_LEAVE;
200 }
201
202 IoUnregisterFileSystem(RfsdGlobal->DeviceObject);
203
204 #ifdef _MSC_VER
205 #pragma prefast( suppress: 28175, "allowed to unload" )
206 #endif
207 RfsdGlobal->DriverObject->DriverUnload = DriverUnload;
208
209 SetFlag(RfsdGlobal->Flags ,RFSD_UNLOAD_PENDING);
210
211 RfsdPrint((DBG_INFO, "RfsdPrepareToUnload: Driver is ready to unload.\n"));
212
213 Status = STATUS_SUCCESS;
214
215 } _SEH2_FINALLY {
216
217 if (GlobalDataResourceAcquired) {
218 ExReleaseResourceForThreadLite(
219 &RfsdGlobal->Resource,
220 ExGetCurrentResourceThread()
221 );
222 }
223
224 if (!IrpContext->ExceptionInProgress) {
225 RfsdCompleteIrpContext(IrpContext, Status);
226 }
227 } _SEH2_END;
228
229 return Status;
230 }
231
232 #endif
233
234 __drv_mustHoldCriticalRegion
235 NTSTATUS
236 RfsdDeviceControl (IN PRFSD_IRP_CONTEXT IrpContext)
237 {
238 PIRP Irp;
239 PIO_STACK_LOCATION IoStackLocation;
240 ULONG IoControlCode;
241 NTSTATUS Status;
242
243 PAGED_CODE();
244
245 ASSERT(IrpContext);
246
247 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
248 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
249
250 Irp = IrpContext->Irp;
251
252 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
253
254 IoControlCode =
255 IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
256
257 switch (IoControlCode) {
258
259 #if RFSD_UNLOAD
260 case IOCTL_PREPARE_TO_UNLOAD:
261 Status = RfsdPrepareToUnload(IrpContext);
262 break;
263 #endif
264 default:
265 Status = RfsdDeviceControlNormal(IrpContext);
266 }
267
268 return Status;
269 }