My favorites | Sign in
Project Home Downloads Wiki Issues Source
Repository:
Checkout   Browse   Changes   Clones  
Changes to /GhostBus/sys/ghostbus.c
b16a57e2037a vs. eae8a2d49f6c Compare: vs.  Format:
Revision eae8a2d49f6c
Go to: 
Project members, sign in to write a code review
/GhostBus/sys/ghostbus.c   b16a57e2037a /GhostBus/sys/ghostbus.c   eae8a2d49f6c
1 /* 1 /*
2 * Ghost - A honeypot for USB malware 2 * Ghost - A honeypot for USB malware
3 * Copyright (C) 2011-2012 Sebastian Poeplau (sebastian.poeplau@gmail.com) 3 * Copyright (C) 2011-2012 Sebastian Poeplau (sebastian.poeplau@gmail.com)
4 * 4 *
5 * This program is free software: you can redistribute it and/or modify 5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or 7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version. 8 * (at your option) any later version.
9 * 9 *
10 * This program is distributed in the hope that it will be useful, 10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * 17 *
18 * Additional permission under GNU GPL version 3 section 7 18 * Additional permission under GNU GPL version 3 section 7
19 * 19 *
20 * If you modify this Program, or any covered work, by linking or combining 20 * If you modify this Program, or any covered work, by linking or combining
21 * it with the Windows Driver Frameworks (or a modified version of that library), 21 * it with the Windows Driver Frameworks (or a modified version of that library),
22 * containing parts covered by the terms of the Microsoft Software License Terms - 22 * containing parts covered by the terms of the Microsoft Software License Terms -
23 * Microsoft Windows Driver Kit, the licensors of this Program grant you additional 23 * Microsoft Windows Driver Kit, the licensors of this Program grant you additional
24 * permission to convey the resulting work. 24 * permission to convey the resulting work.
25 * 25 *
26 */ 26 */
27 27
28 #include "ghostbus_internal.h" 28 #include "ghostbus_internal.h"
29 #include "ghostbus.h" 29 #include "ghostbus.h"
30 #include "file_io.h" 30 #include "file_io.h"
31 #include "device_control.h" 31 #include "device_control.h"
32 #include <version.h> 32 #include <version.h>
33 33
34 #include <ntstrsafe.h> 34 #include <ntstrsafe.h>
35 #include <wdmguid.h> 35 #include <wdmguid.h>
36 36
37 37
38 /* 38 /*
39 * Declaration of framework callback methods and DriverEntry 39 * Declaration of framework callback methods and DriverEntry
40 */ 40 */
41 DRIVER_INITIALIZE DriverEntry; 41 DRIVER_INITIALIZE DriverEntry;
42 EVT_WDF_DRIVER_DEVICE_ADD GhostBusDeviceAdd; 42 EVT_WDF_DRIVER_DEVICE_ADD GhostBusDeviceAdd;
43 EVT_WDF_DRIVER_UNLOAD GhostBusUnload; 43 EVT_WDF_DRIVER_UNLOAD GhostBusUnload;
44 EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL GhostBusDeviceControl; 44 EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL GhostBusDeviceControl;
45 EVT_WDF_CHILD_LIST_CREATE_DEVICE GhostBusChildListCreateDevice; 45 EVT_WDF_CHILD_LIST_CREATE_DEVICE GhostBusChildListCreateDevice;
46 46
47 47
48 /* 48 /*
49 * This is the driver's main routine. It is called once when the driver is loaded. 49 * This is the driver's main routine. It is called once when the driver is loaded.
50 * 50 *
51 * DriverEntry mainly creates the framework driver object and registers the AddDevice routine. 51 * DriverEntry mainly creates the framework driver object and registers the AddDevice routine.
52 */ 52 */
53 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 53 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
54 { 54 {
55 WDF_DRIVER_CONFIG config; 55 WDF_DRIVER_CONFIG config;
56 WDFDRIVER Driver; 56 WDFDRIVER Driver;
57 NTSTATUS status; 57 NTSTATUS status;
58 58
59 KdPrint(("GhostBus version %s built %s %s\n", GHOST_VERSION, __DATE__, __TIME__)); 59 KdPrint(("GhostBus version %s built %s %s\n", GHOST_VERSION, __DATE__, __TIME__));
60 60
61 WDF_DRIVER_CONFIG_INIT(&config, GhostBusDeviceAdd); 61 WDF_DRIVER_CONFIG_INIT(&config, GhostBusDeviceAdd);
62 config.EvtDriverUnload = GhostBusUnload; 62 config.EvtDriverUnload = GhostBusUnload;
63 status = WdfDriverCreate(DriverObject, RegistryPath, NULL, &config, &Driver); 63 status = WdfDriverCreate(DriverObject, RegistryPath, NULL, &config, &Driver);
64 64
65 if (!NT_SUCCESS(status)) { 65 if (!NT_SUCCESS(status)) {
66 KdPrint(("Unable to create WDF driver\n")); 66 KdPrint(("Unable to create WDF driver\n"));
67 return status; 67 return status;
68 } 68 }
69 69
70 return status; 70 return status;
71 } 71 }
72 72
73 73
74 /* 74 /*
75 * This function is called just before the device object is destroyed. We use it 75 * This function is called just before the device object is destroyed. We use it
76 * to unmount the image file in order to ensure that all data is written to disk 76 * to unmount the image file in order to ensure that all data is written to disk
77 * successfully before the file handle is discarded. 77 * successfully before the file handle is discarded.
78 */ 78 */
79 VOID GhostDriveDeviceCleanup(WDFOBJECT Object) 79 VOID GhostDriveDeviceCleanup(WDFOBJECT Object)
80 { 80 {
81 NTSTATUS status; 81 NTSTATUS status;
82 PGHOST_DRIVE_CONTEXT Context; 82 PGHOST_DRIVE_PDO_CONTEXT Context;
83 PGHOST_INFO_PROCESS_DATA ProcessInfo; 83 PGHOST_INFO_PROCESS_DATA ProcessInfo;
84 int counter; 84 int counter;
85 85
86 Context = GhostDriveGetContext(Object); 86 Context = GhostDrivePdoGetContext(Object);
87 KdPrint(("Image has been written to: %u\n", Context->ImageWritten)); 87 KdPrint(("Image has been written to: %u\n", Context->ImageWritten));
88 if (Context->ImageMounted) 88 if (Context->ImageMounted)
89 GhostFileIoUmountImage(Object); 89 GhostFileIoUmountImage(Object);
90 90
91 // Free the writer info structs 91 // Free the writer info structs
92 counter = 0; 92 counter = 0;
93 while (Context->WriterInfo != NULL) { 93 while (Context->WriterInfo != NULL) {
94 ProcessInfo = Context->WriterInfo; 94 ProcessInfo = Context->WriterInfo;
95 Context->WriterInfo = Context->WriterInfo->Next; 95 Context->WriterInfo = Context->WriterInfo->Next;
96 GhostInfoFreeProcessData(ProcessInfo); 96 GhostInfoFreeProcessData(ProcessInfo);
97 counter++; 97 counter++;
98 } 98 }
99 99
100 KdPrint(("%d info struct(s) freed\n", counter)); 100 KdPrint(("%d info struct(s) freed\n", counter));
101 } 101 }
102 102
103 103
104 /* 104 /*
105 * This routine is called by the framework whenever a new device is found and needs to be installed. 105 * This routine is called by the framework whenever a new device is found and needs to be installed.
106 * For GhostBus, there should be no more than one device in the system. 106 * For GhostBus, there should be no more than one device in the system.
107 * 107 *
108 * GhostBusDeviceAdd sets up a symbolic link for user-mode applications to communicate with the 108 * GhostBusDeviceAdd sets up a symbolic link for user-mode applications to communicate with the
109 * device and initializes I/O and device properties. 109 * device and initializes I/O and device properties.
110 */ 110 */
111 NTSTATUS GhostBusDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit) 111 NTSTATUS GhostBusDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
112 { 112 {
113 NTSTATUS status; 113 NTSTATUS status;
114 WDFDEVICE Device; 114 WDFDEVICE Device;
115 DECLARE_CONST_UNICODE_STRING(DeviceName, BUS_DEVICE_NAME); 115 DECLARE_CONST_UNICODE_STRING(DeviceName, BUS_DEVICE_NAME);
116 DECLARE_CONST_UNICODE_STRING(LinkName, BUS_LINK_NAME); 116 DECLARE_CONST_UNICODE_STRING(LinkName, BUS_LINK_NAME);
117 WDF_IO_QUEUE_CONFIG QueueConfig; 117 WDF_IO_QUEUE_CONFIG QueueConfig;
118 WDF_CHILD_LIST_CONFIG ChildListConfig; 118 WDF_CHILD_LIST_CONFIG ChildListConfig;
119 PNP_BUS_INFORMATION BusInfo; 119 PNP_BUS_INFORMATION BusInfo;
120 WDF_OBJECT_ATTRIBUTES DeviceAttr; 120 WDF_OBJECT_ATTRIBUTES DeviceAttr;
121 121
122 KdPrint(("DeviceAdd called\n")); 122 KdPrint(("DeviceAdd called\n"));
123 123
124 // Set the maximum execution level 124 // Set the maximum execution level
125 WDF_OBJECT_ATTRIBUTES_INIT(&DeviceAttr); 125 WDF_OBJECT_ATTRIBUTES_INIT(&DeviceAttr);
126 DeviceAttr.ExecutionLevel = WdfExecutionLevelPassive; 126 DeviceAttr.ExecutionLevel = WdfExecutionLevelPassive;
127 127
128 // Name the new device 128 // Name the new device
129 status = WdfDeviceInitAssignName(DeviceInit, &DeviceName); 129 status = WdfDeviceInitAssignName(DeviceInit, &DeviceName);
130 if (!NT_SUCCESS(status)) { 130 if (!NT_SUCCESS(status)) {
131 KdPrint(("Could not assign a name\n")); 131 KdPrint(("Could not assign a name\n"));
132 return status; 132 return status;
133 } 133 }
134 134
135 // Set device properties 135 // Set device properties
136 //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); 136 //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
137 WdfDeviceInitSetExclusive(DeviceInit, TRUE); 137 WdfDeviceInitSetExclusive(DeviceInit, TRUE);
138 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); 138 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
139 139
140 // Initialize the device's child list 140 // Initialize the device's child list
141 WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(GHOST_DRIVE_IDENTIFICATION), 141 WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(GHOST_DRIVE_IDENTIFICATION),
142 GhostBusChildListCreateDevice); 142 GhostBusChildListCreateDevice);
143 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES); 143 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES);
144 144
145 // Create the device 145 // Create the device
146 status = WdfDeviceCreate(&DeviceInit, &DeviceAttr, &Device); 146 status = WdfDeviceCreate(&DeviceInit, &DeviceAttr, &Device);
147 if (!NT_SUCCESS(status)) { 147 if (!NT_SUCCESS(status)) {
148 KdPrint(("Could not create a device\n")); 148 KdPrint(("Could not create a device\n"));
149 return status; 149 return status;
150 } 150 }
151 151
152 // Set up the device's I/O queue to handle I/O requests 152 // Set up the device's I/O queue to handle I/O requests
153 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&QueueConfig, WdfIoQueueDispatchSequential); 153 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&QueueConfig, WdfIoQueueDispatchSequential);
154 QueueConfig.EvtIoDeviceControl = GhostBusDeviceControl; 154 QueueConfig.EvtIoDeviceControl = GhostBusDeviceControl;
155 status = WdfIoQueueCreate(Device, &QueueConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL); 155 status = WdfIoQueueCreate(Device, &QueueConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL);
156 if (!NT_SUCCESS(status)) { 156 if (!NT_SUCCESS(status)) {
157 KdPrint(("Could create the I/O queue\n")); 157 KdPrint(("Could create the I/O queue\n"));
158 return status; 158 return status;
159 } 159 }
160 160
161 // Set information for child devices 161 // Set information for child devices
162 //BusInfo.BusTypeGuid = GUID_BUS_TYPE_GHOST; 162 //BusInfo.BusTypeGuid = GUID_BUS_TYPE_GHOST;
163 BusInfo.BusTypeGuid = GUID_BUS_TYPE_USB; 163 BusInfo.BusTypeGuid = GUID_BUS_TYPE_USB;
164 BusInfo.LegacyBusType = PNPBus; 164 BusInfo.LegacyBusType = PNPBus;
165 BusInfo.BusNumber = 0; 165 BusInfo.BusNumber = 0;
166 WdfDeviceSetBusInformationForChildren(Device, &BusInfo); 166 WdfDeviceSetBusInformationForChildren(Device, &BusInfo);
167 167
168 // Create symbolic link in user-reachable directory 168 // Create symbolic link in user-reachable directory
169 status = WdfDeviceCreateSymbolicLink(Device, &LinkName); 169 status = WdfDeviceCreateSymbolicLink(Device, &LinkName);
170 if (!NT_SUCCESS(status)) { 170 if (!NT_SUCCESS(status)) {
171 KdPrint(("Could not create symbolic link\n")); 171 KdPrint(("Could not create symbolic link\n"));
172 return status; 172 return status;
173 } 173 }
174 174
175 return status; 175 return status;
176 } 176 }
177 177
178 178
179 /* 179 /*
180 * This routine is called by the framework when the driver is about to be unloaded. 180 * This routine is called by the framework when the driver is about to be unloaded.
181 */ 181 */
182 VOID GhostBusUnload(WDFDRIVER Driver) 182 VOID GhostBusUnload(WDFDRIVER Driver)
183 { 183 {
184 KdPrint(("Unload called\n")); 184 KdPrint(("Unload called\n"));
185 } 185 }
186 186
187 187
188 NTSTATUS GhostDriveInitImage(WDFDEVICE Device, ULONG ID) { 188 /*
189 * This routine initiates an image file for the given drive PDO.
190 */
191 NTSTATUS GhostDrivePdoInitImage(WDFDEVICE Device, ULONG ID) {
189 WCHAR imagename[] = IMAGE_NAME; 192 WCHAR imagename[] = IMAGE_NAME;
190 LARGE_INTEGER FileSize; 193 LARGE_INTEGER FileSize;
191 UNICODE_STRING FileToMount, RegValue; 194 UNICODE_STRING FileToMount, RegValue;
192 NTSTATUS status; 195 NTSTATUS status;
193 WDFKEY ParametersKey; 196 WDFKEY ParametersKey;
194 DECLARE_CONST_UNICODE_STRING(ValueName, L"ImageFileName0"); 197 DECLARE_CONST_UNICODE_STRING(ValueName, L"ImageFileName0");
195 USHORT ByteLength = 0; 198 USHORT ByteLength = 0;
196 PWCHAR Buffer; 199 PWCHAR Buffer;
197 int i; 200 int i;
198 PCWSTR Prefix = L"\\DosDevices\\"; 201 PCWSTR Prefix = L"\\DosDevices\\";
199 size_t PrefixLength; 202 size_t PrefixLength;
200 203
201 #ifndef USE_FIXED_IMAGE_NAME 204 #ifndef USE_FIXED_IMAGE_NAME
202 KdPrint(("Reading the image file name from the registry\n")); 205 KdPrint(("Reading the image file name from the registry\n"));
203 206
204 /* Read the desired image file name from the registry */ 207 /* Read the desired image file name from the registry */
205 status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), GENERIC_READ, 208 status = WdfDriverOpenParametersRegistryKey(WdfGetDriver(), GENERIC_READ,
206 WDF_NO_OBJECT_ATTRIBUTES, &ParametersKey); 209 WDF_NO_OBJECT_ATTRIBUTES, &ParametersKey);
207 if (!NT_SUCCESS(status)) { 210 if (!NT_SUCCESS(status)) {
208 KdPrint(("Could not open the driver's registry key\n")); 211 KdPrint(("Could not open the driver's registry key\n"));
209 return status; 212 return status;
210 } 213 }
211 214
212 ValueName.Buffer[13] = (WCHAR)(ID + 0x30); 215 ValueName.Buffer[13] = (WCHAR)(ID + 0x30);
213 status = WdfRegistryQueryUnicodeString(ParametersKey, &ValueName, &ByteLength, NULL); 216 status = WdfRegistryQueryUnicodeString(ParametersKey, &ValueName, &ByteLength, NULL);
214 if (status != STATUS_BUFFER_OVERFLOW && !NT_SUCCESS(status)) { 217 if (status != STATUS_BUFFER_OVERFLOW && !NT_SUCCESS(status)) {
215 KdPrint(("Could not obtain the length of the image file name from the registry\n")); 218 KdPrint(("Could not obtain the length of the image file name from the registry\n"));
216 return status; 219 return status;
217 } 220 }
218 221
219 Buffer = ExAllocatePoolWithTag(NonPagedPool, ByteLength, TAG); 222 Buffer = ExAllocatePoolWithTag(NonPagedPool, ByteLength, TAG);
220 RtlInitEmptyUnicodeString(&RegValue, Buffer, ByteLength); 223 RtlInitEmptyUnicodeString(&RegValue, Buffer, ByteLength);
221 224
222 status = WdfRegistryQueryUnicodeString(ParametersKey, &ValueName, NULL, &RegValue); 225 status = WdfRegistryQueryUnicodeString(ParametersKey, &ValueName, NULL, &RegValue);
223 if (!NT_SUCCESS(status)) { 226 if (!NT_SUCCESS(status)) {
224 KdPrint(("Could not read the image file name from the registry\n")); 227 KdPrint(("Could not read the image file name from the registry\n"));
225 return status; 228 return status;
226 } 229 }
227 230
228 WdfRegistryClose(ParametersKey); 231 WdfRegistryClose(ParametersKey);
229 232
230 /* Add the required "\DosDevices" prefix */ 233 /* Add the required "\DosDevices" prefix */
231 PrefixLength = wcslen(Prefix) * sizeof(WCHAR); 234 PrefixLength = wcslen(Prefix) * sizeof(WCHAR);
232 Buffer = ExAllocatePoolWithTag(NonPagedPool, ByteLength + PrefixLength, TAG); 235 Buffer = ExAllocatePoolWithTag(NonPagedPool, ByteLength + PrefixLength, TAG);
233 RtlInitEmptyUnicodeString(&FileToMount, Buffer, ByteLength + PrefixLength); 236 RtlInitEmptyUnicodeString(&FileToMount, Buffer, ByteLength + PrefixLength);
234 status = RtlUnicodeStringCopyString(&FileToMount, Prefix); 237 status = RtlUnicodeStringCopyString(&FileToMount, Prefix);
235 if (!NT_SUCCESS(status)) { 238 if (!NT_SUCCESS(status)) {
236 KdPrint(("String copy operation failed\n")); 239 KdPrint(("String copy operation failed\n"));
237 return status; 240 return status;
238 } 241 }
239 status = RtlUnicodeStringCat(&FileToMount, &RegValue); 242 status = RtlUnicodeStringCat(&FileToMount, &RegValue);
240 if (!NT_SUCCESS(status)) { 243 if (!NT_SUCCESS(status)) {
241 KdPrint(("String copy operation failed\n")); 244 KdPrint(("String copy operation failed\n"));
242 return status; 245 return status;
243 } 246 }
244 247
245 ExFreePoolWithTag(RegValue.Buffer, TAG); 248 ExFreePoolWithTag(RegValue.Buffer, TAG);
246 #else 249 #else
247 KdPrint(("Using the image file name that is compiled into the driver\n")); 250 KdPrint(("Using the image file name that is compiled into the driver\n"));
248 251
249 /* Use the fixed image file name */ 252 /* Use the fixed image file name */
250 RtlInitUnicodeString(&FileToMount, imagename); 253 RtlInitUnicodeString(&FileToMount, imagename);
251 #endif 254 #endif
252 255
253 FileSize.QuadPart = 100 * 1024 * 1024; 256 FileSize.QuadPart = 100 * 1024 * 1024;
254 KdPrint(("Image file name: %wZ\n", &FileToMount)); 257 KdPrint(("Image file name: %wZ\n", &FileToMount));
255 status = GhostFileIoMountImage(Device, &FileToMount, &FileSize); 258 status = GhostFileIoMountImage(Device, &FileToMount, &FileSize);
256 259
257 #ifndef USE_FIXED_IMAGE_NAME 260 #ifndef USE_FIXED_IMAGE_NAME
258 ExFreePoolWithTag(FileToMount.Buffer, TAG); 261 ExFreePoolWithTag(FileToMount.Buffer, TAG);
259 #endif 262 #endif
260 263
261 return status; 264 return status;
262 } 265 }
263 266
264 267
265 /* 268 /*
266 * GhostBusDeviceControl handles I/O request packages with device control codes, 269 * GhostBusDeviceControl handles I/O request packages with device control codes for the bus FDO,
267 * that is especially user-defined codes controlling child enumeration. 270 * that is especially user-defined codes controlling child enumeration.
268 * 271 *
269 * TODO: Move request handling to separate functions. 272 * TODO: Move request handling to separate functions.
270 */ 273 */
271 VOID GhostBusDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, 274 VOID GhostBusDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength,
272 size_t InputBufferLength, ULONG IoControlCode) 275 size_t InputBufferLength, ULONG IoControlCode)
273 { 276 {
274 GHOST_DRIVE_IDENTIFICATION Identification; 277 GHOST_DRIVE_IDENTIFICATION Identification;
275 WDFCHILDLIST ChildList; 278 WDFCHILDLIST ChildList;
276 PLONG pID; 279 PLONG pID;
277 LONG ID; 280 LONG ID;
278 ULONG_PTR info = 0; 281 ULONG_PTR info = 0;
279 NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; 282 NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
280 283
281 KdPrint(("DeviceControl called\n")); 284 KdPrint(("DeviceControl called\n"));
282 285
283 switch (IoControlCode) { 286 switch (IoControlCode) {
284 287
285 case IOCTL_GHOST_BUS_ENABLE_DRIVE: 288 case IOCTL_GHOST_BUS_ENABLE_DRIVE:
286 KdPrint(("Enabling GhostDrive\n")); 289 KdPrint(("Enabling GhostDrive\n"));
287 290
288 // Retrieve the drive's ID from the request's input buffer 291 // Retrieve the drive's ID from the request's input buffer
289 status = WdfRequestRetrieveInputBuffer(Request, sizeof(LONG), &pID, NULL); 292 status = WdfRequestRetrieveInputBuffer(Request, sizeof(LONG), &pID, NULL);
290 if (!NT_SUCCESS(status)) { 293 if (!NT_SUCCESS(status)) {
291 KdPrint(("Could not retrieve ID\n")); 294 KdPrint(("Could not retrieve ID\n"));
292 status = STATUS_INVALID_PARAMETER; 295 status = STATUS_INVALID_PARAMETER;
293 break; 296 break;
294 } 297 }
295 298
296 // Inform the PnP manager of a new device being plugged in 299 // Inform the PnP manager of a new device being plugged in
297 ChildList = WdfFdoGetDefaultChildList(WdfIoQueueGetDevice(Queue)); 300 ChildList = WdfFdoGetDefaultChildList(WdfIoQueueGetDevice(Queue));
298 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Identification.Header, sizeof(Identification)); 301 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Identification.Header, sizeof(Identification));
299 302
300 // If the requested device ID is the special value -1, then we look for a free device ID 303 // If the requested device ID is the special value -1, then we look for a free device ID
301 ID = *pID; 304 ID = *pID;
302 if (ID == -1) { 305 if (ID == -1) {
303 int i; 306 int i;
304 WDF_CHILD_LIST_ITERATOR Iterator; 307 WDF_CHILD_LIST_ITERATOR Iterator;
305 WDF_CHILD_RETRIEVE_INFO ChildInfo; 308 WDF_CHILD_RETRIEVE_INFO ChildInfo;
306 WDFDEVICE Device; 309 WDFDEVICE Device;
307 310
308 WDF_CHILD_RETRIEVE_INFO_INIT(&ChildInfo, &Identification.Header); 311 WDF_CHILD_RETRIEVE_INFO_INIT(&ChildInfo, &Identification.Header);
309 WDF_CHILD_LIST_ITERATOR_INIT(&Iterator, WdfRetrieveAllChildren); 312 WDF_CHILD_LIST_ITERATOR_INIT(&Iterator, WdfRetrieveAllChildren);
310 WdfChildListBeginIteration(ChildList, &Iterator); 313 WdfChildListBeginIteration(ChildList, &Iterator);
311 314
312 for (i = 0; i < GHOST_DRIVE_MAX_NUM; i++) { 315 for (i = 0; i < GHOST_DRIVE_MAX_NUM; i++) {
313 Identification.Id = i; 316 Identification.Id = i;
314 317
315 status = WdfChildListRetrieveNextDevice(ChildList, &Iterator, &Device, &ChildInfo); 318 status = WdfChildListRetrieveNextDevice(ChildList, &Iterator, &Device, &ChildInfo);
316 if (status == STATUS_NO_MORE_ENTRIES) { 319 if (status == STATUS_NO_MORE_ENTRIES) {
317 KdPrint(("Device ID %d is free\n", i)); 320 KdPrint(("Device ID %d is free\n", i));
318 ID = i; 321 ID = i;
319 break; 322 break;
320 } 323 }
321 else if (!NT_SUCCESS(status)) { 324 else if (!NT_SUCCESS(status)) {
322 KdPrint(("Could not retrieve child device\n")); 325 KdPrint(("Could not retrieve child device\n"));
323 } 326 }
324 } 327 }
325 328
326 WdfChildListEndIteration(ChildList, &Iterator); 329 WdfChildListEndIteration(ChildList, &Iterator);
327 330
328 // If we didn't find a free ID, then fail 331 // If we didn't find a free ID, then fail
329 if (ID == -1) { 332 if (ID == -1) {
330 KdPrint(("No free ID\n")); 333 KdPrint(("No free ID\n"));
331 status = STATUS_UNSUCCESSFUL; 334 status = STATUS_UNSUCCESSFUL;
332 break; 335 break;
333 } 336 }
334 } 337 }
335 338
336 Identification.Id = ID; 339 Identification.Id = ID;
337 340
338 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(ChildList, &Identification.Header, NULL); 341 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(ChildList, &Identification.Header, NULL);
339 if (!NT_SUCCESS(status)) { 342 if (!NT_SUCCESS(status)) {
340 KdPrint(("Could not add child to child list\n")); 343 KdPrint(("Could not add child to child list\n"));
341 status = STATUS_INTERNAL_ERROR; 344 status = STATUS_INTERNAL_ERROR;
342 break; 345 break;
343 } 346 }
344 347
345 // Write the device's ID to the output buffer 348 // Write the device's ID to the output buffer
346 status = WdfRequestRetrieveInputBuffer(Request, sizeof(LONG), &pID, NULL); 349 status = WdfRequestRetrieveInputBuffer(Request, sizeof(LONG), &pID, NULL);
347 if (!NT_SUCCESS(status)) { 350 if (!NT_SUCCESS(status)) {
348 KdPrint(("Could not retrieve the output buffer\n")); 351 KdPrint(("Could not retrieve the output buffer\n"));
349 break; 352 break;
350 } 353 }
351 354
352 *pID = ID; 355 *pID = ID;
353 info = sizeof(LONG); 356 info = sizeof(LONG);
354 357
355 status = STATUS_SUCCESS; 358 status = STATUS_SUCCESS;
356 break; 359 break;
357 360
358 case IOCTL_GHOST_BUS_DISABLE_DRIVE: 361 case IOCTL_GHOST_BUS_DISABLE_DRIVE:
362 {
363 WDFDEVICE ChildPdo;
364 WDF_CHILD_RETRIEVE_INFO ChildInfo;
365
359 KdPrint(("Disabling GhostDrive\n")); 366 KdPrint(("Disabling GhostDrive\n"));
360 367
361 // Retrieve the drive's ID from the request's input buffer 368 // Retrieve the drive's ID from the request's input buffer
362 status = WdfRequestRetrieveInputBuffer(Request, sizeof(LONG), &pID, NULL); 369 status = WdfRequestRetrieveInputBuffer(Request, sizeof(LONG), &pID, NULL);
363 if (!NT_SUCCESS(status)) { 370 if (!NT_SUCCESS(status)) {
364 KdPrint(("Could not retrieve ID\n")); 371 KdPrint(("Could not retrieve ID\n"));
365 status = STATUS_INVALID_PARAMETER; 372 status = STATUS_INVALID_PARAMETER;
366 break; 373 break;
367 } 374 }
368 375
369 // Inform the PnP manager that a child device has been removed 376 // Inform the PnP manager that a child device has been removed
370 ChildList = WdfFdoGetDefaultChildList(WdfIoQueueGetDevice(Queue)); 377 ChildList = WdfFdoGetDefaultChildList(WdfIoQueueGetDevice(Queue));
371 378
372 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Identification.Header, sizeof(Identification)); 379 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Identification.Header, sizeof(Identification));
373 Identification.Id = *pID; 380 Identification.Id = *pID;
381
382 // Obtain the child's PDO to send it an umount command
383 WDF_CHILD_RETRIEVE_INFO_INIT(&ChildInfo, &Identification.Header);
384 ChildPdo = WdfChildListRetrievePdo(ChildList, &ChildInfo);
385 if (ChildPdo == NULL) {
386 KdPrint(("Bus: Couldn't obtain the drive PDO\n"));
387 }
374 388
375 /*status = WdfChildListUpdateChildDescriptionAsMissing(ChildList, &Identification.Header); 389 /*status = WdfChildListUpdateChildDescriptionAsMissing(ChildList, &Identification.Header);
376 if (!NT_SUCCESS(status)) { 390 if (!NT_SUCCESS(status)) {
377 KdPrint(("Could not remove child from child list\n")); 391 KdPrint(("Could not remove child from child list\n"));
378 }*/ 392 }*/
379 393
380 if (!WdfChildListRequestChildEject(ChildList, &Identification.Header)) { 394 if (!WdfChildListRequestChildEject(ChildList, &Identification.Header)) {
381 KdPrint(("Could not eject child device\n")); 395 KdPrint(("Could not eject child device\n"));
382 status = STATUS_INTERNAL_ERROR; 396 status = STATUS_INTERNAL_ERROR;
383 break; 397 break;
384 } 398 }
385 399
386 status = STATUS_SUCCESS; 400 status = STATUS_SUCCESS;
387 break; 401 break;
402 }
388 403
389 default: 404 default:
390 405
391 break; 406 break;
392 407
393 } 408 }
394 409
395 WdfRequestCompleteWithInformation(Request, status, info); 410 WdfRequestCompleteWithInformation(Request, status, info);
396 } 411 }
397 412
398 413
399 NTSTATUS GhostDriveQueryRemove(WDFDEVICE Device) { 414 NTSTATUS GhostDrivePdoQueryRemove(WDFDEVICE Device) {
400 PGHOST_DRIVE_CONTEXT Context; 415 PGHOST_DRIVE_PDO_CONTEXT Context;
401 416
402 KdPrint(("QueryRemove\n")); 417 KdPrint(("QueryRemove\n"));
403 418
404 Context = GhostDriveGetContext(Device); 419 Context = GhostDrivePdoGetContext(Device);
405 KdPrint(("Draining the writer info queue...\n")); 420 KdPrint(("Draining the writer info queue...\n"));
406 WdfIoQueuePurgeSynchronously(Context->WriterInfoQueue); 421 WdfIoQueuePurgeSynchronously(Context->WriterInfoQueue);
407 422
408 if (!NT_SUCCESS(GhostFileIoUmountImage(Device))) { 423 if (!NT_SUCCESS(GhostFileIoUmountImage(Device))) {
409 KdPrint(("Could not unmount the image\n")); 424 KdPrint(("Could not unmount the image\n"));
410 } 425 }
411 426
412 return STATUS_SUCCESS; 427 return STATUS_SUCCESS;
413 } 428 }
414 429
415 430
416 /* 431 /*
417 * The Windows Driver Framework calls this function whenever a new child device has to be created. 432 * The Windows Driver Framework calls this function whenever a new child device has to be created.
418 * We create the device object and set its properties. Most importantly, we mark the device as a 433 * We create the device object and set its properties. Most importantly, we mark the device as a
419 * removable one. 434 * removable one.
420 */ 435 */
421 NTSTATUS GhostBusChildListCreateDevice(WDFCHILDLIST ChildList, 436 NTSTATUS GhostBusChildListCreateDevice(WDFCHILDLIST ChildList,
422 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, 437 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
423 PWDFDEVICE_INIT ChildInit) 438 PWDFDEVICE_INIT ChildInit)
424 { 439 {
425 DECLARE_CONST_UNICODE_STRING(DeviceID, GHOST_DRIVE_DEVICE_ID); 440 DECLARE_CONST_UNICODE_STRING(DeviceID, GHOST_DRIVE_DEVICE_ID);
426 DECLARE_CONST_UNICODE_STRING(DeviceDescription, GHOST_DRIVE_DESCRIPTION); 441 DECLARE_CONST_UNICODE_STRING(DeviceDescription, GHOST_DRIVE_DESCRIPTION);
427 DECLARE_CONST_UNICODE_STRING(DeviceLocation, GHOST_DRIVE_LOCATION); 442 DECLARE_CONST_UNICODE_STRING(DeviceLocation, GHOST_DRIVE_LOCATION);
428 DECLARE_UNICODE_STRING_SIZE(InstanceID, 2 * sizeof(WCHAR)); // the ID is only one character 443 DECLARE_UNICODE_STRING_SIZE(InstanceID, 2 * sizeof(WCHAR)); // the ID is only one character
429 DECLARE_CONST_UNICODE_STRING(DeviceSDDL, DEVICE_SDDL_STRING); 444 DECLARE_CONST_UNICODE_STRING(DeviceSDDL, DEVICE_SDDL_STRING);
430 WDFDEVICE ChildDevice; 445 WDFDEVICE ChildDevice;
431 WDF_DEVICE_PNP_CAPABILITIES PnpCaps; 446 WDF_DEVICE_PNP_CAPABILITIES PnpCaps;
432 PGHOST_DRIVE_IDENTIFICATION Identification = (PGHOST_DRIVE_IDENTIFICATION)IdentificationDescription; 447 PGHOST_DRIVE_IDENTIFICATION Identification = (PGHOST_DRIVE_IDENTIFICATION)IdentificationDescription;
433 NTSTATUS status; 448 NTSTATUS status;
434 WDF_OBJECT_ATTRIBUTES DeviceAttr; 449 WDF_OBJECT_ATTRIBUTES DeviceAttr;
435 PGHOST_DRIVE_CONTEXT Context; 450 PGHOST_DRIVE_PDO_CONTEXT Context;
436 ULONG ID; 451 ULONG ID;
437 WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks; 452 WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerCallbacks;
453 WDF_OBJECT_ATTRIBUTES QueueAttr;
454 WDF_IO_QUEUE_CONFIG QueueConfig;
438 455
439 KdPrint(("ChildListCreateDevice called\n")); 456 KdPrint(("ChildListCreateDevice called\n"));
440 ID = ((PGHOST_DRIVE_IDENTIFICATION) IdentificationDescription)->Id; 457 ID = ((PGHOST_DRIVE_IDENTIFICATION) IdentificationDescription)->Id;
441 458
442 // Define the context for the new device 459 // Define the context for the new device
443 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DeviceAttr, GHOST_DRIVE_CONTEXT); 460 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DeviceAttr, GHOST_DRIVE_PDO_CONTEXT);
444 DeviceAttr.EvtCleanupCallback = GhostDriveDeviceCleanup; 461 DeviceAttr.EvtCleanupCallback = GhostDriveDeviceCleanup;
445 DeviceAttr.ExecutionLevel = WdfExecutionLevelPassive; 462 DeviceAttr.ExecutionLevel = WdfExecutionLevelPassive;
446 463
447 /* 464 /*
448 // begin tmp 465 // begin tmp
449 { 466 {
450 DECLARE_CONST_UNICODE_STRING(GenDisk, L"GenDisk"); 467 DECLARE_CONST_UNICODE_STRING(GenDisk, L"GenDisk");
451 468
452 // Set the device ID 469 // Set the device ID
453 status = WdfPdoInitAssignDeviceID(ChildInit, &GenDisk); 470 status = WdfPdoInitAssignDeviceID(ChildInit, &GenDisk);
454 if (!NT_SUCCESS(status)) { 471 if (!NT_SUCCESS(status)) {
455 KdPrint(("Could not set the child device's ID\n")); 472 KdPrint(("Could not set the child device's ID\n"));
456 WdfDeviceInitFree(ChildInit); 473 WdfDeviceInitFree(ChildInit);
457 return status; 474 return status;
458 } 475 }
459 476
460 // Set the hardware ID to the same value 477 // Set the hardware ID to the same value
461 status = WdfPdoInitAddHardwareID(ChildInit, &GenDisk); 478 status = WdfPdoInitAddHardwareID(ChildInit, &GenDisk);
462 if (!NT_SUCCESS(status)) { 479 if (!NT_SUCCESS(status)) {
463 KdPrint(("Could not set the child device's hardware ID\n")); 480 KdPrint(("Could not set the child device's hardware ID\n"));
464 WdfDeviceInitFree(ChildInit); 481 WdfDeviceInitFree(ChildInit);
465 return status; 482 return status;
466 } 483 }
467 } 484 }
468 // end tmp 485 // end tmp
469 */ 486 */
470 487
471 // Set the device ID 488 // Set the device ID
472 status = WdfPdoInitAssignDeviceID(ChildInit, &DeviceID); 489 status = WdfPdoInitAssignDeviceID(ChildInit, &DeviceID);
473 if (!NT_SUCCESS(status)) { 490 if (!NT_SUCCESS(status)) {
474 KdPrint(("Could not set the child device's ID\n")); 491 KdPrint(("Could not set the child device's ID\n"));
475 WdfDeviceInitFree(ChildInit); 492 WdfDeviceInitFree(ChildInit);
476 return status; 493 return status;
477 } 494 }
478 495
479 // Set the hardware ID to the same value 496 // Set the hardware ID to the same value
480 status = WdfPdoInitAddHardwareID(ChildInit, &DeviceID); 497 status = WdfPdoInitAddHardwareID(ChildInit, &DeviceID);
481 if (!NT_SUCCESS(status)) { 498 if (!NT_SUCCESS(status)) {
482 KdPrint(("Could not set the child device's hardware ID\n")); 499 KdPrint(("Could not set the child device's hardware ID\n"));
483 WdfDeviceInitFree(ChildInit); 500 WdfDeviceInitFree(ChildInit);
484 return status; 501 return status;
485 } 502 }
486 503
487 // Set the instance ID 504 // Set the instance ID
488 status = RtlIntegerToUnicodeString(Identification->Id, 10, &InstanceID); 505 status = RtlIntegerToUnicodeString(Identification->Id, 10, &InstanceID);
489 if (!NT_SUCCESS(status)) { 506 if (!NT_SUCCESS(status)) {
490 KdPrint(("Could not create a string from the GhostDrive's ID\n")); 507 KdPrint(("Could not create a string from the GhostDrive's ID\n"));
491 WdfDeviceInitFree(ChildInit); 508 WdfDeviceInitFree(ChildInit);
492 return status; 509 return status;
493 } 510 }
494 511
495 status = WdfPdoInitAssignInstanceID(ChildInit, &InstanceID); 512 status = WdfPdoInitAssignInstanceID(ChildInit, &InstanceID);
496 if (!NT_SUCCESS(status)) { 513 if (!NT_SUCCESS(status)) {
497 KdPrint(("Could not assign the instance ID\n")); 514 KdPrint(("Could not assign the instance ID\n"));
498 WdfDeviceInitFree(ChildInit); 515 WdfDeviceInitFree(ChildInit);
499 return status; 516 return status;
500 } 517 }
501 518
502 // Add a description and set default locale to United States English 519 // Add a description and set default locale to United States English
503 WdfPdoInitSetDefaultLocale(ChildInit, 0x409); 520 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
504 status = WdfPdoInitAddDeviceText(ChildInit, &DeviceDescription, &DeviceLocation, 0x409); 521 status = WdfPdoInitAddDeviceText(ChildInit, &DeviceDescription, &DeviceLocation, 0x409);
505 if (!NT_SUCCESS(status)) { 522 if (!NT_SUCCESS(status)) {
506 KdPrint(("Could not set a description for the child device\n")); 523 KdPrint(("Could not set a description for the child device\n"));
507 WdfDeviceInitFree(ChildInit); 524 WdfDeviceInitFree(ChildInit);
508 return status; 525 return status;
509 } 526 }
510 527
511 // Set device properties 528 // Set device properties
512 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_DISK); 529 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_DISK);
513 WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect); 530 WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);
514 WdfDeviceInitSetExclusive(ChildInit, FALSE); 531 WdfDeviceInitSetExclusive(ChildInit, FALSE);
515 status = WdfDeviceInitAssignSDDLString(ChildInit, &DeviceSDDL); 532 status = WdfDeviceInitAssignSDDLString(ChildInit, &DeviceSDDL);
516 if (!NT_SUCCESS(status)) { 533 if (!NT_SUCCESS(status)) {
517 KdPrint(("Could not assign an SDDL string\n")); 534 KdPrint(("Could not assign an SDDL string\n"));
518 return status; 535 return status;
519 } 536 }
520 537
521 // Register callbacks 538 // Register callbacks
522 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks); 539 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerCallbacks);
523 PnpPowerCallbacks.EvtDeviceQueryRemove = GhostDriveQueryRemove; 540 PnpPowerCallbacks.EvtDeviceQueryRemove = GhostDrivePdoQueryRemove;
524 WdfDeviceInitSetPnpPowerEventCallbacks(ChildInit, &PnpPowerCallbacks); 541 WdfDeviceInitSetPnpPowerEventCallbacks(ChildInit, &PnpPowerCallbacks);
525 542
526 // Create the device 543 // Create the device
527 status = WdfDeviceCreate(&ChildInit, &DeviceAttr, &ChildDevice); 544 status = WdfDeviceCreate(&ChildInit, &DeviceAttr, &ChildDevice);
528 if (!NT_SUCCESS(status)) { 545 if (!NT_SUCCESS(status)) {
529 KdPrint(("Could not create the child device\n")); 546 KdPrint(("Could not create the child device\n"));
530 return status; 547 return status;
531 } 548 }
532 549
533 // Report PnP capabilities - this is the crucial part of the whole story, because here we can 550 // Report PnP capabilities - this is the crucial part of the whole story, because here we can
534 // make the device removable 551 // make the device removable
535 WDF_DEVICE_PNP_CAPABILITIES_INIT(&PnpCaps); 552 WDF_DEVICE_PNP_CAPABILITIES_INIT(&PnpCaps);
536 PnpCaps.LockSupported = WdfFalse; 553 PnpCaps.LockSupported = WdfFalse;
537 PnpCaps.EjectSupported = WdfTrue; 554 PnpCaps.EjectSupported = WdfTrue;
538 PnpCaps.Removable = WdfTrue; 555 PnpCaps.Removable = WdfTrue;
539 PnpCaps.DockDevice = WdfFalse; 556 PnpCaps.DockDevice = WdfFalse;
540 PnpCaps.UniqueID = WdfFalse; // the ID is only unique to the bus 557 PnpCaps.UniqueID = WdfFalse; // the ID is only unique to the bus
541 PnpCaps.SilentInstall = WdfFalse; // maybe change that later 558 PnpCaps.SilentInstall = WdfFalse; // maybe change that later
542 PnpCaps.SurpriseRemovalOK = WdfFalse; // same here 559 PnpCaps.SurpriseRemovalOK = WdfFalse; // same here
543 PnpCaps.HardwareDisabled = WdfFalse; 560 PnpCaps.HardwareDisabled = WdfFalse;
544 PnpCaps.NoDisplayInUI = WdfFalse; 561 PnpCaps.NoDisplayInUI = WdfFalse;
545 PnpCaps.UINumber = Identification->Id; 562 PnpCaps.UINumber = Identification->Id;
546 WdfDeviceSetPnpCapabilities(ChildDevice, &PnpCaps); 563 WdfDeviceSetPnpCapabilities(ChildDevice, &PnpCaps);
547 564
548 // Initialize the device extension 565 // Initialize the device extension
549 Context = GhostDriveGetContext(ChildDevice); 566 Context = GhostDrivePdoGetContext(ChildDevice);
550 Context->ImageMounted = FALSE; 567 Context->ImageMounted = FALSE;
551 Context->ImageWritten = FALSE; 568 Context->ImageWritten = FALSE;
552 Context->ID = ID; 569 Context->ID = ID;
553 Context->ChangeCount = 0; 570 Context->ChangeCount = 0;
554 Context->WriterInfoCount = 0; 571 Context->WriterInfoCount = 0;
555 Context->WriterInfo = NULL; 572 Context->WriterInfo = NULL;
556 573
557 // begin tmp 574 // Set up the device's I/O queue to handle I/O requests
558 { 575 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&QueueConfig, WdfIoQueueDispatchSequential);
559 WDF_OBJECT_ATTRIBUTES QueueAttr; 576 QueueConfig.EvtIoRead = GhostFileIoRead;
560 WDF_IO_QUEUE_CONFIG QueueConfig; 577 QueueConfig.EvtIoWrite = GhostFileIoWrite;
561 578 QueueConfig.EvtIoDeviceControl = GhostDeviceControlDispatch;
562 // Set up the device's I/O queue to handle I/O requests
563 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&QueueConfig, WdfIoQueueDispatchSequential);
564 QueueConfig.EvtIoRead = GhostFileIoRead;
565 QueueConfig.EvtIoWrite = GhostFileIoWrite;
566 QueueConfig.EvtIoDeviceControl = GhostDeviceControlDispatch;
567 579
568 WDF_OBJECT_ATTRIBUTES_INIT(&QueueAttr); 580 WDF_OBJECT_ATTRIBUTES_INIT(&QueueAttr);
569 QueueAttr.ExecutionLevel = WdfExecutionLevelPassive; // necessary to collect writer information 581 QueueAttr.ExecutionLevel = WdfExecutionLevelPassive; // necessary to collect writer information
570 582
571 status = WdfIoQueueCreate(ChildDevice, &QueueConfig, &QueueAttr, NULL); 583 status = WdfIoQueueCreate(ChildDevice, &QueueConfig, &QueueAttr, NULL);
572 if (!NT_SUCCESS(status)) { 584 if (!NT_SUCCESS(status)) {
573 KdPrint(("Could not create the default I/O queue\n")); 585 KdPrint(("Could not create the default I/O queue\n"));
574 return status; 586 return status;
575 } 587 }
576 588
577 // Create a separate queue for blocking writer info requests 589 // Create a separate queue for blocking writer info requests
578 WDF_IO_QUEUE_CONFIG_INIT(&QueueConfig, WdfIoQueueDispatchManual); 590 WDF_IO_QUEUE_CONFIG_INIT(&QueueConfig, WdfIoQueueDispatchManual);
579 591
580 status = WdfIoQueueCreate(ChildDevice, &QueueConfig, &QueueAttr, &Context->WriterInfoQueue); 592 status = WdfIoQueueCreate(ChildDevice, &QueueConfig, &QueueAttr, &Context->WriterInfoQueue);
581 if (!NT_SUCCESS(status)) { 593 if (!NT_SUCCESS(status)) {
582 KdPrint(("Could not create the I/O queue for writer info requests\n")); 594 KdPrint(("Could not create the I/O queue for writer info requests\n"));
583 return status; 595 return status;
584 }
585 } 596 }
586 // end tmp
587 597
588 // Mount the image 598 // Mount the image
589 status = GhostDriveInitImage(ChildDevice, ID); 599 status = GhostDrivePdoInitImage(ChildDevice, ID);
590 if (!NT_SUCCESS(status)) { 600 if (!NT_SUCCESS(status)) {
591 KdPrint(("Mount failed\n")); 601 KdPrint(("Mount failed\n"));
592 return status; 602 return status;
593 } 603 }
594 604
595 return STATUS_SUCCESS; 605 return STATUS_SUCCESS;
596 } 606 }
Powered by Google Project Hosting