[project] Rename winvblock__uint32 back to UINT32
[people/sha0/winvblock.git] / src / winvblock / disk / dev_ctl.c
1 /**
2  * Copyright (C) 2009-2011, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
3  * Copyright 2006-2008, V.
4  * For WinAoE contact information, see http://winaoe.org/
5  *
6  * This file is part of WinVBlock, derived from WinAoE.
7  *
8  * WinVBlock is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * WinVBlock is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 /**
23  * @file
24  *
25  * Disk Device Control IRP handling.
26  */
27
28 #include <ntddk.h>
29 #include <scsi.h>
30 #include <srb.h>
31 #include <ntdddisk.h>
32 #include <ntddscsi.h>
33 #include <ntddstor.h>
34 #include <ntddvol.h>
35 #include <mountdev.h>
36
37 #include "winvblock.h"
38 #include "portable.h"
39 #include "driver.h"
40 #include "bus.h"
41 #include "device.h"
42 #include "disk.h"
43 #include "debug.h"
44
45 /* Forward declarations. */
46 static WV_F_DEV_DISPATCH disk_dev_ctl__storage_query_prop_;
47 static WV_F_DEV_DISPATCH disk_dev_ctl__get_geom_;
48 static WV_F_DEV_DISPATCH disk_dev_ctl__scsi_get_address_;
49
50 static NTSTATUS STDCALL disk_dev_ctl__storage_query_prop_(
51     IN WV_SP_DEV_T dev,
52     IN PIRP irp
53   ) {
54     WV_SP_DISK_T disk;
55     PIO_STACK_LOCATION io_stack_loc = IoGetCurrentIrpStackLocation(irp);
56     NTSTATUS status = STATUS_INVALID_PARAMETER;
57     PSTORAGE_PROPERTY_QUERY storage_prop_query = irp->AssociatedIrp.SystemBuffer;
58     UINT32 copy_size;
59     STORAGE_ADAPTER_DESCRIPTOR storage_adapter_desc;
60     STORAGE_DEVICE_DESCRIPTOR storage_dev_desc;
61
62     disk = disk__get_ptr(dev);
63     if (
64         storage_prop_query->PropertyId == StorageAdapterProperty &&
65         storage_prop_query->QueryType == PropertyStandardQuery
66       ) {
67         copy_size = (
68             io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength <
69             sizeof (STORAGE_ADAPTER_DESCRIPTOR) ?
70             io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength :
71             sizeof (STORAGE_ADAPTER_DESCRIPTOR)
72           );
73         storage_adapter_desc.Version = sizeof (STORAGE_ADAPTER_DESCRIPTOR);
74         storage_adapter_desc.Size = sizeof (STORAGE_ADAPTER_DESCRIPTOR);
75         storage_adapter_desc.MaximumTransferLength =
76           disk__max_xfer_len(disk);
77         #if 0
78         storage_adapter_desc.MaximumTransferLength = SECTORSIZE * POOLSIZE;
79         #endif
80         storage_adapter_desc.MaximumPhysicalPages = (UINT32) -1;
81         storage_adapter_desc.AlignmentMask = 0;
82         storage_adapter_desc.AdapterUsesPio = TRUE;
83         storage_adapter_desc.AdapterScansDown = FALSE;
84         storage_adapter_desc.CommandQueueing = FALSE;
85         storage_adapter_desc.AcceleratedTransfer = FALSE;
86         storage_adapter_desc.BusType = BusTypeScsi;
87         RtlCopyMemory(
88             irp->AssociatedIrp.SystemBuffer,
89             &storage_adapter_desc,
90             copy_size
91           );
92         irp->IoStatus.Information = (ULONG_PTR) copy_size;
93         status = STATUS_SUCCESS;
94       }
95
96     if (
97         storage_prop_query->PropertyId == StorageDeviceProperty &&
98         storage_prop_query->QueryType == PropertyStandardQuery
99       ) {
100         copy_size = (
101             io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength <
102             sizeof (STORAGE_DEVICE_DESCRIPTOR) ?
103             io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength :
104             sizeof (STORAGE_DEVICE_DESCRIPTOR)
105           );
106         storage_dev_desc.Version = sizeof (STORAGE_DEVICE_DESCRIPTOR);
107         storage_dev_desc.Size = sizeof (STORAGE_DEVICE_DESCRIPTOR);
108         storage_dev_desc.DeviceType = DIRECT_ACCESS_DEVICE;
109         storage_dev_desc.DeviceTypeModifier = 0;
110         storage_dev_desc.RemovableMedia = WvDiskIsRemovable[disk->Media];
111         storage_dev_desc.CommandQueueing = FALSE;
112         storage_dev_desc.VendorIdOffset = 0;
113         storage_dev_desc.ProductIdOffset = 0;
114         storage_dev_desc.ProductRevisionOffset = 0;
115         storage_dev_desc.SerialNumberOffset = 0;
116         storage_dev_desc.BusType = BusTypeScsi;
117         storage_dev_desc.RawPropertiesLength = 0;
118         RtlCopyMemory(
119             irp->AssociatedIrp.SystemBuffer,
120             &storage_dev_desc,
121             copy_size
122           );
123         irp->IoStatus.Information = (ULONG_PTR) copy_size;
124         status = STATUS_SUCCESS;
125       }
126
127     if (status == STATUS_INVALID_PARAMETER) {
128         DBG(
129             "!!Invalid IOCTL_STORAGE_QUERY_PROPERTY "
130               "(PropertyId: %08x / QueryType: %08x)!!\n",
131             storage_prop_query->PropertyId,
132             storage_prop_query->QueryType
133           );
134       }
135     return status;
136   }
137
138 static NTSTATUS STDCALL disk_dev_ctl__get_geom_(
139     IN WV_SP_DEV_T dev,
140     IN PIRP irp
141   ) {
142     PIO_STACK_LOCATION io_stack_loc = IoGetCurrentIrpStackLocation(irp);
143     UINT32 copy_size;
144     DISK_GEOMETRY disk_geom;
145     WV_SP_DISK_T disk;
146
147     copy_size = (
148         io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength <
149         sizeof (DISK_GEOMETRY) ?
150         io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength :
151         sizeof (DISK_GEOMETRY)
152       );
153     disk_geom.MediaType = FixedMedia;
154     disk = disk__get_ptr(dev);
155     disk_geom.Cylinders.QuadPart = disk->Cylinders;
156     disk_geom.TracksPerCylinder = disk->Heads;
157     disk_geom.SectorsPerTrack = disk->Sectors;
158     disk_geom.BytesPerSector = disk->SectorSize;
159     RtlCopyMemory(
160         irp->AssociatedIrp.SystemBuffer,
161         &disk_geom,
162         copy_size
163       );
164     irp->IoStatus.Information = (ULONG_PTR) copy_size;
165     return STATUS_SUCCESS;
166   }
167
168 static NTSTATUS STDCALL disk_dev_ctl__scsi_get_address_(
169     IN WV_SP_DEV_T dev,
170     IN PIRP irp
171   ) {
172     PIO_STACK_LOCATION io_stack_loc= IoGetCurrentIrpStackLocation(irp);
173     UINT32 copy_size;
174     SCSI_ADDRESS scsi_address;
175
176     copy_size = (
177         io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength <
178         sizeof (SCSI_ADDRESS) ?
179         io_stack_loc->Parameters.DeviceIoControl.OutputBufferLength :
180         sizeof (SCSI_ADDRESS)
181       );
182     scsi_address.Length = sizeof (SCSI_ADDRESS);
183     scsi_address.PortNumber = 0;
184     scsi_address.PathId = 0;
185     scsi_address.TargetId = (UCHAR) dev->DevNum;
186     scsi_address.Lun = 0;
187     RtlCopyMemory(
188         irp->AssociatedIrp.SystemBuffer,
189         &scsi_address,
190         copy_size
191       );
192     irp->IoStatus.Information = (ULONG_PTR) copy_size;
193     return STATUS_SUCCESS;
194   }
195
196 NTSTATUS STDCALL disk_dev_ctl__dispatch(
197     IN WV_SP_DEV_T dev,
198     IN PIRP irp,
199     IN ULONG POINTER_ALIGNMENT code
200   ) {
201     NTSTATUS status;
202
203     switch (code) {
204         case IOCTL_STORAGE_QUERY_PROPERTY:
205           status = disk_dev_ctl__storage_query_prop_(dev, irp);
206           break;
207
208         case IOCTL_DISK_GET_DRIVE_GEOMETRY:
209           status = disk_dev_ctl__get_geom_(dev, irp);
210           break;
211
212         case IOCTL_SCSI_GET_ADDRESS:
213           status = disk_dev_ctl__scsi_get_address_(dev, irp);
214           break;
215
216         /* Some cases that pop up on Windows Server 2003. */
217         #if 0
218         case IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY:
219         case IOCTL_MOUNTDEV_LINK_CREATED:
220         case IOCTL_MOUNTDEV_QUERY_STABLE_GUID:
221         case IOCTL_VOLUME_ONLINE:
222           irp->IoStatus.Information = 0;
223           status = STATUS_SUCCESS;
224           break;
225         #endif
226
227         default:
228           irp->IoStatus.Information = 0;
229           status = STATUS_INVALID_PARAMETER;
230       }
231
232     irp->IoStatus.Status = status;
233     IoCompleteRequest(irp, IO_NO_INCREMENT);
234     return status;
235   }