/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. You should have received a copy of the GNU General * Public License along with this program. If not, see * . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ #include "config.h" #include "lwiosys.h" #include "iodriver.h" #include "ioinit.h" #include #include #include #include "lwlist.h" #include "lwioutils.h" #include "lwiocfg.h" #include "ntlogmacros.h" #include "lwthreads.h" #include #define NT_PENDING_OR_SUCCESS_OR_NOT(status) \ (LW_NT_SUCCESS_OR_NOT(status) || (STATUS_PENDING == (status))) #define IsValidStatusForIrpType(Status, IrpType) \ (NT_PENDING_OR_SUCCESS_OR_NOT(Status) || \ ((IRP_TYPE_READ_DIRECTORY_CHANGE == (IrpType)) && \ (STATUS_NOTIFY_ENUM_DIR == (Status)))) typedef struct _IOP_DRIVER_CONFIG { PSTR pszName; PSTR pszPath; LW_LIST_LINKS Links; } IOP_DRIVER_CONFIG, *PIOP_DRIVER_CONFIG; typedef struct _IOP_CONFIG { LW_LIST_LINKS DriverConfigList; ULONG DriverCount; } IOP_CONFIG, *PIOP_CONFIG; typedef struct _IOP_CONFIG_PARSE_STATE { PIOP_CONFIG pConfig; PIOP_DRIVER_CONFIG pDriverConfig; NTSTATUS Status; } IOP_CONFIG_PARSE_STATE, *PIOP_CONFIG_PARSE_STATE; typedef struct _IOP_ROOT_STATE { PIOP_CONFIG Config; // Diagnostics Only ULONG DriverCount; LW_LIST_LINKS DriverObjectList; // Diagnostics Only ULONG DeviceCount; // Should really be a hash table... LW_LIST_LINKS DeviceObjectList; LW_RTL_MUTEX InitMutex; PLW_MAP_SECURITY_CONTEXT MapSecurityContext; } IOP_ROOT_STATE, *PIOP_ROOT_STATE; typedef ULONG IO_DRIVER_OBJECT_FLAGS; #define IO_DRIVER_OBJECT_FLAG_INITIALIZED 0x00000001 #define IO_DRIVER_OBJECT_FLAG_READY 0x00000002 struct _IO_DRIVER_OBJECT { LONG ReferenceCount; IO_DRIVER_OBJECT_FLAGS Flags; PIOP_ROOT_STATE Root; PIOP_DRIVER_CONFIG Config; PVOID LibraryHandle; PIO_DRIVER_ENTRY DriverEntry; struct { PIO_DRIVER_SHUTDOWN_CALLBACK Shutdown; PIO_DRIVER_DISPATCH_CALLBACK Dispatch; } Callback; PVOID Context; // Devices LW_LIST_LINKS DeviceList; ULONG DeviceCount; // For each list to which this object belongs. LW_LIST_LINKS RootLinks; }; struct _IO_DEVICE_OBJECT { LONG ReferenceCount; UNICODE_STRING DeviceName; PIO_DRIVER_OBJECT Driver; PVOID Context; // File objects for this device. LW_LIST_LINKS FileObjectsList; // For each list to which this object belongs. LW_LIST_LINKS DriverLinks; LW_LIST_LINKS RootLinks; LW_RTL_MUTEX Mutex; LW_RTL_MUTEX CancelMutex; }; typedef ULONG FILE_OBJECT_FLAGS; #define FILE_OBJECT_FLAG_CREATE_DONE 0x00000001 #define FILE_OBJECT_FLAG_CANCELLED 0x00000002 #define FILE_OBJECT_FLAG_RUNDOWN 0x00000004 #define FILE_OBJECT_FLAG_CLOSE_DONE 0x00000008 #define FILE_OBJECT_FLAG_RELATIVE 0x00000010 #define FILE_OBJECT_FLAG_RUNDOWN_WAIT 0x00000020 struct _IO_FILE_OBJECT { LONG ReferenceCount; PIO_DEVICE_OBJECT pDevice; PVOID pContext; UNICODE_STRING FileName; FILE_OBJECT_FLAGS Flags; // TODO -- Track file vs named pipe LW_RTL_MUTEX Mutex; // Count of IRPs that have dispatched but are not complete. LONG DispatchedIrpCount; // List of referencing IRPs (via IRP_INTERNAL.FileObjectLinks) LW_LIST_LINKS IrpList; // Links for IO_DEVICE_OBJECT.FileObjectsList LW_LIST_LINKS DeviceLinks; struct { LW_RTL_CONDITION_VARIABLE Condition; PIO_ASYNC_COMPLETE_CALLBACK Callback; PVOID CallbackContext; PIO_STATUS_BLOCK pIoStatusBlock; } Rundown; // TODO -- Pre-allocate IRP_TYPE_CLOSE... }; // ioinit.c NTSTATUS IopParse( IN OUT PIO_FILE_NAME pFileName, OUT PIO_DEVICE_OBJECT* ppDevice ); NTSTATUS IopGetMapSecurityContext( OUT PLW_MAP_SECURITY_CONTEXT* ppContext ); // ioconfig.c VOID IopConfigFreeConfig( IN OUT PIOP_CONFIG* ppConfig ); NTSTATUS IopConfigReadRegistry( OUT PIOP_CONFIG* ppConfig ); // ioroot.c VOID IopRootFree( IN OUT PIOP_ROOT_STATE* ppRoot ); NTSTATUS IopRootCreate( OUT PIOP_ROOT_STATE* ppRoot, IN PCSTR pszConfigFilePath ); NTSTATUS IopRootLoadDriver( IN PIOP_ROOT_STATE pRoot, IN PIO_STATIC_DRIVER pStaticDrivers, IN PWSTR pwszDriverName ); PIO_DRIVER_OBJECT IopRootFindDriver( IN PIOP_ROOT_STATE pRoot, IN PWSTR pwszDriverName ); PIO_DEVICE_OBJECT IopRootFindDevice( IN PIOP_ROOT_STATE pRoot, IN PUNICODE_STRING pDeviceName ); VOID IopRootInsertDriver( IN PIOP_ROOT_STATE pRoot, IN PLW_LIST_LINKS pDriverRootLinks ); VOID IopRootRemoveDriver( IN PIOP_ROOT_STATE pRoot, IN PLW_LIST_LINKS pDriverRootLinks ); VOID IopRootInsertDevice( IN PIOP_ROOT_STATE pRoot, IN PLW_LIST_LINKS pDeviceRootLinks ); VOID IopRootRemoveDevice( IN PIOP_ROOT_STATE pRoot, IN PLW_LIST_LINKS pDeviceRootLinks ); NTSTATUS IopRootParse( IN PIOP_ROOT_STATE pRoot, IN OUT PIO_FILE_NAME pFileName, OUT PIO_DEVICE_OBJECT* ppDevice ); NTSTATUS IopRootGetMapSecurityContext( IN PIOP_ROOT_STATE pRoot, OUT PLW_MAP_SECURITY_CONTEXT* ppContext ); // iodriver.c VOID IopDriverUnload( IN OUT PIO_DRIVER_OBJECT* ppDriverObject ); NTSTATUS IopDriverLoad( OUT PIO_DRIVER_OBJECT* ppDriverObject, IN PIOP_ROOT_STATE pRoot, IN PIOP_DRIVER_CONFIG pDriverConfig, IN PIO_STATIC_DRIVER pStaticDrivers ); VOID IopDriverInsertDevice( IN PIO_DRIVER_OBJECT pDriver, IN PLW_LIST_LINKS pDeviceDriverLinks ); VOID IopDriverRemoveDevice( IN PIO_DRIVER_OBJECT pDriver, IN PLW_LIST_LINKS pDeviceDriverLinks ); // iodevice.c NTSTATUS IopDeviceCallDriver( IN IO_DEVICE_HANDLE DeviceHandle, IN OUT PIRP pIrp ); VOID IopDeviceLock( IN PIO_DEVICE_OBJECT pDeviceObject ); VOID IopDeviceUnlock( IN PIO_DEVICE_OBJECT pDeviceObject ); // ioirp.c NTSTATUS IopIrpCreate( OUT PIRP* ppIrp, IN IRP_TYPE Type, IN PIO_FILE_OBJECT pFileObject ); VOID IopIrpReference( IN PIRP Irp ); VOID IopIrpDereference( IN OUT PIRP* Irp ); PIRP IopIrpGetIrpFromAsyncCancelContext( IN PIO_ASYNC_CANCEL_CONTEXT Context ); BOOLEAN IopIrpCancel( IN PIRP pIrp ); NTSTATUS IopIrpDispatch( IN PIRP pIrp, IN OUT OPTIONAL PIO_ASYNC_CONTROL_BLOCK AsyncControlBlock, IN OPTIONAL PIO_STATUS_BLOCK pIoStatusBlock, IN OPTIONAL PIO_FILE_HANDLE pCreateFileHandle ); VOID IopIrpCancelFileObject( IN PIO_FILE_OBJECT pFileObject ); // iofile.c VOID IopFileObjectLock( IN PIO_FILE_OBJECT pFileObject ); VOID IopFileObjectUnlock( IN PIO_FILE_OBJECT pFileObject ); VOID IopFileObjectReference( IN PIO_FILE_OBJECT pFileObject ); VOID IopFileObjectDereference( IN OUT PIO_FILE_OBJECT* ppFileObject ); NTSTATUS IopFileObjectAllocate( OUT PIO_FILE_OBJECT* ppFileObject, IN PIO_DEVICE_OBJECT pDevice, IN PIO_FILE_NAME FileName ); VOID IopFileObjectFree( IN OUT PIO_FILE_OBJECT* ppFileObject ); NTSTATUS IopFileObjectRundown( IN PIO_FILE_OBJECT pFileObject, IN OPTIONAL PIO_ASYNC_COMPLETE_CALLBACK Callback, IN OPTIONAL PVOID CallbackContext, IN OPTIONAL PIO_STATUS_BLOCK IoStatusBlock ); NTSTATUS IopFileObjectAddDispatched( IN PIO_FILE_OBJECT pFileObject, IN IRP_TYPE Type ); VOID IopFileObjectRemoveDispatched( IN PIO_FILE_OBJECT pFileObject, IN IRP_TYPE Type ); // iosecurity.c VOID IopSecurityReferenceSecurityContext( IN PIO_CREATE_SECURITY_CONTEXT SecurityContext ); // ioapi.c -- internally available // TODO--Replace with Iop helper function VOID IoDereferenceAsyncCancelContext( IN OUT PIO_ASYNC_CANCEL_CONTEXT* AsyncCancelContext );