Windows: Replace ParentObjectInformation pointer
[openafs.git] / src / WINNT / afsrdr / kernel / lib / AFSDevControl.cpp
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3  * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice,
14  *   this list of conditions and the following disclaimer in the
15  *   documentation
16  *   and/or other materials provided with the distribution.
17  * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18  *   nor the names of their contributors may be used to endorse or promote
19  *   products derived from this software without specific prior written
20  *   permission from Kernel Drivers, LLC and Your File System, Inc.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 //
36 // File: AFSDevControl.cpp
37 //
38
39 #include "AFSCommon.h"
40
41 //
42 // Function: AFSDevControl
43 //
44 // Description:
45 //
46 //      This is the dipatch handler for the IRP_MJ_DEVICE_CONTROL requests.
47 //
48 // Return:
49 //
50 //      A status is returned for the function
51 //
52
53 NTSTATUS
54 AFSDevControl( IN PDEVICE_OBJECT LibDeviceObject,
55                IN PIRP Irp)
56 {
57     UNREFERENCED_PARAMETER(LibDeviceObject);
58     NTSTATUS ntStatus = STATUS_SUCCESS;
59     IO_STACK_LOCATION *pIrpSp;
60     ULONG               ulIoControlCode = 0;
61
62     __try
63     {
64
65         pIrpSp = IoGetCurrentIrpStackLocation( Irp);
66
67         ulIoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
68
69         switch( ulIoControlCode)
70         {
71
72             case IOCTL_AFS_INITIALIZE_LIBRARY_DEVICE:
73             {
74
75                 AFSLibraryInitCB *pLibInitCB = (AFSLibraryInitCB *)Irp->AssociatedIrp.SystemBuffer;
76
77                 if ( Irp->RequestorMode != KernelMode)
78                 {
79
80                     ntStatus = STATUS_ACCESS_DENIED;
81
82                     break;
83                 }
84
85                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSLibraryInitCB))
86                 {
87
88                     ntStatus = STATUS_INVALID_PARAMETER;
89
90                     break;
91                 }
92
93                 ntStatus = AFSInitializeLibrary( pLibInitCB);
94
95                 if( !NT_SUCCESS( ntStatus))
96                 {
97
98                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
99                                   AFS_TRACE_LEVEL_ERROR,
100                                   "AFSDevControl AFSInitializeLibrary failure %08lX\n",
101                                   ntStatus);
102
103                     break;
104                 }
105
106                 //
107                 // Initialize our global entries
108                 //
109
110                 ntStatus = AFSInitializeGlobalDirectoryEntries();
111
112                 if( !NT_SUCCESS( ntStatus))
113                 {
114
115                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
116                                   AFS_TRACE_LEVEL_ERROR,
117                                   "AFSDevControl AFSInitializeGlobalDirectoryEntries failure %08lX\n",
118                                   ntStatus);
119
120                     break;
121                 }
122
123                 ntStatus = AFSInitializeSpecialShareNameList();
124
125                 if( !NT_SUCCESS( ntStatus))
126                 {
127
128                     AFSDbgLogMsg( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
129                                   AFS_TRACE_LEVEL_ERROR,
130                                   "AFSDevControl AFSInitializeSpecialShareNameList failure %08lX\n",
131                                   ntStatus);
132
133                     break;
134                 }
135
136                 break;
137             }
138
139             case IOCTL_AFS_ADD_CONNECTION:
140             {
141
142                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
143
144                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
145                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength < (ULONG)FIELD_OFFSET( AFSNetworkProviderConnectionCB, RemoteName) +
146                                                                                                             pConnectCB->RemoteNameLength ||
147                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG))
148                 {
149
150                     ntStatus = STATUS_INVALID_PARAMETER;
151
152                     break;
153                 }
154
155                 ntStatus = AFSAddConnection( pConnectCB,
156                                              (PULONG)Irp->AssociatedIrp.SystemBuffer,
157                                              &Irp->IoStatus.Information);
158
159                 break;
160             }
161
162             case IOCTL_AFS_CANCEL_CONNECTION:
163             {
164
165                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
166
167                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB))
168                 {
169
170                     ntStatus = STATUS_INVALID_PARAMETER;
171
172                     break;
173                 }
174
175                 ntStatus = AFSCancelConnection( pConnectCB,
176                                                 (AFSCancelConnectionResultCB *)Irp->AssociatedIrp.SystemBuffer,
177                                                 &Irp->IoStatus.Information);
178
179                 break;
180             }
181
182             case IOCTL_AFS_GET_CONNECTION:
183             {
184
185                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
186
187                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
188                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
189                 {
190
191                     ntStatus = STATUS_INVALID_PARAMETER;
192
193                     break;
194                 }
195
196                 ntStatus = AFSGetConnection( pConnectCB,
197                                              (WCHAR *)Irp->AssociatedIrp.SystemBuffer,
198                                              pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
199                                              &Irp->IoStatus.Information);
200
201                 break;
202             }
203
204             case IOCTL_AFS_LIST_CONNECTIONS:
205             {
206
207                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
208                 {
209
210                     ntStatus = STATUS_INVALID_PARAMETER;
211
212                     break;
213                 }
214
215                 ntStatus = AFSListConnections( (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer,
216                                                 pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
217                                                 &Irp->IoStatus.Information);
218
219                 break;
220             }
221
222             case IOCTL_AFS_GET_CONNECTION_INFORMATION:
223             {
224
225                 AFSNetworkProviderConnectionCB *pConnectCB = (AFSNetworkProviderConnectionCB *)Irp->AssociatedIrp.SystemBuffer;
226
227                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkProviderConnectionCB) ||
228                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength == 0)
229                 {
230
231                     ntStatus = STATUS_INVALID_PARAMETER;
232
233                     break;
234                 }
235
236                 ntStatus = AFSGetConnectionInfo( pConnectCB,
237                                                  pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
238                                                  &Irp->IoStatus.Information);
239
240                 break;
241             }
242
243             case IOCTL_AFS_SET_FILE_EXTENTS:
244             {
245
246                 AFSSetFileExtentsCB *pExtents = (AFSSetFileExtentsCB*) Irp->AssociatedIrp.SystemBuffer;
247
248                 //
249                 // Check lengths twice so that if the buffer makes the
250                 // count invalid we will not Accvio
251                 //
252
253                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
254                     ( FIELD_OFFSET( AFSSetFileExtentsCB, ExtentCount) + sizeof(ULONG)) ||
255                     pIrpSp->Parameters.DeviceIoControl.InputBufferLength <
256                     ( FIELD_OFFSET( AFSSetFileExtentsCB, ExtentCount) + sizeof(ULONG) +
257                       sizeof (AFSFileExtentCB) * pExtents->ExtentCount))
258                 {
259
260                     ntStatus = STATUS_INVALID_PARAMETER;
261
262                     break;
263                 }
264
265                 ntStatus = AFSProcessSetFileExtents( pExtents );
266
267                 Irp->IoStatus.Information = 0;
268                 Irp->IoStatus.Status = ntStatus;
269
270                 break;
271             }
272
273             case IOCTL_AFS_RELEASE_FILE_EXTENTS:
274             {
275                 ntStatus = AFSProcessReleaseFileExtents( Irp);
276                 break;
277             }
278
279             case IOCTL_AFS_SET_FILE_EXTENT_FAILURE:
280             {
281
282                 ntStatus = AFSProcessExtentFailure( Irp);
283
284                 break;
285             }
286
287             case IOCTL_AFS_INVALIDATE_CACHE:
288             {
289
290                 AFSInvalidateCacheCB *pInvalidate = (AFSInvalidateCacheCB*)Irp->AssociatedIrp.SystemBuffer;
291
292                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSInvalidateCacheCB))
293                 {
294
295                     ntStatus = STATUS_INVALID_PARAMETER;
296
297                     break;
298                 }
299
300                 ntStatus = AFSInvalidateCache( pInvalidate);
301
302                 Irp->IoStatus.Information = 0;
303                 Irp->IoStatus.Status = ntStatus;
304
305                 break;
306             }
307
308             case IOCTL_AFS_NETWORK_STATUS:
309             {
310
311                 AFSNetworkStatusCB *pNetworkStatus = (AFSNetworkStatusCB *)Irp->AssociatedIrp.SystemBuffer;
312
313                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSNetworkStatusCB))
314                 {
315
316                     ntStatus = STATUS_INVALID_PARAMETER;
317
318                     break;
319                 }
320
321                 //
322                 // Set the network status
323                 //
324
325                 ntStatus = AFSSetNetworkState( pNetworkStatus);
326
327                 Irp->IoStatus.Information = 0;
328                 Irp->IoStatus.Status = ntStatus;
329
330                 break;
331             }
332
333             case IOCTL_AFS_VOLUME_STATUS:
334             {
335
336                 AFSVolumeStatusCB *pVolumeStatus = (AFSVolumeStatusCB *)Irp->AssociatedIrp.SystemBuffer;
337
338                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSVolumeStatusCB))
339                 {
340
341                     ntStatus = STATUS_INVALID_PARAMETER;
342
343                     break;
344                 }
345
346                 ntStatus = AFSSetVolumeState( pVolumeStatus);
347
348                 Irp->IoStatus.Information = 0;
349                 Irp->IoStatus.Status = ntStatus;
350
351                 break;
352             }
353
354             case IOCTL_AFS_STATUS_REQUEST:
355             {
356
357                 if( pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSDriverStatusRespCB))
358                 {
359
360                     ntStatus = STATUS_INVALID_PARAMETER;
361
362                     break;
363                 }
364
365                 ntStatus = AFSGetDriverStatus( (AFSDriverStatusRespCB *)Irp->AssociatedIrp.SystemBuffer);
366
367                 Irp->IoStatus.Information = sizeof( AFSDriverStatusRespCB);
368
369                 break;
370             }
371
372             case IOCTL_AFS_GET_OBJECT_INFORMATION:
373             {
374
375
376                 if( pIrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof( AFSGetStatusInfoCB) ||
377                     pIrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( AFSStatusInfoCB))
378
379                 {
380
381                     ntStatus = STATUS_INVALID_PARAMETER;
382
383                     break;
384                 }
385
386                 ntStatus = AFSGetObjectStatus( (AFSGetStatusInfoCB *)Irp->AssociatedIrp.SystemBuffer,
387                                                pIrpSp->Parameters.DeviceIoControl.InputBufferLength,
388                                                (AFSStatusInfoCB *)Irp->AssociatedIrp.SystemBuffer,
389                                                (ULONG *)&Irp->IoStatus.Information);
390
391                 break;
392             }
393
394             case 0x140390:      // IOCTL_LMR_DISABLE_LOCAL_BUFFERING
395             {
396                 //
397                 // See http://msdn.microsoft.com/en-us/library/ee210753%28v=vs.85%29.aspx
398                 //
399                 // The IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code is defined internally by
400                 // the system as 0x140390 and not in a public header file. It is used by
401                 // special-purpose applications to disable local client-side in-memory
402                 // caching of data when reading data from or writing data to a remote file.
403                 // After local buffering is disabled, the setting remains in effect until all
404                 // open handles to the file are closed and the redirector cleans up its internal
405                 // data structures.
406                 //
407                 // General-purpose applications should not use IOCTL_LMR_DISABLE_LOCAL_BUFFERING,
408                 // because it can result in excessive network traffic and associated loss of
409                 // performance. The IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code should be used
410                 // only in specialized applications moving large amounts of data over the network
411                 // while attempting to maximize use of network bandwidth. For example, the CopyFile
412                 // and CopyFileEx functions use IOCTL_LMR_DISABLE_LOCAL_BUFFERING to improve large
413                 // file copy performance.
414                 //
415                 // IOCTL_LMR_DISABLE_LOCAL_BUFFERING is not implemented by local file systems and
416                 // will fail with the error ERROR_INVALID_FUNCTION. Issuing the
417                 // IOCTL_LMR_DISABLE_LOCAL_BUFFERING control code on remote directory handles will
418                 // fail with the error ERROR_NOT_SUPPORTED.
419                 //
420
421                 ntStatus = STATUS_NOT_SUPPORTED;
422
423                 break;
424             }
425
426          default:
427             {
428                 //
429                 // Note that this code path is never executed - default behavior is caught in the
430                 // security checks in lib.  New Ioctl functions therefore have to be added here and
431                 // in ..\fs\AFSCommSupport.cpp
432                 //
433
434                 ntStatus = STATUS_NOT_IMPLEMENTED;
435
436                 break;
437             }
438         }
439
440 //try_exit:
441
442     }
443     __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()))
444     {
445
446         ntStatus = STATUS_UNSUCCESSFUL;
447
448         AFSDbgLogMsg( 0,
449                       0,
450                       "EXCEPTION - AFSDevControl %08lX\n",
451                       ulIoControlCode);
452
453         AFSDumpTraceFilesFnc();
454     }
455
456     Irp->IoStatus.Status = ntStatus;
457
458     AFSCompleteRequest( Irp,
459                         ntStatus);
460
461     return ntStatus;
462 }