[ZIPFLDR] Allow the shell extension to extract passworded zip files
[reactos.git] / drivers / crypto / ksecdd / dispatch.c
1 /*
2 * PROJECT: ReactOS Drivers
3 * COPYRIGHT: See COPYING in the top level directory
4 * PURPOSE: Kernel Security Support Provider Interface Driver
5 *
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "ksecdd.h"
12 #include <ksecioctl.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17
18 /* FUNCTIONS ******************************************************************/
19
20 static
21 NTSTATUS
22 KsecQueryFileInformation(
23 PVOID InfoBuffer,
24 FILE_INFORMATION_CLASS FileInformationClass,
25 PSIZE_T BufferLength)
26 {
27 PFILE_STANDARD_INFORMATION StandardInformation;
28
29 /* Only FileStandardInformation is supported */
30 if (FileInformationClass != FileStandardInformation)
31 {
32 return STATUS_INVALID_INFO_CLASS;
33 }
34
35 /* Validate buffer size */
36 if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
37 {
38 *BufferLength = sizeof(FILE_STANDARD_INFORMATION);
39 return STATUS_INFO_LENGTH_MISMATCH;
40 }
41
42 /* Fill the structure */
43 StandardInformation = (PFILE_STANDARD_INFORMATION)InfoBuffer;
44 StandardInformation->AllocationSize.QuadPart = 0;
45 StandardInformation->EndOfFile.QuadPart = 0;
46 StandardInformation->NumberOfLinks = 1;
47 StandardInformation->DeletePending = FALSE;
48 StandardInformation->Directory = FALSE;
49 *BufferLength = sizeof(FILE_STANDARD_INFORMATION);
50
51 return STATUS_SUCCESS;
52 }
53
54 static
55 NTSTATUS
56 KsecQueryVolumeInformation(
57 PVOID InfoBuffer,
58 FS_INFORMATION_CLASS FsInformationClass,
59 PSIZE_T BufferLength)
60 {
61 PFILE_FS_DEVICE_INFORMATION DeviceInformation;
62
63 /* Only FileFsDeviceInformation is supported */
64 if (FsInformationClass != FileFsDeviceInformation)
65 {
66 return STATUS_INVALID_INFO_CLASS;
67 }
68
69 /* Validate buffer size */
70 if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
71 {
72 *BufferLength = sizeof(FILE_FS_DEVICE_INFORMATION);
73 return STATUS_INFO_LENGTH_MISMATCH;
74 }
75
76 /* Fill the structure */
77 DeviceInformation = (PFILE_FS_DEVICE_INFORMATION)InfoBuffer;
78 DeviceInformation->DeviceType = FILE_DEVICE_NULL;
79 DeviceInformation->Characteristics = 0;
80 *BufferLength = sizeof(FILE_FS_DEVICE_INFORMATION);
81
82 return STATUS_SUCCESS;
83 }
84
85 static
86 NTSTATUS
87 KsecDeviceControl(
88 ULONG IoControlCode,
89 PVOID Buffer,
90 SIZE_T InputLength,
91 PSIZE_T OutputLength)
92 {
93 NTSTATUS Status;
94
95 if ((IoControlCode == IOCTL_KSEC_RANDOM_FILL_BUFFER) ||
96 (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_PROCESS) ||
97 (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_PROCESS) ||
98 (IoControlCode == IOCTL_KSEC_ENCRYPT_CROSS_PROCESS) ||
99 (IoControlCode == IOCTL_KSEC_DECRYPT_CROSS_PROCESS) ||
100 (IoControlCode == IOCTL_KSEC_ENCRYPT_SAME_LOGON) ||
101 (IoControlCode == IOCTL_KSEC_DECRYPT_SAME_LOGON))
102 {
103 /* Make sure we have a valid output buffer */
104 if ((Buffer == NULL) || (OutputLength == NULL))
105 {
106 return STATUS_INVALID_PARAMETER;
107 }
108
109 /* Check if the input is smaller than the output */
110 if (InputLength < *OutputLength)
111 {
112 /* We might have uninitialized memory, zero it out */
113 RtlSecureZeroMemory((PUCHAR)Buffer + InputLength,
114 *OutputLength - InputLength);
115 }
116 }
117
118 /* Check ioctl code */
119 switch (IoControlCode)
120 {
121 case IOCTL_KSEC_REGISTER_LSA_PROCESS:
122
123 Status = STATUS_SUCCESS;
124 break;
125
126 case IOCTL_KSEC_RANDOM_FILL_BUFFER:
127
128 Status = KsecGenRandom(Buffer, *OutputLength);
129 break;
130
131 case IOCTL_KSEC_ENCRYPT_SAME_PROCESS:
132
133 Status = KsecEncryptMemory(Buffer,
134 *OutputLength,
135 RTL_ENCRYPT_OPTION_SAME_PROCESS);
136 break;
137
138 case IOCTL_KSEC_DECRYPT_SAME_PROCESS:
139
140 Status = KsecDecryptMemory(Buffer,
141 *OutputLength,
142 RTL_ENCRYPT_OPTION_SAME_PROCESS);
143 break;
144
145 case IOCTL_KSEC_ENCRYPT_CROSS_PROCESS:
146
147 Status = KsecEncryptMemory(Buffer,
148 *OutputLength,
149 RTL_ENCRYPT_OPTION_CROSS_PROCESS);
150 break;
151
152 case IOCTL_KSEC_DECRYPT_CROSS_PROCESS:
153
154 Status = KsecDecryptMemory(Buffer,
155 *OutputLength,
156 RTL_ENCRYPT_OPTION_CROSS_PROCESS);
157 break;
158
159 case IOCTL_KSEC_ENCRYPT_SAME_LOGON:
160
161 Status = KsecEncryptMemory(Buffer,
162 *OutputLength,
163 RTL_ENCRYPT_OPTION_SAME_LOGON);
164 break;
165
166 case IOCTL_KSEC_DECRYPT_SAME_LOGON:
167
168 Status = KsecDecryptMemory(Buffer,
169 *OutputLength,
170 RTL_ENCRYPT_OPTION_SAME_LOGON);
171 break;
172
173 default:
174 DPRINT1("Unhandled control code 0x%lx\n", IoControlCode);
175 __debugbreak();
176 return STATUS_INVALID_PARAMETER;
177 }
178
179 return Status;
180 }
181
182 NTSTATUS
183 NTAPI
184 KsecDdDispatch(
185 PDEVICE_OBJECT DeviceObject,
186 PIRP Irp)
187 {
188 PIO_STACK_LOCATION IoStackLocation;
189 ULONG_PTR Information;
190 NTSTATUS Status;
191 PVOID Buffer;
192 SIZE_T InputLength, OutputLength;
193 FILE_INFORMATION_CLASS FileInfoClass;
194 FS_INFORMATION_CLASS FsInfoClass;
195 ULONG IoControlCode;
196
197 IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
198
199 switch (IoStackLocation->MajorFunction)
200 {
201 case IRP_MJ_CREATE:
202 case IRP_MJ_CLOSE:
203
204 /* Just return success */
205 Status = STATUS_SUCCESS;
206 Information = 0;
207 break;
208
209 case IRP_MJ_READ:
210
211 /* There is nothing to read */
212 Status = STATUS_END_OF_FILE;
213 Information = 0;
214 break;
215
216 case IRP_MJ_WRITE:
217
218 /* Pretend to have written everything */
219 Status = STATUS_SUCCESS;
220 Information = IoStackLocation->Parameters.Write.Length;
221 break;
222
223 case IRP_MJ_QUERY_INFORMATION:
224
225 /* Extract the parameters */
226 Buffer = Irp->AssociatedIrp.SystemBuffer;
227 OutputLength = IoStackLocation->Parameters.QueryFile.Length;
228 FileInfoClass = IoStackLocation->Parameters.QueryFile.FileInformationClass;
229
230 /* Call the internal function */
231 Status = KsecQueryFileInformation(Buffer,
232 FileInfoClass,
233 &OutputLength);
234 Information = OutputLength;
235 break;
236
237 case IRP_MJ_QUERY_VOLUME_INFORMATION:
238
239 /* Extract the parameters */
240 Buffer = Irp->AssociatedIrp.SystemBuffer;
241 OutputLength = IoStackLocation->Parameters.QueryVolume.Length;
242 FsInfoClass = IoStackLocation->Parameters.QueryVolume.FsInformationClass;
243
244 /* Call the internal function */
245 Status = KsecQueryVolumeInformation(Buffer,
246 FsInfoClass,
247 &OutputLength);
248 Information = OutputLength;
249 break;
250
251 case IRP_MJ_DEVICE_CONTROL:
252
253 /* Extract the parameters */
254 InputLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
255 OutputLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
256 IoControlCode = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;
257
258 /* Check for METHOD_OUT_DIRECT method */
259 if ((METHOD_FROM_CTL_CODE(IoControlCode) == METHOD_OUT_DIRECT) &&
260 (OutputLength != 0))
261 {
262 /* Use the provided MDL */
263 OutputLength = Irp->MdlAddress->ByteCount;
264 Buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress,
265 NormalPagePriority);
266 if (Buffer == NULL)
267 {
268 Status = STATUS_INSUFFICIENT_RESOURCES;
269 Information = 0;
270 break;
271 }
272 }
273 else
274 {
275 /* Otherwise this is METHOD_BUFFERED, use the SystemBuffer */
276 Buffer = Irp->AssociatedIrp.SystemBuffer;
277 }
278
279 /* Call the internal function */
280 Status = KsecDeviceControl(IoControlCode,
281 Buffer,
282 InputLength,
283 &OutputLength);
284 Information = OutputLength;
285 break;
286
287 default:
288 DPRINT1("Unhandled major function %lu!\n",
289 IoStackLocation->MajorFunction);
290 ASSERT(FALSE);
291 return STATUS_INVALID_DEVICE_REQUEST;
292 }
293
294 /* Return the information */
295 Irp->IoStatus.Status = Status;
296 Irp->IoStatus.Information = Information;
297
298 /* Complete the request */
299 IoCompleteRequest(Irp, IO_NO_INCREMENT);
300
301 return Status;
302 }