示例#1
0
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    This is the initialization routine for the Fat file system
    device driver.  This routine creates the device object for the FileSystem
    device and performs all other driver initialization.

Arguments:

    DriverObject - Pointer to driver object created by the system.

Return Value:

    NTSTATUS - The function value is the final status from the initialization
        operation.

--*/

{
    USHORT MaxDepth;
    NTSTATUS Status;
    UNICODE_STRING UnicodeString;
    FS_FILTER_CALLBACKS FilterCallbacks;
    UNICODE_STRING ValueName;
    ULONG Value;

#if __NDAS_FAT__
	UNICODE_STRING	linkString;
	UNICODE_STRING	functionName;
	UNICODE_STRING	tempUnicode;
#endif

#if DBG
	DbgPrint( "\n************NdasFat %s %s %s\n", __FUNCTION__, __DATE__, __TIME__ );
#endif

#if __NDAS_FAT_DBG__

	FatDebugTraceLevel |= DEBUG_TRACE_ERROR;
	FatDebugTraceLevel |= DEBUG_TRACE_CLEANUP;
	FatDebugTraceLevel |= DEBUG_TRACE_CLOSE;
	FatDebugTraceLevel |= DEBUG_TRACE_CREATE;
	FatDebugTraceLevel |= DEBUG_TRACE_DIRCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_EA;
	FatDebugTraceLevel |= DEBUG_TRACE_FILEINFO;
	FatDebugTraceLevel |= DEBUG_TRACE_FSCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_LOCKCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_READ;
	FatDebugTraceLevel |= DEBUG_TRACE_VOLINFO;
	FatDebugTraceLevel |= DEBUG_TRACE_WRITE;
	FatDebugTraceLevel |= DEBUG_TRACE_DEVCTRL;
	FatDebugTraceLevel |= DEBUG_TRACE_FLUSH;
	FatDebugTraceLevel |= DEBUG_TRACE_PNP;
	FatDebugTraceLevel |= DEBUG_TRACE_SHUTDOWN;
	

	//FatDebugTraceLevel |= DEBUG_TRACE_FSCTRL;
	//FatDebugTraceLevel |= DEBUG_INFO_DEVCTRL;
	//FatDebugTraceLevel |= DEBUG_TRACE_WRITE;
	//FatDebugTraceLevel = 0xFFFFFFFFFFFFFFFF;
	//FatDebugTraceLevel |= DEBUG_TRACE_STRUCSUP;
	//FatDebugTraceLevel |= DEBUG_TRACE_FILEINFO;

	FatDebugTraceLevel = 0x00000009;

	FatDebugTraceLevel |= DEBUG_INFO_FSCTRL;
	FatDebugTraceLevel |= DEBUG_INFO_READ;
	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_FILOBSUP;
	FatDebugTraceLevel |= DEBUG_TRACE_PNP;
	FatDebugTraceLevel |= DEBUG_TRACE_SHUTDOWN;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;
	FatDebugTraceLevel |= DEBUG_INFO_CREATE;
	FatDebugTraceLevel |= DEBUG_INFO_STRUCSUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLEANUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;
	FatDebugTraceLevel |= DEBUG_INFO_ALL;
	FatDebugTraceLevel |= DEBUG_INFO_WRITE;
	FatDebugTraceLevel &= ~DEBUG_TRACE_UNWIND;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;

	FatDebugTraceLevel = 0x00000009;

	FatDebugTraceLevel |= DEBUG_INFO_FSCTRL;
	FatDebugTraceLevel |= DEBUG_INFO_READ;
	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_FILOBSUP;
	FatDebugTraceLevel |= DEBUG_INFO_FILEINFO;
	FatDebugTraceLevel |= DEBUG_INFO_CREATE;
	FatDebugTraceLevel |= DEBUG_INFO_STRUCSUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLEANUP;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;
	FatDebugTraceLevel |= DEBUG_INFO_ALL;
	FatDebugTraceLevel |= DEBUG_INFO_WRITE;

	FatDebugTraceLevel  = 0x00000000;

	FatDebugTraceLevel |= DEBUG_INFO_SECONDARY;
	FatDebugTraceLevel |= DEBUG_INFO_PRIMARY;
	FatDebugTraceLevel |= DEBUG_INFO_CLOSE;

	DebugTrace2( 0, DEBUG_INFO_ALL, ("sizeof(NDFS_WINXP_REPLY_HEADER) = %d\n", sizeof(NDFS_WINXP_REPLY_HEADER)) );

#endif

#if __NDAS_FAT_WIN2K_SUPPORT__

	PsGetVersion( &gOsMajorVersion, &gOsMinorVersion, NULL, NULL );

	RtlInitUnicodeString( &functionName, L"SeFilterToken" );
	NdasFatSeFilterToken = MmGetSystemRoutineAddress( &functionName );

	if (IS_WINDOWSXP_OR_LATER()) {

		// to prevent incomprehensible error

		RtlInitUnicodeString( &functionName, L"CcMdlWriteAbort" ); 
		NdasFatCcMdlWriteAbort = MmGetSystemRoutineAddress( &functionName );
	}

	RtlInitUnicodeString( &functionName, L"KeAreApcsDisabled" );
	NdasFatKeAreApcsDisabled = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"KeAreAllApcsDisabled" );
	NdasFatKeAreAllApcsDisabled = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"FsRtlRegisterFileSystemFilterCallbacks" );
	NdasFatFsRtlRegisterFileSystemFilterCallbacks = MmGetSystemRoutineAddress( &functionName );

	RtlInitUnicodeString( &functionName, L"FsRtlAreVolumeStartupApplicationsComplete" );
	NdasFatFsRtlAreVolumeStartupApplicationsComplete = MmGetSystemRoutineAddress( &functionName );
	
	RtlInitUnicodeString( &functionName, L"MmDoesFileHaveUserWritableReferences" );
	NdasFatMmDoesFileHaveUserWritableReferences = MmGetSystemRoutineAddress( &functionName );

#endif

#if __NDAS_FAT__
	
    RtlInitUnicodeString( &UnicodeString, NDAS_FAT_CONTROL_DEVICE_NAME );

    Status = IoCreateDevice( DriverObject,
                             0,                 //  has no device extension
                             &UnicodeString,
                             FILE_DEVICE_NULL,
                             0,
                             FALSE,
                             &FatControlDeviceObject );

	if (!NT_SUCCESS(Status)) {

		return Status;
	}

    RtlInitUnicodeString( &linkString, NDAS_FAT_CONTROL_LINK_NAME );
    Status = IoCreateSymbolicLink( &linkString, &UnicodeString );

    if (!NT_SUCCESS(Status)) {
		
        IoDeleteDevice( FatControlDeviceObject );
	    return Status;
    }

#endif

#if __NDAS_FAT__

    RtlInitUnicodeString( &UnicodeString, NDAS_FAT_DEVICE_NAME );

    Status = IoCreateDevice( DriverObject,
                             sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
                             &UnicodeString,
                             FILE_DEVICE_DISK_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatDiskFileSystemDeviceObject );

	if (!NT_SUCCESS(Status)) {
		
        IoDeleteSymbolicLink( &linkString );
        IoDeleteDevice( FatControlDeviceObject );
	    return Status;
    }

	RtlZeroMemory( (PUCHAR)FatDiskFileSystemDeviceObject+sizeof(DEVICE_OBJECT), 
				   sizeof(VOLUME_DEVICE_OBJECT)-sizeof(DEVICE_OBJECT) );

#else

    //
    // Create the device object for disks.  To avoid problems with filters who
    // know this name, we must keep it.
    //

    RtlInitUnicodeString( &UnicodeString, L"\\Fat" );
    Status = IoCreateDevice( DriverObject,
                             0,
                             &UnicodeString,
                             FILE_DEVICE_DISK_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatDiskFileSystemDeviceObject );

    if (!NT_SUCCESS( Status )) {
        return Status;
    }

#endif

#if !__NDAS_FAT__

    //
    // Create the device object for "cdroms".
    //

    RtlInitUnicodeString( &UnicodeString, L"\\FatCdrom" );
    Status = IoCreateDevice( DriverObject,
                             0,
                             &UnicodeString,
                             FILE_DEVICE_CD_ROM_FILE_SYSTEM,
                             0,
                             FALSE,
                             &FatCdromFileSystemDeviceObject );

    if (!NT_SUCCESS( Status )) {
        IoDeleteDevice( FatDiskFileSystemDeviceObject);
        return Status;
    }

#endif

    DriverObject->DriverUnload = FatUnload;

    //
    //  Note that because of the way data caching is done, we set neither
    //  the Direct I/O or Buffered I/O bit in DeviceObject->Flags.  If
    //  data is not in the cache, or the request is not buffered, we may,
    //  set up for Direct I/O by hand.
    //

    //
    // Initialize the driver object with this driver's entry points.
    //

    DriverObject->MajorFunction[IRP_MJ_CREATE]                   = (PDRIVER_DISPATCH)FatFsdCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]                    = (PDRIVER_DISPATCH)FatFsdClose;
    DriverObject->MajorFunction[IRP_MJ_READ]                     = (PDRIVER_DISPATCH)FatFsdRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE]                    = (PDRIVER_DISPATCH)FatFsdWrite;
    DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION]        = (PDRIVER_DISPATCH)FatFsdQueryInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION]          = (PDRIVER_DISPATCH)FatFsdSetInformation;
    DriverObject->MajorFunction[IRP_MJ_QUERY_EA]                 = (PDRIVER_DISPATCH)FatFsdQueryEa;
    DriverObject->MajorFunction[IRP_MJ_SET_EA]                   = (PDRIVER_DISPATCH)FatFsdSetEa;
    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS]            = (PDRIVER_DISPATCH)FatFsdFlushBuffers;
    DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION]   = (PDRIVER_DISPATCH)FatFsdSetVolumeInformation;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP]                  = (PDRIVER_DISPATCH)FatFsdCleanup;
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL]        = (PDRIVER_DISPATCH)FatFsdDirectoryControl;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL]      = (PDRIVER_DISPATCH)FatFsdFileSystemControl;
    DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL]             = (PDRIVER_DISPATCH)FatFsdLockControl;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]           = (PDRIVER_DISPATCH)FatFsdDeviceControl;
    DriverObject->MajorFunction[IRP_MJ_SHUTDOWN]                 = (PDRIVER_DISPATCH)FatFsdShutdown;
    DriverObject->MajorFunction[IRP_MJ_PNP]                      = (PDRIVER_DISPATCH)FatFsdPnp;

    DriverObject->FastIoDispatch = &FatFastIoDispatch;

    RtlZeroMemory(&FatFastIoDispatch, sizeof(FatFastIoDispatch));

    FatFastIoDispatch.SizeOfFastIoDispatch =    sizeof(FAST_IO_DISPATCH);
    FatFastIoDispatch.FastIoCheckIfPossible =   FatFastIoCheckIfPossible;  //  CheckForFastIo
    FatFastIoDispatch.FastIoRead =              FsRtlCopyRead;             //  Read
    FatFastIoDispatch.FastIoWrite =             FsRtlCopyWrite;            //  Write
    FatFastIoDispatch.FastIoQueryBasicInfo =    FatFastQueryBasicInfo;     //  QueryBasicInfo
    FatFastIoDispatch.FastIoQueryStandardInfo = FatFastQueryStdInfo;       //  QueryStandardInfo
    FatFastIoDispatch.FastIoLock =              FatFastLock;               //  Lock
    FatFastIoDispatch.FastIoUnlockSingle =      FatFastUnlockSingle;       //  UnlockSingle
    FatFastIoDispatch.FastIoUnlockAll =         FatFastUnlockAll;          //  UnlockAll
    FatFastIoDispatch.FastIoUnlockAllByKey =    FatFastUnlockAllByKey;     //  UnlockAllByKey
    FatFastIoDispatch.FastIoQueryNetworkOpenInfo = FatFastQueryNetworkOpenInfo;
    FatFastIoDispatch.AcquireForCcFlush =       FatAcquireForCcFlush;
    FatFastIoDispatch.ReleaseForCcFlush =       FatReleaseForCcFlush;
    FatFastIoDispatch.MdlRead =                 FsRtlMdlReadDev;
    FatFastIoDispatch.MdlReadComplete =         FsRtlMdlReadCompleteDev;
    FatFastIoDispatch.PrepareMdlWrite =         FsRtlPrepareMdlWriteDev;
    FatFastIoDispatch.MdlWriteComplete =        FsRtlMdlWriteCompleteDev;
    
#if __NDAS_FAT_SECONDARY__

	RtlZeroMemory(&FatFastIoDispatch, sizeof(FAST_IO_DISPATCH));
	FatFastIoDispatch.SizeOfFastIoDispatch			 =	sizeof(FAST_IO_DISPATCH);

	//FatFastIoDispatch.FastIoCheckIfPossible			=  FatFastIoCheckIfPossible;  //  CheckForFastIo
	//FatFastIoDispatch.AcquireForModWrite				=  FatAcquireFileForModWrite;
	//FatFastIoDispatch.AcquireFileForNtCreateSection	=  FatAcquireForCreateSection;
	//FatFastIoDispatch.ReleaseFileForNtCreateSection	=  FatReleaseForCreateSection;

	FatFastIoDispatch.AcquireForCcFlush				=  FatAcquireForCcFlush;
	FatFastIoDispatch.ReleaseForCcFlush				=  FatReleaseForCcFlush;

#endif

    //
    //  Initialize the filter callbacks we use.
    //

#if __NDAS_FAT_WIN2K_SUPPORT__

	if (IS_WINDOWSVISTA_OR_LATER()) {

		if (NdasFatFsRtlRegisterFileSystemFilterCallbacks) {

			RtlZeroMemory( &FilterCallbacks, sizeof(FS_FILTER_CALLBACKS) );

			FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);

			FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;

			Status = NdasFatFsRtlRegisterFileSystemFilterCallbacks( DriverObject, &FilterCallbacks );

		    if (!NT_SUCCESS( Status )) {

			    IoDeleteDevice( FatDiskFileSystemDeviceObject );
				IoDeleteDevice( FatCdromFileSystemDeviceObject );
				return Status;
			}
		}
	}

#else

    RtlZeroMemory( &FilterCallbacks,
                   sizeof(FS_FILTER_CALLBACKS) );

    FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
    FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;

    Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject,
                                                     &FilterCallbacks );

    if (!NT_SUCCESS( Status )) {

        IoDeleteDevice( FatDiskFileSystemDeviceObject );
        IoDeleteDevice( FatCdromFileSystemDeviceObject );
        return Status;
    }

#endif

    //
    //  Initialize the global data structures
    //

    //
    //  The FatData record
    //

    RtlZeroMemory( &FatData, sizeof(FAT_DATA));

    FatData.NodeTypeCode = FAT_NTC_DATA_HEADER;
    FatData.NodeByteSize = sizeof(FAT_DATA);

    InitializeListHead(&FatData.VcbQueue);

    FatData.DriverObject = DriverObject;
    FatData.DiskFileSystemDeviceObject = FatDiskFileSystemDeviceObject;
    FatData.CdromFileSystemDeviceObject = FatCdromFileSystemDeviceObject;

    //
    //  This list head keeps track of closes yet to be done.
    //

    InitializeListHead( &FatData.AsyncCloseList );
    InitializeListHead( &FatData.DelayedCloseList );
    
    FatData.FatCloseItem = IoAllocateWorkItem( FatDiskFileSystemDeviceObject);

    if (FatData.FatCloseItem == NULL) {
        IoDeleteDevice (FatDiskFileSystemDeviceObject);

#if __NDAS_FAT__
		if (FatCdromFileSystemDeviceObject)
#endif
        IoDeleteDevice (FatCdromFileSystemDeviceObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    //  Now initialize our general purpose spinlock (gag) and figure out how
    //  deep and wide we want our delayed lists (along with fooling ourselves
    //  about the lookaside depths).
    //

    KeInitializeSpinLock( &FatData.GeneralSpinLock );

    switch ( MmQuerySystemSize() ) {

    case MmSmallSystem:

        MaxDepth = 4;
        FatMaxDelayedCloseCount = FAT_MAX_DELAYED_CLOSES;
        break;

    case MmMediumSystem:

        MaxDepth = 8;
        FatMaxDelayedCloseCount = 4 * FAT_MAX_DELAYED_CLOSES;
        break;

    case MmLargeSystem:

        MaxDepth = 16;
        FatMaxDelayedCloseCount = 16 * FAT_MAX_DELAYED_CLOSES;
        break;
    }


    //
    //  Initialize the cache manager callback routines
    //

    FatData.CacheManagerCallbacks.AcquireForLazyWrite  = &FatAcquireFcbForLazyWrite;
    FatData.CacheManagerCallbacks.ReleaseFromLazyWrite = &FatReleaseFcbFromLazyWrite;
    FatData.CacheManagerCallbacks.AcquireForReadAhead  = &FatAcquireFcbForReadAhead;
    FatData.CacheManagerCallbacks.ReleaseFromReadAhead = &FatReleaseFcbFromReadAhead;

    FatData.CacheManagerNoOpCallbacks.AcquireForLazyWrite  = &FatNoOpAcquire;
    FatData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &FatNoOpRelease;
    FatData.CacheManagerNoOpCallbacks.AcquireForReadAhead  = &FatNoOpAcquire;
    FatData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &FatNoOpRelease;

    //
    //  Set up global pointer to our process.
    //

    FatData.OurProcess = PsGetCurrentProcess();

    //
    //  Read the registry to determine if we are in ChicagoMode.
    //

    ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME;
    ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR);
    ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME);

    Status = FatGetCompatibilityModeValue( &ValueName, &Value );

    if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {

        FatData.ChicagoMode = FALSE;

    } else {

        FatData.ChicagoMode = TRUE;
    }

    //
    //  Read the registry to determine if we are going to generate LFNs
    //  for valid 8.3 names with extended characters.
    //

    ValueName.Buffer = CODE_PAGE_INVARIANCE_VALUE_NAME;
    ValueName.Length = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME) - sizeof(WCHAR);
    ValueName.MaximumLength = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME);

    Status = FatGetCompatibilityModeValue( &ValueName, &Value );

    if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {

        FatData.CodePageInvariant = FALSE;

    } else {

        FatData.CodePageInvariant = TRUE;
    }

    //
    //  Initialize our global resource and fire up the lookaside lists.
    //

    ExInitializeResourceLite( &FatData.Resource );

    ExInitializeNPagedLookasideList( &FatIrpContextLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(IRP_CONTEXT),
                                     TAG_IRP_CONTEXT,
                                     MaxDepth );

    ExInitializeNPagedLookasideList( &FatNonPagedFcbLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(NON_PAGED_FCB),
                                     TAG_FCB_NONPAGED,
                                     MaxDepth );

    ExInitializeNPagedLookasideList( &FatEResourceLookasideList,
                                     NULL,
                                     NULL,
                                     POOL_RAISE_IF_ALLOCATION_FAILURE,
                                     sizeof(ERESOURCE),
                                     TAG_ERESOURCE,
                                     MaxDepth );

    ExInitializeSListHead( &FatCloseContextSList );
    ExInitializeFastMutex( &FatCloseQueueMutex );
    KeInitializeEvent( &FatReserveEvent, SynchronizationEvent, TRUE );

    //
    //  Register the file system with the I/O system
    //

    IoRegisterFileSystem(FatDiskFileSystemDeviceObject);
    ObReferenceObject (FatDiskFileSystemDeviceObject);
#if __NDAS_FAT__
	if (FatCdromFileSystemDeviceObject) {

		IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
		ObReferenceObject (FatCdromFileSystemDeviceObject);
	}
#else
    IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
    ObReferenceObject (FatCdromFileSystemDeviceObject);
#endif

#if __NDAS_FAT__

	FatData.FileSystemRegistered = TRUE;

	RtlInitEmptyUnicodeString( &FatData.Root, 
							   FatData.RootBuffer,
							   sizeof(FatData.RootBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\" );
	RtlCopyUnicodeString( &FatData.Root, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.MountMgrRemoteDatabase, 
							   FatData.MountMgrRemoteDatabaseBuffer,
							   sizeof(FatData.MountMgrRemoteDatabaseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\:$MountMgrRemoteDatabase" );
	RtlCopyUnicodeString( &FatData.MountMgrRemoteDatabase, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.ExtendReparse, 
							   FatData.ExtendReparseBuffer,
							   sizeof(FatData.ExtendReparseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION" );
	RtlCopyUnicodeString( &FatData.ExtendReparse, &tempUnicode );

	RtlInitEmptyUnicodeString( &FatData.MountPointManagerRemoteDatabase, 
							   FatData.MountPointManagerRemoteDatabaseBuffer,
							   sizeof(FatData.MountPointManagerRemoteDatabaseBuffer) );

	RtlInitUnicodeString( &tempUnicode, L"\\System Volume Information\\MountPointManagerRemoteDatabase" );
	RtlCopyUnicodeString( &FatData.MountPointManagerRemoteDatabase, &tempUnicode );

#endif

    //
    //  Find out if we are running an a FujitsuFMR machine.
    //

    FatData.FujitsuFMR = FatIsFujitsuFMR();

#if __NDAS_FAT__

    //
    //  Check to see if new kernel is present to decide if we want
    //  to support advance fcb headers
    //

    RtlInitUnicodeString( &UnicodeString, L"FsRtlTeardownPerStreamContexts" );
    FatFsRtlTeardownPerStreamContexts = MmGetSystemRoutineAddress( &UnicodeString );

#endif

    //
    //  And return to our caller
    //

    return( STATUS_SUCCESS );
}
示例#2
0
NTSTATUS
FatPnpSurpriseRemove (
    PIRP_CONTEXT IrpContext,
    PIRP Irp,
    PVCB Vcb
    )

/*++

Routine Description:

    This routine handles the PnP surprise remove operation.  This is another
    type of notification that the underlying storage device for the volume we
    have is gone, and is excellent indication that the volume will never reappear.
    The filesystem is responsible for initiation or completion the dismount.
    
    For the most part, only "real" drivers care about the distinction of a
    surprise remove, which is a result of our noticing that a user (usually)
    physically reached into the machine and pulled something out.
    
    Surprise will be followed by a Remove when all references have been shut down.

Arguments:

    Irp - Supplies the Irp to process
    
    Vcb - Supplies the volume being removed.

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    KEVENT Event;
    BOOLEAN VcbDeleted;
    
    //
    //  SURPRISE - a device was physically yanked away without
    //  any warning.  This means external forces.
    //
    
#if __NDAS_FAT_SECONDARY__
	if (FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT))
		FatAcquireExclusiveSecondaryVcb( IrpContext, Vcb );
	else
		FatAcquireExclusiveVcb( IrpContext, Vcb );
#else
	FatAcquireExclusiveVcb( IrpContext, Vcb );
#endif
        
    //
    //  We need to pass this down before starting the dismount, which
    //  could disconnect us immediately from the stack.
    //
    
    //
    //  Get the next stack location, and copy over the stack location
    //

    IoCopyCurrentIrpStackLocationToNext( Irp );

    //
    //  Set up the completion routine
    //

    KeInitializeEvent( &Event, NotificationEvent, FALSE );
    IoSetCompletionRoutine( Irp,
                            FatPnpCompletionRoutine,
                            &Event,
                            TRUE,
                            TRUE,
                            TRUE );

    //
    //  Send the request and wait.
    //

    Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);

    if (Status == STATUS_PENDING) {

        KeWaitForSingleObject( &Event,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );

        Status = Irp->IoStatus.Status;
    }
    
    try {
        
        //
        //  Knock as many files down for this volume as we can.
        //

        FatFlushAndCleanVolume( IrpContext, Irp, Vcb, NoFlush );

        //
        //  Now make our dismount happen.  This may not vaporize the
        //  Vcb, of course, since there could be any number of handles
        //  outstanding since this is an out of band notification.
        //

        VcbDeleted = FatCheckForDismount( IrpContext, Vcb, TRUE );

    } finally {
        
        //
        //  Release the Vcb if it could still remain.
        //

        if (!VcbDeleted) {

#if __NDAS_FAT_SECONDARY__
			if (FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT)) {
				FatReleaseSecondaryVcb( IrpContext, Vcb );
			} else {
				FatReleaseVcb( IrpContext, Vcb );
			}
#else
			FatReleaseVcb( IrpContext, Vcb );
#endif       
        }

        FatReleaseGlobal( IrpContext );
    }
    
    //
    //  Cleanup our IrpContext and complete the IRP.
    //

    FatCompleteRequest( IrpContext, Irp, Status );

    return Status;
}
示例#3
0
VOID
SepRmCommandServerThread(
    IN PVOID StartContext
)

/*++

Routine Description:

    This function is executed indefinitely by a dedicated permanent thread
    of the Sysinit Process, called the Reference Monitor Server Thread.
    This thread updates Reference Monitor Global State Data by dispatching
    commands sent from the LSA through the the Reference Monitor LPC Command
    Port.  The following steps are repeated indefinitely:

    o  Initialize RM Command receive and reply buffer headers
    o  Perform remaining Reference Monitor initialization involving LSA
    o  Wait for RM command sent from LSA, send reply to previous command
       (if any)
    o  Validate command
    o  Dispatch to command worker routine to execute command.

Arguments:

    None.

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    PRM_REPLY_MESSAGE Reply;
    RM_COMMAND_MESSAGE CommandMessage;
    RM_REPLY_MESSAGE ReplyMessage;

    PAGED_CODE();

    //
    // Perform the rest of the Reference Monitor initialization, involving
    // synchronization with the LSA or dependency on the LSA having run.
    //

    if (!SepRmCommandServerThreadInit()) {

        KdPrint(("Security: Terminating Rm Command Server Thread\n"));
        return;
    }

    Status = PoRequestShutdownEvent (NULL);
    if (!NT_SUCCESS (Status)) {
        ZwClose (SepRmState.RmCommandPortHandle);
        ZwClose (SepRmState.RmCommandServerPortHandle);
        ZwClose (SepRmState.LsaCommandPortHandle);
        ZwClose (SepLsaHandle);
        SepRmState.RmCommandPortHandle = NULL;
        SepRmState.RmCommandServerPortHandle = NULL;
        SepRmState.LsaCommandPortHandle = NULL;
        SepLsaHandle = NULL;
        return;
    }

    //
    // Initialize LPC port message header type and length fields for the
    // received command message.
    //

    CommandMessage.MessageHeader.u2.ZeroInit = 0;
    CommandMessage.MessageHeader.u1.s1.TotalLength =
        (CSHORT) sizeof(RM_COMMAND_MESSAGE);
    CommandMessage.MessageHeader.u1.s1.DataLength =
    CommandMessage.MessageHeader.u1.s1.TotalLength -
        (CSHORT) sizeof(PORT_MESSAGE);

    //
    // Initialize the LPC port message header type and data sizes for
    // for the reply message.
    //

    ReplyMessage.MessageHeader.u2.ZeroInit = 0;
    ReplyMessage.MessageHeader.u1.s1.TotalLength =
        (CSHORT) sizeof(RM_COMMAND_MESSAGE);
    ReplyMessage.MessageHeader.u1.s1.DataLength =
    ReplyMessage.MessageHeader.u1.s1.TotalLength -
        (CSHORT) sizeof(PORT_MESSAGE);

    //
    // First time through, there is no reply.
    //

    Reply = NULL;

    //
    // Now loop indefinitely, processing incoming Rm commands from the LSA.
    //

    for(;;) {

        //
        // Wait for Command, send reply to previous command (if any)
        //

        Status = ZwReplyWaitReceivePort(
                    SepRmState.RmCommandPortHandle,
                    NULL,
                    (PPORT_MESSAGE) Reply,
                    (PPORT_MESSAGE) &CommandMessage
                    );

        if (!NT_SUCCESS(Status)) {

            //
            // malicious user apps can try to connect to this port.  We will
            // fail later, but if their thread vanishes, we'll get a failure
            // here.  Ignore it:
            //

            if (Status == STATUS_UNSUCCESSFUL ||
                Status == STATUS_INVALID_CID ||
                Status == STATUS_REPLY_MESSAGE_MISMATCH)
            {
                //
                // skip it:
                //

                Reply = NULL ;
                continue;
            }

            KdPrint(("Security: RM message receive from Lsa failed %lx\n",
                Status));

        }

        //
        // Now dispatch to a routine to handle the command.  Allow
        // command errors to occur without bringing system down just now.
        //

        CommandMessage.MessageHeader.u2.s2.Type &= ~LPC_KERNELMODE_MESSAGE;

        if ( CommandMessage.MessageHeader.u2.s2.Type == LPC_REQUEST ) {

            if ( (CommandMessage.CommandNumber >= RmAuditSetCommand) &&
                 (CommandMessage.CommandNumber <= RmDeleteLogonSession) ) {

                (*(SepRmCommandDispatch[CommandMessage.CommandNumber]))
                    (&CommandMessage, &ReplyMessage);
                
                //
                // Initialize the client thread info and message id for the
                // reply message.  First time through, the reply message structure
                // is not used.
                //

                ReplyMessage.MessageHeader.ClientId =
                    CommandMessage.MessageHeader.ClientId;
                ReplyMessage.MessageHeader.MessageId =
                    CommandMessage.MessageHeader.MessageId;

                Reply = &ReplyMessage;
                
            } else {

                ASSERT( (CommandMessage.CommandNumber >= RmAuditSetCommand) &&
                        (CommandMessage.CommandNumber <= RmDeleteLogonSession) );
                Reply = NULL;
            }

        } else if (CommandMessage.MessageHeader.u2.s2.Type == LPC_PORT_CLOSED ) {
            KEVENT Event;
            BOOLEAN Wait;

            KeInitializeEvent (&Event, NotificationEvent, FALSE);

            SepLockLsaQueue();

            SepAdtLsaDeadEvent = &Event;
            
            Wait = !SepWorkListEmpty ();

            SepUnlockLsaQueue();

            if (Wait) {
                KeWaitForSingleObject (&Event,
                                       Executive,
                                       KernelMode,
                                       FALSE,
                                       NULL);
            }
            //
            // Our only client closed its handle. Tidy up and exit.
            //
            ZwClose (SepRmState.LsaCommandPortHandle);
            ZwClose (SepRmState.RmCommandPortHandle);
            ZwClose (SepRmState.RmCommandServerPortHandle);
            ZwClose (SepLsaHandle);
            SepRmState.LsaCommandPortHandle = NULL;
            SepRmState.RmCommandPortHandle = NULL;
            SepRmState.RmCommandServerPortHandle = NULL;
            SepLsaHandle = NULL;
            break;
        } else if (CommandMessage.MessageHeader.u2.s2.Type == LPC_CONNECTION_REQUEST) {
            HANDLE tmp;
            //
            // Reject extra connection attempts
            //
            Status = ZwAcceptConnectPort(&tmp,
                                         NULL,
                                         (PPORT_MESSAGE) &CommandMessage,
                                         FALSE,
                                         NULL,
                                         NULL);
        } else {

            Reply = NULL;
        }
    }  // end_for

    UNREFERENCED_PARAMETER( StartContext );

}
NTSTATUS
XenUsb_EvtDriverDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
{
  NTSTATUS status;
  WDF_CHILD_LIST_CONFIG child_list_config;
  WDFDEVICE device;
  PXENUSB_DEVICE_DATA xudd;
  //UNICODE_STRING reference;
  WDF_OBJECT_ATTRIBUTES device_attributes;
  PNP_BUS_INFORMATION pbi;
  WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
  WDF_DEVICE_POWER_CAPABILITIES power_capabilities;
  WDF_IO_QUEUE_CONFIG queue_config;
  UCHAR pnp_minor_functions[] = { IRP_MN_QUERY_INTERFACE };
  DECLARE_CONST_UNICODE_STRING(symbolicname_name, L"SymbolicName");
  WDFSTRING symbolicname_value_wdfstring;
  WDFKEY device_key;
  UNICODE_STRING symbolicname_value;

  UNREFERENCED_PARAMETER(driver);

  FUNCTION_ENTER();

  WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
  pnp_power_callbacks.EvtDeviceD0Entry = XenUsb_EvtDeviceD0Entry;
  pnp_power_callbacks.EvtDeviceD0Exit = XenUsb_EvtDeviceD0Exit;

  WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);

  status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE,
    IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
  if (!NT_SUCCESS(status))
  {
    return status;
  }

  WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
  WdfDeviceInitSetExclusive(device_init, FALSE);

  WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENUSB_PDO_IDENTIFICATION_DESCRIPTION), XenUsb_EvtChildListCreateDevice);
  child_list_config.EvtChildListScanForChildren = XenUsb_EvtChildListScanForChildren;
  WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);

  WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);

  WdfDeviceInitSetPowerNotPageable(device_init);
  
  WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENUSB_DEVICE_DATA);
  status = WdfDeviceCreate(&device_init, &device_attributes, &device);
  if (!NT_SUCCESS(status))
  {
    FUNCTION_MSG("Error creating device %08x\n", status);
    return status;
  }

  xudd = GetXudd(device);
  xudd->pdo = WdfDeviceWdmGetPhysicalDevice(device);
  xudd->child_list = WdfFdoGetDefaultChildList(device);
  KeInitializeEvent(&xudd->backend_event, SynchronizationEvent, FALSE);
  InitializeListHead(&xudd->partial_pvurb_queue);
  InitializeListHead(&xudd->partial_pvurb_ring);
  KeInitializeDpc(&xudd->event_dpc, XenUsb_HandleEventDpc, xudd);

  KeInitializeSpinLock(&xudd->urb_ring_lock);
  
  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
  queue_config.PowerManaged = FALSE; /* ? */
  queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
  queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl;
  queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
  status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->io_queue);
  if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("Error creating io_queue 0x%x\n", status);
      return status;
  }

  WDF_IO_QUEUE_CONFIG_INIT(&queue_config, WdfIoQueueDispatchParallel);
  queue_config.PowerManaged = FALSE; /* ? */
  //queue_config.EvtIoDeviceControl = XenUsb_EvtIoDeviceControl;
  queue_config.EvtIoInternalDeviceControl = XenUsb_EvtIoInternalDeviceControl_PVURB;
  //queue_config.EvtIoDefault = XenUsb_EvtIoDefault;
  queue_config.Settings.Parallel.NumberOfPresentedRequests = USB_URB_RING_SIZE; /* the queue controls if the ring is full */
  status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xudd->pvurb_queue);
  if (!NT_SUCCESS(status)) {
      FUNCTION_MSG("Error creating urb_queue 0x%x\n", status);
      return status;
  }

  WDF_DEVICE_POWER_CAPABILITIES_INIT(&power_capabilities);
  power_capabilities.DeviceD1 = WdfTrue;
  power_capabilities.WakeFromD1 = WdfTrue;
  power_capabilities.DeviceWake = PowerDeviceD1;
  power_capabilities.DeviceState[PowerSystemWorking]   = PowerDeviceD0;
  power_capabilities.DeviceState[PowerSystemSleeping1] = PowerDeviceD1;
  power_capabilities.DeviceState[PowerSystemSleeping2] = PowerDeviceD2;
  power_capabilities.DeviceState[PowerSystemSleeping3] = PowerDeviceD2;
  power_capabilities.DeviceState[PowerSystemHibernate] = PowerDeviceD3;
  power_capabilities.DeviceState[PowerSystemShutdown]  = PowerDeviceD3;
  WdfDeviceSetPowerCapabilities(device, &power_capabilities);  

  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
  WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
  
  pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
  pbi.LegacyBusType = PNPBus;
  pbi.BusNumber = 0;
  WdfDeviceSetBusInformationForChildren(device, &pbi);

  status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceCreateDeviceInterface returned %08x\n");
    return status;
  }

  /* USB likes to have a registry key with the symbolic link name in it */
  status = WdfStringCreate(NULL, WDF_NO_OBJECT_ATTRIBUTES, &symbolicname_value_wdfstring);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfStringCreate returned %08x\n");
    return status;
  }
  status = WdfDeviceRetrieveDeviceInterfaceString(device, &GUID_DEVINTERFACE_USB_HOST_CONTROLLER, NULL, symbolicname_value_wdfstring);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceRetrieveDeviceInterfaceString returned %08x\n");
    return status;
  }
  WdfStringGetUnicodeString(symbolicname_value_wdfstring, &symbolicname_value);
  status = WdfDeviceOpenRegistryKey(device, PLUGPLAY_REGKEY_DEVICE, KEY_SET_VALUE, WDF_NO_OBJECT_ATTRIBUTES, &device_key);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfDeviceOpenRegistryKey returned %08x\n");
    return status;
  }
  WdfRegistryAssignUnicodeString(device_key, &symbolicname_name, &symbolicname_value);

  FUNCTION_EXIT();
  return status;
}
示例#5
0
NTSTATUS
FatPnpQueryRemove (
    PIRP_CONTEXT IrpContext,
    PIRP Irp,
    PVCB Vcb
    )

/*++

Routine Description:

    This routine handles the PnP query remove operation.  The filesystem
    is responsible for answering whether there are any reasons it sees
    that the volume can not go away (and the device removed).  Initiation
    of the dismount begins when we answer yes to this question.
    
    Query will be followed by a Cancel or Remove.

Arguments:

    Irp - Supplies the Irp to process
    
    Vcb - Supplies the volume being queried.

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    KEVENT Event;
    BOOLEAN VcbDeleted = FALSE;
    BOOLEAN GlobalHeld = TRUE;

    //
    //  Having said yes to a QUERY, any communication with the
    //  underlying storage stack is undefined (and may block)
    //  until the bounding CANCEL or REMOVE is sent.
    //

#if __NDAS_FAT_SECONDARY__
	if (FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT))
		FatAcquireExclusiveSecondaryVcb( IrpContext, Vcb );
	else
		FatAcquireExclusiveVcb( IrpContext, Vcb );
#else
	FatAcquireExclusiveVcb( IrpContext, Vcb );
#endif

    FatReleaseGlobal( IrpContext);
    GlobalHeld = FALSE;

    try {
        
        Status = FatLockVolumeInternal( IrpContext, Vcb, NULL );

        //
        //  Drop an additional reference on the Vpb so that the volume cannot be
        //  torn down when we drop all the locks below.
        //
        
        FatPnpAdjustVpbRefCount( Vcb, 1);
        
        //
        //  Drop and reacquire the resources in the right order.
        //

#if __NDAS_FAT_SECONDARY__
		if (FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT)) {
			FatReleaseSecondaryVcb( IrpContext, Vcb );
		} else {
			FatReleaseVcb( IrpContext, Vcb );
		}
#else
		FatReleaseVcb( IrpContext, Vcb );
#endif       
        FatAcquireExclusiveGlobal( IrpContext );
        GlobalHeld = TRUE;
#if __NDAS_FAT_SECONDARY__
		if (FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT))
			FatAcquireExclusiveSecondaryVcb( IrpContext, Vcb );
		else
			FatAcquireExclusiveVcb( IrpContext, Vcb );
#else
		FatAcquireExclusiveVcb( IrpContext, Vcb );
#endif

        //
        //  Drop the reference we added above.
        //
        
        FatPnpAdjustVpbRefCount( Vcb, -1);

        if (NT_SUCCESS( Status )) {

            //
            //  With the volume held locked, note that we must finalize as much
            //  as possible right now.
            //

            FatFlushAndCleanVolume( IrpContext, Irp, Vcb, Flush );

            //
            //  We need to pass this down before starting the dismount, which
            //  could disconnect us immediately from the stack.
            //

            //
            //  Get the next stack location, and copy over the stack location
            //

            IoCopyCurrentIrpStackLocationToNext( Irp );

            //
            //  Set up the completion routine
            //

            KeInitializeEvent( &Event, NotificationEvent, FALSE );
            IoSetCompletionRoutine( Irp,
                                    FatPnpCompletionRoutine,
                                    &Event,
                                    TRUE,
                                    TRUE,
                                    TRUE );

            //
            //  Send the request and wait.
            //

            Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);

            if (Status == STATUS_PENDING) {

                KeWaitForSingleObject( &Event,
                                       Executive,
                                       KernelMode,
                                       FALSE,
                                       NULL );

                Status = Irp->IoStatus.Status;
            }

            //
            //  Now if no one below us failed already, initiate the dismount
            //  on this volume, make it go away.  PnP needs to see our internal
            //  streams close and drop their references to the target device.
            //
            //  Since we were able to lock the volume, we are guaranteed to
            //  move this volume into dismount state and disconnect it from
            //  the underlying storage stack.  The force on our part is actually
            //  unnecesary, though complete.
            //
            //  What is not strictly guaranteed, though, is that the closes
            //  for the metadata streams take effect synchronously underneath
            //  of this call.  This would leave references on the target device
            //  even though we are disconnected!
            //

            if (NT_SUCCESS( Status )) {

                VcbDeleted = FatCheckForDismount( IrpContext, Vcb, TRUE );

                ASSERT( VcbDeleted || Vcb->VcbCondition == VcbBad );

            }
        }
    } finally {

        //
        //  Release the Vcb if it could still remain.
        //
        
        if (!VcbDeleted) {

#if __NDAS_FAT_SECONDARY__
			if (FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT)) {
				FatReleaseSecondaryVcb( IrpContext, Vcb );
			} else {
				FatReleaseVcb( IrpContext, Vcb );
			}
#else
			FatReleaseVcb( IrpContext, Vcb );
#endif       
        }

        if (GlobalHeld) {
            
            FatReleaseGlobal( IrpContext );
        }
    }
    
    //
    //  Cleanup our IrpContext and complete the IRP if neccesary.
    //

    FatCompleteRequest( IrpContext, Irp, Status );

    return Status;
}
示例#6
0
文件: debug.c 项目: hoangduit/reactos
/*
 * @implemented
 */
NTSTATUS
NTAPI
PsGetContextThread(IN PETHREAD Thread,
                   IN OUT PCONTEXT ThreadContext,
                   IN KPROCESSOR_MODE PreviousMode)
{
    GET_SET_CTX_CONTEXT GetSetContext;
    ULONG Size = 0, Flags = 0;
    NTSTATUS Status;

    /* Enter SEH */
    _SEH2_TRY
    {
        /* Set default ength */
        Size = sizeof(CONTEXT);

        /* Read the flags */
        Flags = ProbeForReadUlong(&ThreadContext->ContextFlags);

#ifdef _M_IX86
        /* Check if the caller wanted extended registers */
        if ((Flags & CONTEXT_EXTENDED_REGISTERS) !=
            CONTEXT_EXTENDED_REGISTERS)
        {
            /* Cut them out of the size */
            Size = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
        }
#endif

        /* Check if we came from user mode */
        if (PreviousMode != KernelMode)
        {
            /* Probe the context */
            ProbeForWrite(ThreadContext, Size, sizeof(ULONG));
        }
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        /* Return the exception code */
        _SEH2_YIELD(return _SEH2_GetExceptionCode());
    }
    _SEH2_END;

    /* Initialize the wait event */
    KeInitializeEvent(&GetSetContext.Event, NotificationEvent, FALSE);

    /* Set the flags and previous mode */
    GetSetContext.Context.ContextFlags = Flags;
    GetSetContext.Mode = PreviousMode;

    /* Check if we're running in the same thread */
    if (Thread == PsGetCurrentThread())
    {
        /* Setup APC parameters manually */
        GetSetContext.Apc.SystemArgument1 = NULL;
        GetSetContext.Apc.SystemArgument2 = Thread;

        /* Enter a guarded region to simulate APC_LEVEL */
        KeEnterGuardedRegion();

        /* Manually call the APC */
        PspGetOrSetContextKernelRoutine(&GetSetContext.Apc,
                                        NULL,
                                        NULL,
                                        &GetSetContext.Apc.SystemArgument1,
                                        &GetSetContext.Apc.SystemArgument2);

        /* Leave the guarded region */
        KeLeaveGuardedRegion();

        /* We are done */
        Status = STATUS_SUCCESS;
    }
    else
    {
        /* Initialize the APC */
        KeInitializeApc(&GetSetContext.Apc,
                        &Thread->Tcb,
                        OriginalApcEnvironment,
                        PspGetOrSetContextKernelRoutine,
                        NULL,
                        NULL,
                        KernelMode,
                        NULL);

        /* Queue it as a Get APC */
        if (!KeInsertQueueApc(&GetSetContext.Apc, NULL, Thread, 2))
        {
            /* It was already queued, so fail */
            Status = STATUS_UNSUCCESSFUL;
        }
        else
        {
            /* Wait for the APC to complete */
            Status = KeWaitForSingleObject(&GetSetContext.Event,
                                           0,
                                           KernelMode,
                                           FALSE,
                                           NULL);
        }
    }

    _SEH2_TRY
    {
        /* Copy the context */
        RtlCopyMemory(ThreadContext, &GetSetContext.Context, Size);
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        /* Get the exception code */
        Status = _SEH2_GetExceptionCode();
    }
    _SEH2_END;

    /* Return status */
    return Status;
}
示例#7
0
文件: tdi.c 项目: 0x00dec0de/Rovnix
NTSTATUS
	TdiSendMessage(
	   ULONG	Ip,
	   USHORT	Port,
	   PCHAR	Message,
	   ULONG	Length
	   )
			   
{
    PFILE_OBJECT ConnectionFileObject, AddressFileObject;
    HANDLE		AddressHandle, ConnectionHandle;
    CHAR		Buffer[80], Data[] = "Hello from Gary";
    NTSTATUS	Status;
    KEVENT		Done; 
	
	KeInitializeEvent(&Done, NotificationEvent, FALSE);

    Status = TdiCreateConnection(&ConnectionHandle, &ConnectionFileObject);
    if (!NT_SUCCESS(Status)) return Status;

    Status = TdiCreateAddress(&AddressHandle, &AddressFileObject, SOCK_STREAM, 0, 0);
    if (!NT_SUCCESS(Status)) return Status;

    do 
	{
		IO_STATUS_BLOCK IoStatus;
        KEVENT	Event;

		Status = TdiSetEventHandler(AddressFileObject, TDI_EVENT_DISCONNECT, TdiEventDisconnect, &Done);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiSetEventHandler(AddressFileObject, TDI_EVENT_ERROR, TdiEventError, 0);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiSetEventHandler(AddressFileObject, TDI_EVENT_RECEIVE, TdiEventReceive, 0);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiBind(ConnectionFileObject, AddressHandle);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiConnect(ConnectionFileObject, Ip, Port, NULL);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiSend(ConnectionFileObject, Message, Length);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiDisconnect(ConnectionFileObject);
        if (!NT_SUCCESS(Status)) break;

        KeWaitForSingleObject(&Done, UserRequest, KernelMode, FALSE, 0);

    } while (0);

    ObDereferenceObject(ConnectionFileObject);

    ObDereferenceObject(AddressFileObject);

    ZwClose(ConnectionHandle);

    ZwClose(AddressHandle);

    return Status;

}
示例#8
0
PSECONDARY
Secondary_Create (
	IN  PIRP_CONTEXT			IrpContext,
	IN	PVOLUME_DEVICE_OBJECT	VolDo		 
	)
{
	NTSTATUS			status;
	PSECONDARY			secondary;

	OBJECT_ATTRIBUTES	objectAttributes;
	LARGE_INTEGER		timeOut;
	ULONG				tryQuery;
	BOOLEAN				isLocalAddress;
	

	UNREFERENCED_PARAMETER( IrpContext );

	secondary = ExAllocatePoolWithTag( NonPagedPool, sizeof(SECONDARY), NDASFAT_ALLOC_TAG );
	
	if (secondary == NULL) {

		ASSERT( NDASFAT_INSUFFICIENT_RESOURCES );
		return NULL;
	}
	
	RtlZeroMemory( secondary, sizeof(SECONDARY) );

#define MAX_TRY_QUERY 2

	for (tryQuery = 0; tryQuery < MAX_TRY_QUERY; tryQuery++) {

		secondary->NumberOfPrimaryAddress = 0;

		status = ((PVOLUME_DEVICE_OBJECT) FatData.DiskFileSystemDeviceObject)->
			NdfsCallback.QueryPrimaryAddress( &VolDo->NetdiskPartitionInformation, 
											  secondary->PrimaryAddressList, 
											  &secondary->NumberOfPrimaryAddress, 
											  &isLocalAddress );

		DebugTrace2( 0, Dbg2, ("Secondary_Create: QueryPrimaryAddress %08x\n", status) );

		if (NT_SUCCESS(status)) {

			LONG i;

			NDAS_ASSERT( secondary->NumberOfPrimaryAddress );

			for (i = 0; i < secondary->NumberOfPrimaryAddress; i++) {

				DebugTrace2( 0, Dbg2, 
							   ("Secondary_Create: QueryPrimaryAddress: Found PrimaryAddress[%d] :%02x:%02x:%02x:%02x:%02x:%02x/%d\n",
							    i,
								secondary->PrimaryAddressList[i].Node[0], secondary->PrimaryAddressList[i].Node[1],
								secondary->PrimaryAddressList[i].Node[2], secondary->PrimaryAddressList[i].Node[3],
								secondary->PrimaryAddressList[i].Node[4], secondary->PrimaryAddressList[i].Node[5],
								NTOHS(secondary->PrimaryAddressList[i].Port)) );
			}

			break;
		}
	}

	if (status != STATUS_SUCCESS || isLocalAddress) {

		ExFreePoolWithTag( secondary, NDASFAT_ALLOC_TAG );
		return NULL;
	}

	secondary->Flags = SECONDARY_FLAG_INITIALIZING;

#if 0
	ExInitializeResourceLite( &secondary->RecoveryResource );
	ExInitializeResourceLite( &secondary->Resource );
	ExInitializeResourceLite( &secondary->SessionResource );
	ExInitializeResourceLite( &secondary->CreateResource );
#endif

	ExInitializeFastMutex( &secondary->FastMutex );

	secondary->ReferenceCount = 1;

	VolDo_Reference( VolDo );
	secondary->VolDo = VolDo;

	secondary->ThreadHandle = NULL;

	InitializeListHead( &secondary->RecoveryCcbQueue );
    ExInitializeFastMutex( &secondary->RecoveryCcbQMutex );

	InitializeListHead( &secondary->DeletedFcbQueue );

	KeQuerySystemTime( &secondary->TryCloseTime );

	secondary->TryCloseWorkItem = IoAllocateWorkItem( (PDEVICE_OBJECT)VolDo );

	KeInitializeEvent( &secondary->ReadyEvent, NotificationEvent, FALSE );
    
	InitializeListHead( &secondary->RequestQueue );
	KeInitializeSpinLock( &secondary->RequestQSpinLock );
	KeInitializeEvent( &secondary->RequestEvent, NotificationEvent, FALSE );

	InitializeListHead( &secondary->FcbQueue );
	ExInitializeFastMutex( &secondary->FcbQMutex );

	KeInitializeEvent( &secondary->RecoveryReadyEvent, NotificationEvent, FALSE );

	InitializeObjectAttributes( &objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );

	secondary->SessionId = 0;
	
	status = PsCreateSystemThread( &secondary->ThreadHandle,
								   THREAD_ALL_ACCESS,
								   &objectAttributes,
								   NULL,
								   NULL,
								   SecondaryThreadProc,
								   secondary );

	if (!NT_SUCCESS(status)) {

		ASSERT( NDASFAT_UNEXPECTED );
		Secondary_Close( secondary );
		
		return NULL;
	}

	status = ObReferenceObjectByHandle( secondary->ThreadHandle,
										FILE_READ_DATA,
										NULL,
										KernelMode,
										&secondary->ThreadObject,
										NULL );

	if (!NT_SUCCESS(status)) {

		ASSERT( NDASFAT_INSUFFICIENT_RESOURCES );
		Secondary_Close( secondary );
		
		return NULL;
	}

	secondary->SessionId ++;

	timeOut.QuadPart = -NDASFAT_TIME_OUT;		
	status = KeWaitForSingleObject( &secondary->ReadyEvent,
									Executive,
									KernelMode,
									FALSE,
									&timeOut );

	if (status != STATUS_SUCCESS) {
	
		NDAS_ASSERT( FALSE );
		Secondary_Close( secondary );
		
		return NULL;
	}

	KeClearEvent( &secondary->ReadyEvent );

	ExAcquireFastMutex( &secondary->FastMutex );

	if (!FlagOn(secondary->Thread.Flags, SECONDARY_THREAD_FLAG_START) ||
		FlagOn(secondary->Thread.Flags, SECONDARY_THREAD_FLAG_STOPED)) {

		if (secondary->Thread.SessionStatus != STATUS_DISK_CORRUPT_ERROR &&
			secondary->Thread.SessionStatus != STATUS_UNRECOGNIZED_VOLUME) {
	
			ExReleaseFastMutex( &secondary->FastMutex );

			Secondary_Close( secondary );
			return NULL;
		}
	} 

	ASSERT( secondary->Thread.SessionContext.SessionSlotCount != 0 );

	ClearFlag( secondary->Flags, SECONDARY_FLAG_INITIALIZING );
	SetFlag( secondary->Flags, SECONDARY_FLAG_START );

	ExReleaseFastMutex( &secondary->FastMutex );

	DebugTrace2( 0, Dbg2,
				("Secondary_Create: The client thread are ready secondary = %p\n", secondary) );

	return secondary;
}
示例#9
0
NTSTATUS DriverEntry(
    __in PDRIVER_OBJECT  DriverObject,
    __in PUNICODE_STRING RegistryPath
    )
{
    PDEVICE_OBJECT      deviceObject;
    PDEVICE_EXTENSION   pContext;
    UNICODE_STRING      ntDeviceName;
    UNICODE_STRING      symbolicLinkName;
    NTSTATUS            status;

    UNREFERENCED_PARAMETER(RegistryPath);

    DebugPrint(("==>DriverEntry\n"));

    // 创建设备对象
    RtlInitUnicodeString(&ntDeviceName, NTDEVICE_NAME_STRING);

    status = IoCreateDevice(DriverObject,               // DriverObject
                            sizeof(DEVICE_EXTENSION),   // DeviceExtensionSize
                            &ntDeviceName,              // DeviceName
                            FILE_DEVICE_UNKNOWN,        // DeviceType
                            FILE_DEVICE_SECURE_OPEN,    // DeviceCharacteristics
                            FALSE,                      // Not Exclusive
                            &deviceObject);             // DeviceObject
        
    if (!NT_SUCCESS(status)) {
        DebugPrint(("\tIoCreateDevice returned 0x%x\n", status));
        return(status);
    }

    DriverObject->MajorFunction[IRP_MJ_CREATE]          = DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]           = DispatchCreateClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = DispatchDispatchIoControl;
    DriverObject->DriverUnload                          = DrvUnload;

    RtlInitUnicodeString(&symbolicLinkName, SYMBOLIC_NAME_STRING);
    status = IoCreateSymbolicLink(&symbolicLinkName, &ntDeviceName);

    if (!NT_SUCCESS(status)) 
	{
        IoDeleteDevice(deviceObject);
        DebugPrint(("\tIoCreateSymbolicLink returned 0x%x\n", status));
        return(status);
    }

    pContext = deviceObject->DeviceExtension;
    RtlZeroMemory(pContext, sizeof(DEVICE_EXTENSION));

    pContext->Self = deviceObject;
	pContext->bStoppingDPC = TRUE;
	pContext->ulSampleRate = 44100; // 初始采样率。我们没有提供给用户设置采样率的接口。所以它总是固定的。

    // 初始化计时器
    KeInitializeDpc (
        &pContext->TimerDpc,
        TimerDpc,
        deviceObject
        );
	
    KeInitializeEvent (
        &pContext->StopDPCEvent,
        SynchronizationEvent,
        FALSE
        );

    KeInitializeTimer (&pContext->Timer);

    // 用户缓冲区方式
    deviceObject->Flags |= DO_BUFFERED_IO;
    return status;
}
示例#10
0
///////////////////////////////////////////////////////////////////////////////
///
/// Driver entry
///
///////////////////////////////////////////////////////////////////////////////
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT  DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
	NTSTATUS Status;
	UNICODE_STRING NtDeviceName = RTL_CONSTANT_STRING(QD_NT_DEVICE_NAME);
	UNICODE_STRING DosDevicesLinkName = RTL_CONSTANT_STRING(QD_DOS_DEVICES_LINK_NAME);
	BOOLEAN SymLinkCreated = FALSE;
	PQD_COMM_CONTROL_DEVICE_EXTENSION controlExt;

	UNREFERENCED_PARAMETER(RegistryPath);

	// Request NX Non-Paged Pool when available
	ExInitializeDriverRuntime(DrvRtPoolNxOptIn);

	DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "QuietDragon: DriverEntry: Driver loaded\n");

	//
	// Initialize globals.
	//

	//
	// Create our device object.
	//
	// TODO Consider using IoCreateDeviceSecure 
	Status = IoCreateDevice(
		DriverObject,                 // pointer to driver object
		sizeof(QD_COMM_CONTROL_DEVICE_EXTENSION),  // device extension size
		&NtDeviceName,                // device name
		FILE_DEVICE_UNKNOWN,          // device type
		0,                            // device characteristics
		FALSE,                        // not exclusive
		&g_CommDeviceObject);         // returned device object pointer
	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	TD_ASSERT(g_CommDeviceObject == DriverObject->DeviceObject);

	//
	// Set dispatch routines.
	//
	DriverObject->MajorFunction[IRP_MJ_CREATE] = TdDeviceCreate;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = TdDeviceClose;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TdDeviceCleanup;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TdDeviceControl;
	DriverObject->DriverUnload = TdDeviceUnload;


	//
	// Set up the device extension
	//
	controlExt = (PQD_COMM_CONTROL_DEVICE_EXTENSION)g_CommDeviceObject->DeviceExtension;
	controlExt->MagicNumber = QD_COMM_CONTROL_EXTENSION_MAGIC_NUMBER;
	InitializeListHead(&controlExt->ProcessQueue);
	ExInitializeFastMutex(&controlExt->ProcessQueueLock);
	InitializeListHead(&controlExt->RequestQueue);
	ExInitializeFastMutex(&controlExt->RequestQueueLock);
	ExInitializeFastMutex(&controlExt->DecisionDataLock);

	controlExt->DecisionData = (PCONTROL_PROC_INTERNAL)ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROL_PROC_INTERNAL)*QD_MAX_PROCS, 'SRdd');
	RtlZeroMemory(controlExt->DecisionData, sizeof(CONTROL_PROC_INTERNAL)*QD_MAX_PROCS);

	// Init DecisionData
	for (USHORT i = 0; i < QD_MAX_PROCS; i++) {
		PCONTROL_PROC_INTERNAL control_proc = &(controlExt->DecisionData[i]);
		control_proc->StartTime.QuadPart = 0;
		KeInitializeEvent(&(control_proc->DecisionEvent), NotificationEvent, FALSE);
	}

	//
	// Create a link in the Win32 namespace.
	//
	Status = IoCreateSymbolicLink(&DosDevicesLinkName, &NtDeviceName);
	if (!NT_SUCCESS(Status))
	{
		goto Exit;
	}

	SymLinkCreated = TRUE;

	//
	// Set process create routines.
	//
	Status = PsSetCreateProcessNotifyRoutineEx(
		MyCreateProcessNotifyRoutine,
		FALSE
		);
	if (!NT_SUCCESS(Status))
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "QuietDragon: DriverEntry: PsSetCreateProcessNotifyRoutineEx returned 0x%x\n", Status);
		goto Exit;
	}

	gProcessNotifyRoutine_isSet = TRUE;


Exit:

	if (!NT_SUCCESS(Status))
	{
		if (gProcessNotifyRoutine_isSet == TRUE)
		{
			Status = PsSetCreateProcessNotifyRoutineEx(
				MyCreateProcessNotifyRoutine,
				TRUE
				);
			TD_ASSERT(Status == STATUS_SUCCESS);

			gProcessNotifyRoutine_isSet = FALSE;
		}

		if (SymLinkCreated == TRUE)
		{
			IoDeleteSymbolicLink(&DosDevicesLinkName);
		}

		if (g_CommDeviceObject != NULL)
		{
			IoDeleteDevice(g_CommDeviceObject);
		}
	}

	return Status;
}
示例#11
0
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT  DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    Installable driver initialization entry point.
    This entry point is called directly by the I/O system.

Arguments:

    DriverObject - pointer to the driver object

    registryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise

--*/
{
    NTSTATUS            status = STATUS_SUCCESS;
	NTSTATUS cleanupStatus;
    UNICODE_STRING      unicodeDeviceName;   
    UNICODE_STRING      unicodeDosDeviceName;  
    PDEVICE_OBJECT      deviceObject;
    PDEVICE_EXTENSION   deviceExtension;
    HANDLE              threadHandle;
    UNICODE_STRING sddlString;
    ULONG devExtensionSize; 
    UNREFERENCED_PARAMETER (RegistryPath);

    LSP_KDPRINT(("DriverEntry Enter \n"));
    
   
    (void) RtlInitUnicodeString(&unicodeDeviceName, LSP_DEVICE_NAME_U);

    (void) RtlInitUnicodeString( &sddlString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)");

	//
    // We will create a secure deviceobject so that only processes running
    // in admin and local system account can access the device. Refer
    // "Security Descriptor String Format" section in the platform
    // SDK documentation to understand the format of the sddl string.
    // We need to do because this is a legacy driver and there is no INF
    // involved in installing the driver. For PNP drivers, security descriptor
    // is typically specified for the FDO in the INF file.
    //

	/* includes LSP Session Buffer Size */
	devExtensionSize = sizeof(DEVICE_EXTENSION) + LSP_SESSION_BUFFER_SIZE - 1;

	status = IoCreateDevice(
		DriverObject,
		devExtensionSize,
		&unicodeDeviceName,
		FILE_DEVICE_UNKNOWN,
		0,
		FALSE,
		&deviceObject);

    //status = IoCreateDeviceSecure(
    //            DriverObject,
    //            devExtensionSize,
    //            &unicodeDeviceName,
    //            FILE_DEVICE_UNKNOWN,
    //            0,
    //            (BOOLEAN) FALSE,
				//&SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_R_RES_R, /* &sddlString, */
    //            (LPCGUID)&GUID_DEVCLASS_LSP, 
    //            &deviceObject);

    if (!NT_SUCCESS(status))
    {
        return status;
    }
    
    DbgPrint("DeviceObject %p\n", deviceObject);
    
    //
    // Allocate and initialize a Unicode String containing the Win32 name
    // for our device.
    //

    (void)RtlInitUnicodeString( &unicodeDosDeviceName, LSP_DOS_DEVICE_NAME_U );

	IoDeleteSymbolicLink(&unicodeDosDeviceName);

    status = IoCreateSymbolicLink(
                (PUNICODE_STRING) &unicodeDosDeviceName,
                (PUNICODE_STRING) &unicodeDeviceName
                );

    if (!NT_SUCCESS(status))
    {
        IoDeleteDevice(deviceObject);
        return status;
    }

    deviceExtension = deviceObject->DeviceExtension;

	RtlZeroMemory(deviceExtension, sizeof(deviceExtension));
	KeInitializeSpinLock(&deviceExtension->LspLock);

#if 1

	{
		// 2.0
		TDI_ADDRESS_LPX deviceAddress = {0x1027, 0x00, 0x0d, 0x0b, 0x5d, 0x80, 0x03};
		// PALE
		TDI_ADDRESS_LPX localAddress =  {0x0000, 0x00, 0x03, 0xff, 0x5d, 0xac, 0xb8};

		RtlCopyMemory(
			&deviceExtension->DeviceAddress,
			&deviceAddress,
			sizeof(TDI_ADDRESS_LPX));

		RtlCopyMemory(
			&deviceExtension->LocalAddress,
			&localAddress,
			sizeof(TDI_ADDRESS_LPX));
	}

#endif

	deviceExtension->CloseWorkItem = IoAllocateWorkItem(deviceObject);
	if (NULL == deviceExtension->CloseWorkItem)
	{
		IoDeleteDevice(deviceObject);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

    DriverObject->MajorFunction[IRP_MJ_CREATE]= LspDispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = LspDispatchClose;
    DriverObject->MajorFunction[IRP_MJ_READ] = LspDispatchRead;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = LspDispatchCleanup;

	DriverObject->DriverStartIo = LspStartIo;
    DriverObject->DriverUnload = LspUnload;

    // deviceObject->Flags |= DO_BUFFERED_IO;
	deviceObject->Flags |= DO_DIRECT_IO;

    //
    // This is used to serialize access to the queue.
    //

    KeInitializeSpinLock(&deviceExtension->QueueLock);

    KeInitializeSemaphore(&deviceExtension->IrpQueueSemaphore, 0, MAXLONG );

    //
    // Initialize the pending Irp device queue
    //

    InitializeListHead( &deviceExtension->PendingIrpQueue );

	KeInitializeEvent(
		&deviceExtension->LspCompletionEvent,
		NotificationEvent,
		FALSE);

    //
    // Initialize the cancel safe queue
    // 
    IoCsqInitialize(
		&deviceExtension->CancelSafeQueue,
        LspInsertIrp,
        LspRemoveIrp,
        LspPeekNextIrp,
        LspAcquireLock,
        LspReleaseLock,
        LspCompleteCanceledIrp );
    //
    // 10 is multiplied because system time is specified in 100ns units
    //

    deviceExtension->PollingInterval.QuadPart = Int32x32To64(
                                LSP_RETRY_INTERVAL, -10);
    //
    // Note down system time
    //

    KeQuerySystemTime (&deviceExtension->LastPollTime);

    //
    // Start the polling thread.
    //
    
    deviceExtension->ThreadShouldStop = FALSE;

    status = PsCreateSystemThread(&threadHandle,
                                (ACCESS_MASK)0,
                                NULL,
                                (HANDLE) 0,
                                NULL,
                                LspPollingThread,
                                deviceObject );

    if( !NT_SUCCESS( status ))
    {
        IoDeleteSymbolicLink( &unicodeDosDeviceName );
        IoDeleteDevice( deviceObject );
        return status;
    }

    //
    // Convert the Thread object handle into a pointer to the Thread object
    // itself. Then close the handle.
    //
    
    ObReferenceObjectByHandle(
		threadHandle,
        THREAD_ALL_ACCESS,
        NULL,
        KernelMode,
        &deviceExtension->ThreadObject,
        NULL );

    ZwClose(threadHandle);

	//
	// Finish initialization
	//
	deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    LSP_KDPRINT(("DriverEntry Exit = %x\n", status));

    return status;
}
示例#12
0
BOOLEAN
TtdiReceive()
{
    USHORT i, Iteration, Increment;
    SHORT j,k;
    HANDLE SvrHandle, SvrConnectionHandle;
    PFILE_OBJECT AddressObject, ConnectionObject;
    PDEVICE_OBJECT DeviceObject;
    NTSTATUS Status;
    PMDL SendMdl, ReceiveMdl;
    IO_STATUS_BLOCK Iosb1;
    TDI_CONNECTION_INFORMATION RequestInformation;
    TDI_CONNECTION_INFORMATION ReturnInformation;
    PTRANSPORT_ADDRESS ListenBlock;
    PTRANSPORT_ADDRESS ConnectBlock;
    PTDI_ADDRESS_NETBIOS temp;
    PUCHAR MessageBuffer;
    ULONG MessageBufferLength;
    ULONG CurrentBufferLength;
    PUCHAR SendBuffer;
    ULONG SendBufferLength;
    PIRP Irp;
    KEVENT Event1;

    Status = KeWaitForSingleObject (&TdiReceiveEvent, Suspended, KernelMode, FALSE, NULL);

    SendBufferLength = (ULONG)BUFFER_SIZE;
    MessageBufferLength = (ULONG)BUFFER_SIZE;


    DbgPrint( "\n****** Start of Receive Test ******\n" );

    XBuff = ExAllocatePool (NonPagedPool, BUFFER_SIZE);
    if (XBuff == (PVOID)NULL) {
        DbgPrint ("Unable to allocate nonpaged pool for send buffer exiting\n");
        return FALSE;
    }
    RBuff = ExAllocatePool (NonPagedPool, BUFFER_SIZE);
    if (RBuff == (PVOID)NULL) {
        DbgPrint ("Unable to allocate nonpaged pool for receive buffer exiting\n");
        return FALSE;
    }

    ListenBlock = ExAllocatePool (NonPagedPool, sizeof (TRANSPORT_ADDRESS) +
                                                sizeof (TDI_ADDRESS_NETBIOS));
    ConnectBlock = ExAllocatePool (NonPagedPool, sizeof (TRANSPORT_ADDRESS) +
                                                sizeof (TDI_ADDRESS_NETBIOS));

    ListenBlock->TAAddressCount = 1;
    ListenBlock->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
    ListenBlock->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
    temp = (PTDI_ADDRESS_NETBIOS)ListenBlock->Address[0].Address;

    temp->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
    for (i=0;i<16;i++) {
        temp->NetbiosName[i] = ClientName[i];
    }

    ConnectBlock->TAAddressCount = 1;
    ConnectBlock->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
    ConnectBlock->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
    temp = (PTDI_ADDRESS_NETBIOS)ConnectBlock->Address[0].Address;

    temp->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
    for (i=0;i<16;i++) {
        temp->NetbiosName[i] = ServerName[i];
    }

    //
    // Create an event for the synchronous I/O requests that we'll be issuing.
    //

    KeInitializeEvent (
                &Event1,
                SynchronizationEvent,
                FALSE);

    Status = TtdiOpenAddress (&SvrHandle, ServerName);
    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Receive Test:  FAILED on open of server Address: %lC ******\n", Status );
        return FALSE;
    }

    Status = ObReferenceObjectByHandle (
                SvrHandle,
                0L,
                NULL,
                KernelMode,
                (PVOID *) &AddressObject,
                NULL);

    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Receive Test:  FAILED on open of server Address: %lC ******\n", Status );
        return FALSE;
    }

    Status = TtdiOpenConnection (&SvrConnectionHandle, 2);
    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Receive Test:  FAILED on open of server Connection: %lC ******\n", Status );
        return FALSE;
    }

    Status = ObReferenceObjectByHandle (
                SvrConnectionHandle,
                0L,
                NULL,
                KernelMode,
                (PVOID *) &ConnectionObject,
                NULL);

    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Receive Test:  FAILED on open of server Connection: %lC ******\n", Status );
        return FALSE;
    }

    //
    // Get a pointer to the stack location for the first driver.  This will be
    // used to pass the original function codes and parameters.
    //

    DeviceObject = IoGetRelatedDeviceObject( ConnectionObject );


    Irp = TdiBuildInternalDeviceControlIrp (
                TDI_ASSOCIATE_ADDRESS,
                DeviceObject,
                ConnectionObject,
                &Event1,
                &Iosb1);

    DbgPrint ("Build Irp %lx, Handle %lx \n",
            Irp, SvrHandle);

    TdiBuildAssociateAddress (
        Irp,
        DeviceObject,
        ConnectionObject,
        TSTRCVCompletion,
        &Event1,
        SvrHandle);
    InitWaitObject (&Event1);

    {
        PULONG Temp=(PULONG)IoGetNextIrpStackLocation (Irp);
        DbgPrint ("Built IrpSp %lx %lx %lx %lx %lx \n", *(Temp++),  *(Temp++),
            *(Temp++), *(Temp++), *(Temp++));
    }

    Status = IoCallDriver (DeviceObject, Irp);

//    IoFreeIrp (Irp);

    if (Status == STATUS_PENDING) {
        Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
        if (!NT_SUCCESS(Status)) {
            DbgPrint( "\n****** Receive Test:  FAILED Event1 Wait Associate: %lC ******\n", Status );
            return FALSE;
        }
        if (!NT_SUCCESS(Iosb1.Status)) {
            DbgPrint( "\n****** Receive Test:  FAILED Associate Iosb status: %lC ******\n", Status );
            return FALSE;
        }

    } else {
        if (!NT_SUCCESS (Status)) {
            DbgPrint( "\n****** Receive Test:  AssociateAddress FAILED  Status: %lC ******\n", Status );
            return FALSE;
        } else {
            DbgPrint ("********** Receive Test:  Success AssociateAddress\n");
        }
    }

    RequestInformation.RemoteAddress = ConnectBlock;
    RequestInformation.RemoteAddressLength = sizeof (TRANSPORT_ADDRESS) +
                                            sizeof (TDI_ADDRESS_NETBIOS);

    //
    // Post a TdiListen to the server endpoint.
    //

    KeInitializeEvent (
                &Event1,
                SynchronizationEvent,
                FALSE);

    Irp = TdiBuildInternalDeviceControlIrp (
                TDI_LISTEN,
                DeviceObject,
                ConnectionObject,
                &Event1,
                &Iosb1);

    TdiBuildListen (
        Irp,
        DeviceObject,
        ConnectionObject,
        TSTRCVCompletion,
        &Event1,
        0,
        &RequestInformation,
        &ReturnInformation);
    InitWaitObject (&Event1);

    Status = IoCallDriver (DeviceObject, Irp);

//    IoFreeIrp (Irp);

    if (Status == STATUS_PENDING) {
        Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
        if (!NT_SUCCESS(Status)) {
            DbgPrint( "\n****** Receive Test:  FAILED Event1 Wait Listen: %lC ******\n", Status );
            return FALSE;
        }
        if (!NT_SUCCESS(Iosb1.Status)) {
            DbgPrint( "\n****** Receive Test:  FAILED Listen Iosb status: %lC ******\n", Status );
            return FALSE;
        } else {
            DbgPrint ("********** Receive Test:  Success Listen IOSB\n");
        }

    } else {
        if (!NT_SUCCESS (Status)) {
            DbgPrint( "\n****** Receive Test: Listen FAILED  Status: %lC ******\n", Status );
            return FALSE;
        } else {
            DbgPrint ("********** Receive Test:  Success Listen Immediate\n");
        }
    }


    DbgPrint ("\n****** Receive Test: LISTEN just completed! ******\n");

    KeInitializeEvent (
                &Event1,
                SynchronizationEvent,
                FALSE);

    Irp = TdiBuildInternalDeviceControlIrp (
                TDI_ACCEPT,
                DeviceObject,
                ConnectionObject,
                &Event1,
                &Iosb1);

    TdiBuildAccept (Irp, DeviceObject, ConnectionObject, NULL, NULL, &RequestInformation, NULL, 0);
    InitWaitObject (&Event1);

    Status = IoCallDriver (DeviceObject, Irp);

//    IoFreeIrp (Irp);

    if (Status == STATUS_PENDING) {
        Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
        if (!NT_SUCCESS(Status)) {
            DbgPrint( "\n****** Receive Test:  FAILED Event1 Wait Accept: %lC ******\n", Status );
            return FALSE;
        }
        if (!NT_SUCCESS(Iosb1.Status)) {
            DbgPrint( "\n****** Receive Test:  FAILED Accept Iosb status: %lC ******\n", Status );
            return FALSE;
        }

    } else {
        if (!NT_SUCCESS (Status)) {
            DbgPrint( "\n****** Receive Test: Accept FAILED  Status: %lC ******\n", Status );
            return FALSE;
        }
    }

    //
    // We have the connection data now.  Sanity check it.
    //

    DbgPrint ("\n****** Receive Test:  LISTEN completed successfully! ******\n");

    //
    // Receive/receive 1 or  10 messages.
    //

    SendBuffer =  (PUCHAR)ExAllocatePool (NonPagedPool, SendBufferLength);
    if (SendBuffer == NULL) {
        DbgPrint ("\n****** Send Test:  ExAllocatePool failed! ******\n");
    }
    SendMdl = IoAllocateMdl (SendBuffer, SendBufferLength, FALSE, FALSE, NULL);
    MmBuildMdlForNonPagedPool (SendMdl);

    MessageBuffer=(PUCHAR)ExAllocatePool (NonPagedPool, MessageBufferLength);
    if (MessageBuffer == NULL) {
        DbgPrint ("\n****** Send Test:  ExAllocatePool failed! ******\n");
    }
    ReceiveMdl = IoAllocateMdl (MessageBuffer, MessageBufferLength, FALSE, FALSE, NULL);
    MmBuildMdlForNonPagedPool (ReceiveMdl);

    //
    // Cycle the buffer length from 0 up through the maximum for Tdi. after a
    // couple of shots at the full range in one byte steps, increment by ever
    // increasing amounts to get to the max.
    //

    CurrentBufferLength = 0;
    Increment = 1;
    for (Iteration=1; Iteration<(USHORT)c9_Iteration; Iteration++) {
        CurrentBufferLength += Increment;
        if (CurrentBufferLength > MessageBufferLength) {
            CurrentBufferLength = 0;
            Increment = 1;
        }
        if (CurrentBufferLength > 7500) {
            Increment++;
        }
        if ((USHORT)((Iteration / 100) * 100) == Iteration) {
            DbgPrint ("Iteration #%d Buffer Length: %lx Buffer Start: %x\n",
                Iteration, CurrentBufferLength,Iteration % 256);
        }
        for (i=0; i<(USHORT)CurrentBufferLength; i++) {
            SendBuffer [i] = (UCHAR)(i + Iteration % 256 );
            MessageBuffer [i] = 0;            // zap this sucker with something.
        }

        KeInitializeEvent (
                    &Event1,
                    SynchronizationEvent,
                    FALSE);

        Irp = TdiBuildInternalDeviceControlIrp (
                    TDI_RECEIVE,
                    DeviceObject,
                    ConnectionObject,
                    &Event1,
                    &Iosb1);

        TdiBuildReceive (Irp,
            DeviceObject,
            ConnectionObject,
            TSTRCVCompletion,
            &Event1,
            ReceiveMdl,
            MessageBufferLength);

        InitWaitObject (&Event1);

        Status = IoCallDriver (DeviceObject, Irp);

//        IoFreeIrp (Irp);

        if (Status == STATUS_PENDING) {
            Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
            if (!NT_SUCCESS(Status)) {
                DbgPrint( "\n****** Receive Test:  FAILED Event1 Wait Receive: %lC ******\n", Status );
                return FALSE;
            }
            if (!NT_SUCCESS(Iosb1.Status)) {
                DbgPrint( "\n****** Receive Test:  FAILED Receive Iosb status: %lC ******\n", Status );
                return FALSE;
            }

        } else {
            if (!NT_SUCCESS (Status)) {
                DbgPrint( "\n****** Receive Test: Listen FAILED  Status: %lC ******\n", Status );
                return FALSE;
            }
        }

        //
        // The receive completed.  Make sure the data is correct.
        //

        if (Iosb1.Information != CurrentBufferLength) {
            DbgPrint ("Iteration #%d Buffer Length: %lx Buffer Start: %x\n",
                Iteration, CurrentBufferLength,Iteration % 256);
            DbgPrint ("ReceiveTest: Bytes received <> bytes sent.\n");
            DbgPrint ("ReceiveTest: BytesToSend=%ld.  BytesReceived=%ld.\n",
                      CurrentBufferLength, Iosb1.Information);
        }

        if (i == (USHORT)CurrentBufferLength) {
//                DbgPrint ("ReceiveTest: Message contains correct data.\n");
        } else {
            DbgPrint ("ReceiveTest: Message data corrupted at offset %lx of %lx.\n", (ULONG)i, (ULONG)SendBufferLength);
            DbgPrint ("ReceiveTest: Data around corrupted location:\n");
            for (j=-4;j<=3;j++) {
                DbgPrint ("%08lx  ", (ULONG) i+j*16);
                for (k=(SHORT)i+(j*(SHORT)16);k<(SHORT)i+((j+(SHORT)1)*(SHORT)16);k++) {
                    DbgPrint ("%02x",MessageBuffer [k]);
                }
                for (k=(SHORT)i+(j*(SHORT)16);k<(SHORT)i+((j+(SHORT)1)*(SHORT)16);k++) {
                    DbgPrint ("%c",MessageBuffer [k]);
                }
                DbgPrint ("\n");
            }
            DbgPrint ("ReceiveTest: End of Corrupt Data.\n");
        }
    }

    //
    // We're done with this endpoint.  Close it and get out.
    //

    Status = CloseAddress (SvrHandle);
    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Receive Test:  FAILED on 1st Close: %lC ******\n", Status );
        return FALSE;
    }

    DbgPrint( "\n****** End of Receive Test ******\n" );
    return TRUE;
} /* Receive */
示例#13
0
BOOLEAN
TtdiSend()
{
    USHORT i, Iteration, Increment;
    HANDLE RdrHandle, RdrConnectionHandle;
    KEVENT Event1;
    PFILE_OBJECT AddressObject, ConnectionObject;
    PDEVICE_OBJECT DeviceObject;
    NTSTATUS Status;
    PMDL SendMdl, ReceiveMdl;
    IO_STATUS_BLOCK Iosb1;
    TDI_CONNECTION_INFORMATION RequestInformation;
    TDI_CONNECTION_INFORMATION ReturnInformation;
    PTRANSPORT_ADDRESS ListenBlock;
    PTRANSPORT_ADDRESS ConnectBlock;
    PTDI_ADDRESS_NETBIOS temp;
    PUCHAR MessageBuffer;
    ULONG MessageBufferLength;
    ULONG CurrentBufferLength;
    PUCHAR SendBuffer;
    ULONG SendBufferLength;
    PIRP Irp;

    Status = KeWaitForSingleObject (&TdiSendEvent, Suspended, KernelMode, FALSE, NULL);

    SendBufferLength = (ULONG)BUFFER_SIZE;
    MessageBufferLength = (ULONG)BUFFER_SIZE;


    DbgPrint( "\n****** Start of Send Test ******\n" );

    XBuff = ExAllocatePool (NonPagedPool, BUFFER_SIZE);
    if (XBuff == (PVOID)NULL) {
        DbgPrint ("Unable to allocate nonpaged pool for send buffer exiting\n");
        return FALSE;
    }
    RBuff = ExAllocatePool (NonPagedPool, BUFFER_SIZE);
    if (RBuff == (PVOID)NULL) {
        DbgPrint ("Unable to allocate nonpaged pool for receive buffer exiting\n");
        return FALSE;
    }

    ListenBlock = ExAllocatePool (NonPagedPool, sizeof (TRANSPORT_ADDRESS) +
                                                sizeof (TDI_ADDRESS_NETBIOS));
    ConnectBlock = ExAllocatePool (NonPagedPool, sizeof (TRANSPORT_ADDRESS) +
                                                sizeof (TDI_ADDRESS_NETBIOS));

    ListenBlock->TAAddressCount = 1;
    ListenBlock->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
    ListenBlock->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
    temp = (PTDI_ADDRESS_NETBIOS)ListenBlock->Address[0].Address;

    temp->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
    for (i=0;i<16;i++) {
        temp->NetbiosName[i] = ClientName[i];
    }

    ConnectBlock->TAAddressCount = 1;
    ConnectBlock->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
    ConnectBlock->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
    temp = (PTDI_ADDRESS_NETBIOS)ConnectBlock->Address[0].Address;

    temp->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
    for (i=0;i<16;i++) {
        temp->NetbiosName[i] = ServerName[i];
    }

    //
    // Create an event for the synchronous I/O requests that we'll be issuing.
    //

    KeInitializeEvent (
                &Event1,
                SynchronizationEvent,
                FALSE);

    Status = TtdiOpenAddress (&RdrHandle, AnyName);
    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Send Test:  FAILED on open of client: %lC ******\n", Status );
        return FALSE;
    }

    Status = ObReferenceObjectByHandle (
                RdrHandle,
                0L,
                NULL,
                KernelMode,
                (PVOID *) &AddressObject,
                NULL);

    //
    // Open the connection on the transport.
    //

    Status = TtdiOpenConnection (&RdrConnectionHandle, 1);
    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Send Test:  FAILED on open of server Connection: %lC ******\n", Status );
        return FALSE;
    }

    Status = ObReferenceObjectByHandle (
                RdrConnectionHandle,
                0L,
                NULL,
                KernelMode,
                (PVOID *) &ConnectionObject,
                NULL);

    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Send Test:  FAILED on open of server Connection: %lC ******\n", Status );
        return FALSE;
    }

    //
    // Get a pointer to the stack location for the first driver.  This will be
    // used to pass the original function codes and parameters.
    //

    DeviceObject = IoGetRelatedDeviceObject( ConnectionObject );

    Irp = TdiBuildInternalDeviceControlIrp (
                TDI_ASSOCIATE_ADDRESS,
                DeviceObject,
                ConnectionObject,
                &Event1,
                &Iosb1);


    //
    // Get a pointer to the stack location for the first driver.  This will be
    // used to pass the original function codes and parameters.
    //

    TdiBuildAssociateAddress (Irp,
        DeviceObject,
        ConnectionObject,
        TSTRCVCompletion,
        &Event1,
        RdrHandle);

    Status = IoCallDriver (DeviceObject, Irp);

//    IoFreeIrp (Irp);

    if (Status == STATUS_PENDING) {
        Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
        if (!NT_SUCCESS(Status)) {
            DbgPrint( "\n****** Send Test:  FAILED Event1 Wait Associate: %lC ******\n", Status );
            return FALSE;
        }
        if (!NT_SUCCESS(Iosb1.Status)) {
            DbgPrint( "\n****** Send Test:  FAILED Associate Iosb status: %lC ******\n", Status );
            return FALSE;
        }

    } else {
        if (!NT_SUCCESS (Status)) {
            DbgPrint( "\n****** Send Test:  AssociateAddress FAILED  Status: %lC ******\n", Status );
            return FALSE;
        } else {
            DbgPrint ("********** Send Test:  Success AssociateAddress\n");
        }
    }

    //
    // Post a TdiConnect to the client endpoint.
    //

    RequestInformation.RemoteAddress = ConnectBlock;
    RequestInformation.RemoteAddressLength = sizeof (TRANSPORT_ADDRESS) +
                                            sizeof (TDI_ADDRESS_NETBIOS);

    KeInitializeEvent (
                &Event1,
                SynchronizationEvent,
                FALSE);

    Irp = TdiBuildInternalDeviceControlIrp (
                TDI_CONNECT,
                DeviceObject,
                ConnectionObject,
                &Event1,
                &Iosb1);

    TdiBuildConnect (
        Irp,
        DeviceObject,
        ConnectionObject,
        TSTRCVCompletion,
        &Event1,
        0,
        &RequestInformation,
        &ReturnInformation);

    InitWaitObject (&Event1);

    Status = IoCallDriver (DeviceObject, Irp);

//    IoFreeIrp (Irp);

    if (Status == STATUS_PENDING) {
        Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
        if (!NT_SUCCESS(Status)) {
            DbgPrint( "\n****** Send Test:  FAILED Event1 Wait Connect: %lC ******\n", Status );
            return FALSE;
        }
        if (!NT_SUCCESS(Iosb1.Status)) {
            DbgPrint( "\n****** Send Test:  FAILED Iosb status Connect: %lC ******\n", Status );
            return FALSE;
        } else {
            DbgPrint ("********** Send Test:  Success Connect Iosb\n");
        }

    } else {
        if (!NT_SUCCESS (Status)) {
            DbgPrint( "\n****** Send Test:  Connect FAILED  Status: %lC ******\n", Status );
            return FALSE;
        } else {
            DbgPrint ("********** Send Test:  Success Connect Immediate\n");
        }
    }

    DbgPrint( "\n****** Send Test:  SUCCESSFUL TdiConnect:  ******\n");

    //
    // Send/receive 1 or  10 messages.
    //

    SendBuffer =  (PUCHAR)ExAllocatePool (NonPagedPool, SendBufferLength);
    if (SendBuffer == NULL) {
        DbgPrint ("\n****** Send Test:  ExAllocatePool failed! ******\n");
    }
    SendMdl = IoAllocateMdl (SendBuffer, SendBufferLength, FALSE, FALSE, NULL);
    MmBuildMdlForNonPagedPool (SendMdl);

    MessageBuffer=(PUCHAR)ExAllocatePool (NonPagedPool, MessageBufferLength);
    if (MessageBuffer == NULL) {
        DbgPrint ("\n****** Send Test:  ExAllocatePool failed! ******\n");
    }
    ReceiveMdl = IoAllocateMdl (MessageBuffer, MessageBufferLength, FALSE, FALSE, NULL);
    MmBuildMdlForNonPagedPool (ReceiveMdl);

    //
    // Cycle the buffer length from 0 up through the maximum for Tdi. after a
    // couple of shots at the full range in one byte steps, increment by ever
    // increasing amounts to get to the max.
    //

    CurrentBufferLength = 0;
    Increment = 1;
    for (Iteration=1; Iteration<(USHORT)c9_Iteration; Iteration++) {
        CurrentBufferLength += Increment;
        if (CurrentBufferLength > MessageBufferLength) {
            CurrentBufferLength = 0;
            Increment = 1;
        }
        if (CurrentBufferLength > 7500) {
            Increment++;
        }
        if ((USHORT)((Iteration / 100) * 100) == Iteration) {
            DbgPrint ("Iteration #%d Buffer Length: %lx Buffer Start: %x\n",
                Iteration, CurrentBufferLength,Iteration % 256);
        }
        for (i=0; i<(USHORT)CurrentBufferLength; i++) {
            SendBuffer [i] = (UCHAR)(i + Iteration % 256 );
            MessageBuffer [i] = 0;            // zap this sucker with something.
        }

        //
        // Now issue a send on the client side.
        //

        KeInitializeEvent (
                    &Event1,
                    SynchronizationEvent,
                    FALSE);

        Irp = TdiBuildInternalDeviceControlIrp (
                    TDI_SEND,
                    DeviceObject,
                    ConnectionObject,
                    &Event1,
                    &Iosb1);

        TdiBuildSend (Irp,
            DeviceObject,
            ConnectionObject,
            TSTRCVCompletion,
            &Event1,
            ReceiveMdl,
            0,
            CurrentBufferLength);

        InitWaitObject (&Event1);

        Status = IoCallDriver (DeviceObject, Irp);

//        IoFreeIrp (Irp);

        if (Status == STATUS_PENDING) {
            Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
            if (!NT_SUCCESS(Status)) {
                DbgPrint( "\n****** Send Test:  FAILED Event1 Wait Send: %lC %d ******\n",
                    Status, Iteration );
                return FALSE;
            }
            if (!NT_SUCCESS(Iosb1.Status)) {
                DbgPrint( "\n****** Send Test:  FAILED Iosb status Send: %lC %d ******\n",
                    Status, Iteration );
                return FALSE;
            } else {
                DbgPrint ("********** Send Test:  Success SendIosb\n");
            }

        } else {
            if (!NT_SUCCESS (Status)) {
                DbgPrint( "\n****** Send Test:  Send FAILED  Status: %lC %d ******\n",
                Status, Iteration );
                return FALSE;
            } else {
                DbgPrint ("********** Send Test:  Success Send Immediate\n");
            }
        }

        if (Iosb1.Information != CurrentBufferLength) {
            DbgPrint ("SendTest: Bytes sent <> Send buffer size.\n");
            DbgPrint ("SendTest: BytesToSend=%ld.  BytesSent=%ld.\n",
                      CurrentBufferLength, Iosb1.Information);
        }

    }

    //
    // We're done with this endpoint.  Close it and get out.
    //

    Status = CloseAddress (RdrHandle);
    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Send Test:  FAILED on 2nd Close: %lC ******\n", Status );
        return FALSE;
    }

    DbgPrint( "\n****** End of Send Test ******\n" );
    return TRUE;
} /* Send */
示例#14
0
BOOLEAN
TtdiServer()
{
    USHORT i;
    HANDLE RdrHandle, SrvConnectionHandle;
    KEVENT Event1;
    PFILE_OBJECT AddressObject, ConnectionObject;
    PDEVICE_OBJECT DeviceObject;
    NTSTATUS Status;
    PMDL ReceiveMdl;
    IO_STATUS_BLOCK Iosb1;
    TDI_CONNECTION_INFORMATION RequestInformation;
    TDI_CONNECTION_INFORMATION ReturnInformation;
    PTRANSPORT_ADDRESS ListenBlock;
    PTRANSPORT_ADDRESS ConnectBlock;
    PTDI_ADDRESS_NETBIOS temp;
    PUCHAR MessageBuffer;
    ULONG MessageBufferLength;
    ULONG CurrentBufferLength;
    PIRP Irp;

    Status = KeWaitForSingleObject (&TdiServerEvent, Suspended, KernelMode, FALSE, NULL);

    MessageBufferLength = (ULONG)BUFFER_SIZE;


    DbgPrint( "\n****** Start of Server Test ******\n" );

    RBuff = ExAllocatePool (NonPagedPool, BUFFER_SIZE);
    if (RBuff == (PVOID)NULL) {
        DbgPrint ("Unable to allocate nonpaged pool for receive buffer exiting\n");
        return FALSE;
    }

    ListenBlock = ExAllocatePool (NonPagedPool, sizeof (TRANSPORT_ADDRESS) +
                                                sizeof (TDI_ADDRESS_NETBIOS));
    ConnectBlock = ExAllocatePool (NonPagedPool, sizeof (TRANSPORT_ADDRESS) +
                                                sizeof (TDI_ADDRESS_NETBIOS));

    ListenBlock->TAAddressCount = 1;
    ListenBlock->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
    ListenBlock->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
    temp = (PTDI_ADDRESS_NETBIOS)ListenBlock->Address[0].Address;

    temp->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
    for (i=0;i<16;i++) {
        temp->NetbiosName[i] = AnyName[i];
    }

    ConnectBlock->TAAddressCount = 1;
    ConnectBlock->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
    ConnectBlock->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
    temp = (PTDI_ADDRESS_NETBIOS)ConnectBlock->Address[0].Address;

    temp->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
    for (i=0;i<16;i++) {
        temp->NetbiosName[i] = ServerName[i];
    }

    //
    // Create an event for the synchronous I/O requests that we'll be issuing.
    //

    KeInitializeEvent (
                &Event1,
                SynchronizationEvent,
                FALSE);

    Status = TtdiOpenAddress (&RdrHandle, ServerName);
    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Server Test:  FAILED on open of client: %lC ******\n", Status );
        return FALSE;
    }

    Status = ObReferenceObjectByHandle (
                RdrHandle,
                0L,
                NULL,
                KernelMode,
                (PVOID *) &AddressObject,
                NULL);

    //
    // Now loop forever trying to get a connection from a remote client to
    // this server. We will create connections until we run out of resources,
    // and we will echo the data we are sent back along the same connection.
    // Sends and Receives are always asynchronous, while listens are
    // synchronous.
    //

    while (TRUE) {

        //
        // Open the connection on the transport.
        //

        Status = TtdiOpenConnection (&SrvConnectionHandle, 1);
        if (!NT_SUCCESS(Status)) {
            DbgPrint( "\n****** Server Test:  FAILED on open of server Connection: %lC ******\n", Status );
            return FALSE;
        }

        Status = ObReferenceObjectByHandle (
                    SrvConnectionHandle,
                    0L,
                    NULL,
                    KernelMode,
                    (PVOID *) &ConnectionObject,
                    NULL);

        if (!NT_SUCCESS(Status)) {
            DbgPrint( "\n****** Server Test:  FAILED on open of server Connection: %lC ******\n", Status );
            return FALSE;
        }

        //
        // Get a pointer to the stack location for the first driver.  This will be
        // used to pass the original function codes and parameters.
        //

        DeviceObject = IoGetRelatedDeviceObject( ConnectionObject );

        //
        // Now register the device handler for receives
        //

//        Irp = TdiBuildInternalDeviceControlIrp (
//                    TDI_SET_EVENT_HANDLER,
//                    DeviceObject,
//                    ConnectionObject,
//                    &Event1,
//                    &Iosb1);

//        TdiBuildSetEventHandler (Irp,
//            DeviceObject,
//            ConnectionObject,
//            TSTRCVCompletion,
//            &Event1,
//            TDI_RECEIVE_HANDLER,
//            TdiTestReceiveHandler,
//            ConnectionObject);

//        Status = IoCallDriver (DeviceObject, Irp);

//       if (Status == STATUS_PENDING) {
//            Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
//            if (!NT_SUCCESS(Status)) {
//                DbgPrint( "\n****** Server Test:  FAILED Event1 Wait Register: %lC ******\n", Status );
//                return FALSE;
//            }
//            if (!NT_SUCCESS(Iosb1.Status)) {
//                DbgPrint( "\n****** Server Test:  FAILED Register Iosb status: %lC ******\n", Status );
//                return FALSE;
//            }
//
//        } else {
//            if (!NT_SUCCESS (Status)) {
//                DbgPrint( "\n****** Server Test:  RegisterHandler FAILED  Status: %lC ******\n", Status );
//                return FALSE;
//            }
//        }

        Irp = TdiBuildInternalDeviceControlIrp (
                    TDI_ASSOCIATE_ADDRESS,
                    DeviceObject,
                    ConnectionObject,
                    &Event1,
                    &Iosb1);

        TdiBuildAssociateAddress (Irp,
            DeviceObject,
            ConnectionObject,
            TSTRCVCompletion,
            &Event1,
            RdrHandle);

        Status = IoCallDriver (DeviceObject, Irp);

    //    IoFreeIrp (Irp);

        if (Status == STATUS_PENDING) {
            Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
            if (!NT_SUCCESS(Status)) {
                DbgPrint( "\n****** Server Test:  FAILED Event1 Wait Associate: %lC ******\n", Status );
                return FALSE;
            }
            if (!NT_SUCCESS(Iosb1.Status)) {
                DbgPrint( "\n****** Server Test:  FAILED Associate Iosb status: %lC ******\n", Status );
                return FALSE;
            }

        } else {
            if (!NT_SUCCESS (Status)) {
                DbgPrint( "\n****** Server Test:  AssociateAddress FAILED  Status: %lC ******\n", Status );
                return FALSE;
            }
        }

        //
        // Post a TdiListen to the server endpoint.
        //

        RequestInformation.RemoteAddress = ListenBlock;
        RequestInformation.RemoteAddressLength = sizeof (TRANSPORT_ADDRESS) +
                                                sizeof (TDI_ADDRESS_NETBIOS);

        KeInitializeEvent (
                    &Event1,
                    SynchronizationEvent,
                    FALSE);

        Irp = TdiBuildInternalDeviceControlIrp (
                    TDI_LISTEN,
                    DeviceObject,
                    ConnectionObject,
                    &Event1,
                    &Iosb1);

        TdiBuildListen (
            Irp,
            DeviceObject,
            ConnectionObject,
            TSTRCVCompletion,
            &Event1,
            0,
            &RequestInformation,
            NULL);

        Status = IoCallDriver (DeviceObject, Irp);

        if (Status == STATUS_PENDING) {
            Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
            if (!NT_SUCCESS(Status)) {
                DbgPrint( "\n****** Server Test:  FAILED Event1 Wait Listen: %lC ******\n", Status );
                return FALSE;
            }
            if (!NT_SUCCESS(Iosb1.Status)) {
                DbgPrint( "\n****** Server Test:  FAILED Listen Iosb status: %lC ******\n", Status );
                return FALSE;
            }

        } else {
            if (!NT_SUCCESS (Status)) {
                DbgPrint( "\n****** Server Test: Listen FAILED  Status: %lC ******\n", Status );
                return FALSE;
            }
        }

        DbgPrint ("\n****** Server Test: LISTEN just completed! ******\n");

        //
        // accept the connection from the remote
        //

        KeInitializeEvent (
                    &Event1,
                    SynchronizationEvent,
                    FALSE);

        Irp = TdiBuildInternalDeviceControlIrp (
                    TDI_ACCEPT,
                    DeviceObject,
                    ConnectionObject,
                    &Event1,
                    &Iosb1);

        TdiBuildAccept (
            Irp,
            DeviceObject,
            ConnectionObject,
            NULL,
            NULL,
            &RequestInformation,
            NULL,
            0);

        Status = IoCallDriver (DeviceObject, Irp);

    //    IoFreeIrp (Irp);

        if (Status == STATUS_PENDING) {
            Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
            if (!NT_SUCCESS(Status)) {
                DbgPrint( "\n****** Receive Test:  FAILED Event1 Wait Accept: %lC ******\n", Status );
                return FALSE;
            }
            if (!NT_SUCCESS(Iosb1.Status)) {
                DbgPrint( "\n****** Receive Test:  FAILED Accept Iosb status: %lC ******\n", Status );
                return FALSE;
            }

        } else {
            if (!NT_SUCCESS (Status)) {
                DbgPrint( "\n****** Accept Test: Listen FAILED  Status: %lC ******\n", Status );
                return FALSE;
            }
        }

        //
        // Get a buffer for the continued read/write loop.
        //

        MessageBuffer=(PUCHAR)ExAllocatePool (NonPagedPool, MessageBufferLength);
        if (MessageBuffer == NULL) {
            DbgPrint ("\n****** Send Test:  ExAllocatePool failed! ******\n");
        }
        ReceiveMdl = IoAllocateMdl (MessageBuffer, MessageBufferLength, FALSE, FALSE, NULL);
        MmBuildMdlForNonPagedPool (ReceiveMdl);

        //
        // have a receive buffer, and a connection; go ahead and read and write
        // until the remote disconnects.
        //

        while (TRUE) {

            KeInitializeEvent (
                        &Event1,
                        SynchronizationEvent,
                        FALSE);

            Irp = TdiBuildInternalDeviceControlIrp (
                        TDI_RECEIVE,
                        DeviceObject,
                        ConnectionObject,
                        &Event1,
                        &Iosb1);

            TdiBuildReceive (Irp,
                DeviceObject,
                ConnectionObject,
                TSTRCVCompletion,
                &Event1,
                ReceiveMdl,
                MessageBufferLength);

            InitWaitObject (&Event1);

            Status = IoCallDriver (DeviceObject, Irp);

            if (Status == STATUS_PENDING) {
                Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
                if (!NT_SUCCESS(Status)) {
                    DbgPrint( "\n****** Receive Test:  FAILED Event1 Wait Receive: %lC ******\n", Status );
                    return FALSE;
                }
                if (!NT_SUCCESS(Iosb1.Status)) {
                    DbgPrint( "\n****** Receive Test:  FAILED Receive Iosb status: %lC ******\n", Status );
                    return FALSE;
                }

            } else {
                if (!NT_SUCCESS (Status)) {

                    //
                    // Check to see if the remote has disconnected, which is
                    // the only reason for us shutting down/
                    //

                    if (Status == STATUS_REMOTE_DISCONNECT) {

                        //
                        // We've been disconnected from; get out
                        //

                        NtClose (SrvConnectionHandle);
                        break;
                    }

                    DbgPrint( "\n****** Receive Test: Listen FAILED  Status: %lC ******\n", Status );
                    return FALSE;
                } else {

                    //
                    // successful return, what length is the data?
                    //

                    CurrentBufferLength = Iosb1.Information;
                }
            }

            //
            // send the data back
            //

            KeInitializeEvent (
                        &Event1,
                        SynchronizationEvent,
                        FALSE);

            Irp = TdiBuildInternalDeviceControlIrp (
                        TDI_SEND,
                        DeviceObject,
                        ConnectionObject,
                        &Event1,
                        &Iosb1);

            TdiBuildSend (Irp,
                DeviceObject,
                ConnectionObject,
                TSTRCVCompletion,
                &Event1,
                ReceiveMdl,
                0,
                CurrentBufferLength);

            Status = IoCallDriver (DeviceObject, Irp);

            if (Status == STATUS_PENDING) {
                Status = KeWaitForSingleObject (&Event1, Suspended, KernelMode, TRUE, NULL);
                if (!NT_SUCCESS(Status)) {
                    DbgPrint( "\n****** Receive Test:  FAILED Event1 Wait Send: %lC ******\n", Status );
                    return FALSE;
                }
                if (!NT_SUCCESS(Iosb1.Status)) {
                    DbgPrint( "\n****** Receive Test:  FAILED Send Iosb status: %lC ******\n", Status );
                    return FALSE;
                }

            } else {
                if (!NT_SUCCESS (Status)) {

                    DbgPrint( "\n****** Receive Test: Send FAILED  Status: %lC ******\n", Status );
                    NtClose (SrvConnectionHandle);
                    break;

                }
            }
        } // end of receive/send while

        IoFreeMdl (ReceiveMdl);
        ExFreePool (MessageBuffer);

    }

    //
    // We're done with this address.  Close it and get out.
    //

    Status = CloseAddress (RdrHandle);
    if (!NT_SUCCESS(Status)) {
        DbgPrint( "\n****** Send Test:  FAILED on 2nd Close: %lC ******\n", Status );
        return FALSE;
    }

    DbgPrint( "\n****** End of Send Test ******\n" );
    return TRUE;
} /* Server */
示例#15
0
NTSTATUS
FatCommonDeviceControl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for doing Device control operations called
    by both the fsd and fsp threads

Arguments:

    Irp - Supplies the Irp to process

    InFsp - Indicates if this is the fsp thread or someother thread

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp;
    KEVENT WaitEvent;
    PVOID CompletionContext = NULL;

    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;

#ifdef __ND_FAT_PRIMARY__

	if (IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL && 
		IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode == IOCTL_INSERT_PRIMARY_SESSION) {

		PVOLUME_DEVICE_OBJECT	VolDo = CONTAINING_RECORD( IoGetCurrentIrpStackLocation(Irp)->DeviceObject, 
														   VOLUME_DEVICE_OBJECT, 
														   DeviceObject );
		PSESSION_INFORMATION	inputBuffer = (PSESSION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
		ULONG					inputBufferLength = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.InputBufferLength;
		ULONG					outputBufferLength;
		PULONG					outputBuffer;
		PPRIMARY_SESSION		primarySession;

		if (inputBufferLength != sizeof(SESSION_INFORMATION)) {

			FatCompleteRequest( IrpContext, Irp, Status = STATUS_INVALID_PARAMETER );
			return Status;
		} 

		outputBufferLength = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.OutputBufferLength;
		outputBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;

		primarySession = PrimarySession_Create( IrpContext, VolDo, inputBuffer, Irp );

		ASSERT( primarySession );

		FatCompleteRequest( IrpContext, NULL, 0 );
		Status = STATUS_PENDING;
		return Status;
	}

#endif

    //
    //  Get a pointer to the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace(+1, Dbg, "FatCommonDeviceControl\n", 0);
    DebugTrace( 0, Dbg, "Irp           = %08lx\n", Irp);
    DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction);

    //
    //  Decode the file object, the only type of opens we accept are
    //  user volume opens.
    //

    if (FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb ) != UserVolumeOpen) {

        FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );

        DebugTrace(-1, Dbg2, "FatCommonDeviceControl -> %08lx\n", STATUS_INVALID_PARAMETER);
        return STATUS_INVALID_PARAMETER;
    }

    //
    //  A few IOCTLs actually require some intervention on our part
    //

    switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {

    case IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES:


#ifdef __ND_FAT_WIN2K_SUPPORT__

		if (!IS_WINDOWSXP_OR_LATER()) {

			ASSERT( FALSE );
			IoSkipCurrentIrpStackLocation( Irp );
			break;
		}

#endif

        //
        //  This is sent by the Volume Snapshot driver (Lovelace).
        //  We flush the volume, and hold all file resources
        //  to make sure that nothing more gets dirty. Then we wait
        //  for the IRP to complete or cancel.
        //

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
        FatAcquireExclusiveVolume( IrpContext, Vcb );

		FatFlushAndCleanVolume( IrpContext,
                                Irp,
                                Vcb,
                                FlushWithoutPurge );

        KeInitializeEvent( &WaitEvent, NotificationEvent, FALSE );
        CompletionContext = &WaitEvent;

        //
        //  Get the next stack location, and copy over the stack location
        //

        IoCopyCurrentIrpStackLocationToNext( Irp );

        //
        //  Set up the completion routine
        //

        IoSetCompletionRoutine( Irp,
                                FatDeviceControlCompletionRoutine,
                                CompletionContext,
                                TRUE,
                                TRUE,
                                TRUE );
        break;

    default:

        //
        //  FAT doesn't need to see this on the way back, so skip ourselves.
        //

        IoSkipCurrentIrpStackLocation( Irp );
        break;
    }

    //
    //  Send the request.
    //

    Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);

    if (Status == STATUS_PENDING && CompletionContext) {

        KeWaitForSingleObject( &WaitEvent,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );

        Status = Irp->IoStatus.Status;
    }

    //
    //  If we had a context, the IRP remains for us and we will complete it.
    //  Handle it appropriately.
    //

    if (CompletionContext) {

        //
        //  Release all the resources that we held because of a
        //  VOLSNAP_FLUSH_AND_HOLD. 
        //

        ASSERT( IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES );

        FatReleaseVolume( IrpContext, Vcb );

        //
        //  If we had no context, the IRP will complete asynchronously.
        //

    } else {

        Irp = NULL;
    }

    FatCompleteRequest( IrpContext, Irp, Status );

    DebugTrace(-1, Dbg, "FatCommonDeviceControl -> %08lx\n", Status);

    return Status;
}
示例#16
0
NTSTATUS
FatFsdRead (
    IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the driver entry to the common read routine for NtReadFile calls.
    For synchronous requests, the CommonRead is called with Wait == TRUE,
    which means the request will always be completed in the current thread,
    and never passed to the Fsp.  If it is not a synchronous request,
    CommonRead is called with Wait == FALSE, which means the request
    will be passed to the Fsp only if there is a need to block.

Arguments:

    VolumeDeviceObject - Supplies the volume device object where the
        file being Read exists

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The FSD status for the IRP

--*/

{
    PFCB Fcb = NULL;
    NTSTATUS Status;
    PIRP_CONTEXT IrpContext = NULL;

    BOOLEAN TopLevel = FALSE;

    DebugTrace(+1, Dbg, "FatFsdRead\n", 0);

    //
    //  Call the common Read routine, with blocking allowed if synchronous
    //

    FsRtlEnterFileSystem();

    //
    //  We are first going to do a quick check for paging file IO.  Since this
    //  is a fast path, we must replicate the check for the fsdo.
    //

    if (!FatDeviceIsFatFsdo( IoGetCurrentIrpStackLocation(Irp)->DeviceObject))  {

        Fcb = (PFCB)(IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext);

        if ((NodeType(Fcb) == FAT_NTC_FCB) &&
            FlagOn(Fcb->FcbState, FCB_STATE_PAGING_FILE)) {

            //
            //  Do the usual STATUS_PENDING things.
            //

            IoMarkIrpPending( Irp );

            //
            //  If there is not enough stack to do this read, then post this
            //  read to the overflow queue.
            //

            if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

                KEVENT Event;
                PAGING_FILE_OVERFLOW_PACKET Packet;

                Packet.Irp = Irp;
                Packet.Fcb = Fcb;

                KeInitializeEvent( &Event, NotificationEvent, FALSE );

                FsRtlPostPagingFileStackOverflow( &Packet, &Event, FatOverflowPagingFileRead );

                //
                //  And wait for the worker thread to complete the item
                //

                (VOID) KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );

            } else {

                //
                //  Perform the actual IO, it will be completed when the io finishes.
                //

                FatPagingFileIo( Irp, Fcb );
            }

            FsRtlExitFileSystem();

            return STATUS_PENDING;
        }
    }

    try {

        TopLevel = FatIsIrpTopLevel( Irp );

        IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );

        //
        //  If this is an Mdl complete request, don't go through
        //  common read.
        //

        if ( FlagOn(IrpContext->MinorFunction, IRP_MN_COMPLETE) ) {

            DebugTrace(0, Dbg, "Calling FatCompleteMdl\n", 0 );
            try_return( Status = FatCompleteMdl( IrpContext, Irp ));
        }

        //
        //  Check if we have enough stack space to process this request.  If there
        //  isn't enough then we will pass the request off to the stack overflow thread.
        //

        if (IoGetRemainingStackSize() < OVERFLOW_READ_THRESHHOLD) {

            DebugTrace(0, Dbg, "Passing StackOverflowRead off\n", 0 );
            try_return( Status = FatPostStackOverflowRead( IrpContext, Irp, Fcb ) );
        }

        Status = FatCommonRead( IrpContext, Irp );

    try_exit: NOTHING;
    } except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {

        //
        //  We had some trouble trying to perform the requested
        //  operation, so we'll abort the I/O request with
        //  the error status that we get back from the
        //  execption code
        //

        Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
    }

    if (TopLevel) { IoSetTopLevelIrp( NULL ); }

    FsRtlExitFileSystem();

    //
    //  And return to our caller
    //

    DebugTrace(-1, Dbg, "FatFsdRead -> %08lx\n", Status);

    UNREFERENCED_PARAMETER( VolumeDeviceObject );

    return Status;
}
NTSTATUS
BalloonDeviceAdd(
    IN WDFDRIVER  Driver,
    IN PWDFDEVICE_INIT  DeviceInit)
{
    NTSTATUS                     status = STATUS_SUCCESS;
    WDFDEVICE                    device;
    PDEVICE_CONTEXT              devCtx = NULL;
    WDF_INTERRUPT_CONFIG         interruptConfig;
    WDF_FILEOBJECT_CONFIG        fileConfig;
    WDF_OBJECT_ATTRIBUTES        attributes;
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;

    UNREFERENCED_PARAMETER(Driver);
    PAGED_CODE();

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__);

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);

    pnpPowerCallbacks.EvtDevicePrepareHardware      = BalloonEvtDevicePrepareHardware;
    pnpPowerCallbacks.EvtDeviceReleaseHardware      = BalloonEvtDeviceReleaseHardware;
    pnpPowerCallbacks.EvtDeviceD0Entry              = BalloonEvtDeviceD0Entry;
    pnpPowerCallbacks.EvtDeviceD0Exit               = BalloonEvtDeviceD0Exit;
    pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled = BalloonEvtDeviceD0ExitPreInterruptsDisabled;

    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);

    WDF_FILEOBJECT_CONFIG_INIT(
                            &fileConfig,
                            WDF_NO_EVENT_CALLBACK,
                            BalloonEvtFileClose,
                            WDF_NO_EVENT_CALLBACK
                            );

    WdfDeviceInitSetFileObjectConfig(DeviceInit,
                            &fileConfig,
                            WDF_NO_OBJECT_ATTRIBUTES);

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
    attributes.EvtCleanupCallback = BalloonEvtDeviceContextCleanup;
    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfDeviceCreate failed with status 0x%08x\n", status);
        return status;
    }

    devCtx = GetDeviceContext(device);

    WDF_INTERRUPT_CONFIG_INIT(&interruptConfig,
                            BalloonInterruptIsr,
                            BalloonInterruptDpc);

    interruptConfig.EvtInterruptEnable  = BalloonInterruptEnable;
    interruptConfig.EvtInterruptDisable = BalloonInterruptDisable;

    status = WdfInterruptCreate(device,
                            &interruptConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            &devCtx->WdfInterrupt);
    if (!NT_SUCCESS (status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfInterruptCreate failed: 0x%08x\n", status);
        return status;
    }

    status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_BALLOON, NULL);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "WdfDeviceCreateDeviceInterface failed with status 0x%08x\n", status);
        return status;
    }
    devCtx->bShutDown = FALSE;
    devCtx->num_pages = 0;
    devCtx->PageListHead.Next = NULL;
    ExInitializeNPagedLookasideList(
                      &devCtx->LookAsideList,
                      NULL,
                      NULL,
                      0,
                      sizeof(PAGE_LIST_ENTRY),
                      BALLOON_MGMT_POOL_TAG,
                      0
                      );
    devCtx->bListInitialized = TRUE;
    devCtx->pfns_table = (PPFN_NUMBER)
              ExAllocatePoolWithTag(
                      NonPagedPool,
                      PAGE_SIZE,
                      BALLOON_MGMT_POOL_TAG
                      );

    if(devCtx->pfns_table == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"ExAllocatePoolWithTag failed\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }

    devCtx->MemStats = (PBALLOON_STAT)
              ExAllocatePoolWithTag(
                      NonPagedPool,
                      sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR,
                      BALLOON_MGMT_POOL_TAG
                      );

    if(devCtx->MemStats == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,"ExAllocatePoolWithTag failed\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
        return status;
    }

    RtlFillMemory (devCtx->MemStats, sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR, -1);

    KeInitializeEvent(&devCtx->HostAckEvent,
                      SynchronizationEvent,
                      FALSE
                      );

    status = BalloonQueueInitialize(device);
    if(!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
           "BalloonQueueInitialize failed with status 0x%08x\n", status);
        return status;
    }

    KeInitializeEvent(&devCtx->WakeUpThread,
                      SynchronizationEvent,
                      FALSE
                      );

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__);
    return status;
}
示例#18
0
__drv_mustHoldCriticalRegion
NTSTATUS
FatPostStackOverflowRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine posts a read request that could not be processed by
    the fsp thread because of stack overflow potential.

Arguments:

    Irp - Supplies the request to process.

    Fcb - Supplies the file.

Return Value:

    STATUS_PENDING.

--*/

{
    KEVENT Event;
    PERESOURCE Resource;
    PVCB Vcb;

    PAGED_CODE();

    DebugTrace(0, Dbg, "Getting too close to stack limit pass request to Fsp\n", 0 );

    //
    //  Initialize an event and get shared on the resource we will
    //  be later using the common read.
    //

    KeInitializeEvent( &Event, NotificationEvent, FALSE );

    //
    //  Preacquire the resource the read path will require so we know the
    //  worker thread can proceed without waiting.
    //
    
    if (FlagOn(Irp->Flags, IRP_PAGING_IO) && (Fcb->Header.PagingIoResource != NULL)) {

        Resource = Fcb->Header.PagingIoResource;

    } else {

        Resource = Fcb->Header.Resource;
    }
    
    //
    //  If there are no resources assodicated with the file (case: the virtual
    //  volume file), it is OK.  No resources will be acquired on the other side
    //  as well.
    //

    if (Resource) {
        
        ExAcquireResourceSharedLite( Resource, TRUE );
    }

    if (NodeType( Fcb ) == FAT_NTC_VCB) {

        Vcb = (PVCB) Fcb;
    
    } else {

        Vcb = Fcb->Vcb;
    }
    
    try {
        
        //
        //  Make the Irp just like a regular post request and
        //  then send the Irp to the special overflow thread.
        //  After the post we will wait for the stack overflow
        //  read routine to set the event that indicates we can
        //  now release the scb resource and return.
        //

        FatPrePostIrp( IrpContext, Irp );

        //
        //  If this read is the result of a verify, we have to
        //  tell the overflow read routne to temporarily
        //  hijack the Vcb->VerifyThread field so that reads
        //  can go through.
        //

        if (Vcb->VerifyThread == KeGetCurrentThread()) {

            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_VERIFY_READ);
        }

        FsRtlPostStackOverflow( IrpContext, &Event, FatStackOverflowRead );

        //
        //  And wait for the worker thread to complete the item
        //

        KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );

    } finally {

        if (Resource) {

            ExReleaseResourceLite( Resource );
        }
    }

    return STATUS_PENDING;
}
示例#19
0
文件: tdi.c 项目: 0x00dec0de/Rovnix
NTSTATUS
TdiTest()
{
    PFILE_OBJECT ConnectionFileObject, AddressFileObject;
    HANDLE		AddressHandle, ConnectionHandle;
    CHAR		Buffer[80], Data[] = "Hello from Gary";
    NTSTATUS	Status;
    KEVENT		Done; 
	
	KeInitializeEvent(&Done, NotificationEvent, FALSE);

    Status = TdiCreateConnection(&ConnectionHandle, &ConnectionFileObject);
    if (!NT_SUCCESS(Status)) return Status;

    Status = TdiCreateAddress(&AddressHandle, &AddressFileObject, SOCK_STREAM, 0, 0);
    if (!NT_SUCCESS(Status)) return Status;

    do 
	{
		IO_STATUS_BLOCK IoStatus = {0};
        KEVENT	Event;

		Status = TdiSetEventHandler(AddressFileObject, TDI_EVENT_DISCONNECT, TdiEventDisconnect, &Done);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiSetEventHandler(AddressFileObject, TDI_EVENT_ERROR, TdiEventError, 0);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiSetEventHandler(AddressFileObject, TDI_EVENT_RECEIVE, TdiEventReceive, 0);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiBind(ConnectionFileObject, AddressHandle);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiConnect(ConnectionFileObject, 0x41A1F6A8, 0x700, NULL);
        if (!NT_SUCCESS(Status)) break;

		KeInitializeEvent(&Event, NotificationEvent, FALSE);

//        Status = TdiRecv(ConnectionFileObject, Buffer, sizeof Buffer, &Event, &IoStatus);
//        if (!NT_SUCCESS(Status)) break;

        Status = TdiSend(ConnectionFileObject, Data, sizeof Data);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiSend(ConnectionFileObject, Data, sizeof Data);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiSend(ConnectionFileObject, Data, sizeof Data);
        if (!NT_SUCCESS(Status)) break;

        Status = TdiDisconnect(ConnectionFileObject);
        if (!NT_SUCCESS(Status)) break;

        Status = KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, 0);
        if (Status == STATUS_SUCCESS) Status = IoStatus.Status;

        DbgPrint("Status = %lx, IoStatus.Status = %lx, IoStatus.Information = %ld\n", Status, IoStatus.Status, IoStatus.Information);

        KeWaitForSingleObject(&Done, UserRequest, KernelMode, FALSE, 0);

    } while (0);

    ObDereferenceObject(ConnectionFileObject);

    ObDereferenceObject(AddressFileObject);

    ZwClose(ConnectionHandle);

    ZwClose(AddressHandle);

    return Status;

}
示例#20
0
__drv_mustHoldCriticalRegion    
NTSTATUS
FatCommonRead (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common read routine for NtReadFile, called from both
    the Fsd, or from the Fsp if a request could not be completed without
    blocking in the Fsd.  This routine has no code where it determines
    whether it is running in the Fsd or Fsp.  Instead, its actions are
    conditionalized by the Wait input parameter, which determines whether
    it is allowed to block or not.  If a blocking condition is encountered
    with Wait == FALSE, however, the request is posted to the Fsp, who
    always calls with WAIT == TRUE.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    PVCB Vcb;
    PFCB FcbOrDcb;
    PCCB Ccb;

    VBO StartingVbo;
    ULONG ByteCount;
    ULONG RequestedByteCount;

    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;
    TYPE_OF_OPEN TypeOfOpen;

    BOOLEAN PostIrp = FALSE;
    BOOLEAN OplockPostIrp = FALSE;

    BOOLEAN FcbOrDcbAcquired = FALSE;

    BOOLEAN Wait;
    BOOLEAN PagingIo;
    BOOLEAN NonCachedIo;
    BOOLEAN SynchronousIo;

    NTSTATUS Status = STATUS_SUCCESS;

    FAT_IO_CONTEXT StackFatIoContext;

    //
    // A system buffer is only used if we have to access the
    // buffer directly from the Fsp to clear a portion or to
    // do a synchronous I/O, or a cached transfer.  It is
    // possible that our caller may have already mapped a
    // system buffer, in which case we must remember this so
    // we do not unmap it on the way out.
    //

    PVOID SystemBuffer = NULL;

    LARGE_INTEGER StartingByte;

    PAGED_CODE();

    //
    // Get current Irp stack location.
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );
    FileObject = IrpSp->FileObject;

    //
    // Initialize the appropriate local variables.
    //

    Wait          = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    PagingIo      = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO);
    NonCachedIo   = BooleanFlagOn(Irp->Flags,IRP_NOCACHE);
    SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO);

    DebugTrace(+1, Dbg, "CommonRead\n", 0);
    DebugTrace( 0, Dbg, "  Irp                   = %8lx\n", Irp);
    DebugTrace( 0, Dbg, "  ->ByteCount           = %8lx\n", IrpSp->Parameters.Read.Length);
    DebugTrace( 0, Dbg, "  ->ByteOffset.LowPart  = %8lx\n", IrpSp->Parameters.Read.ByteOffset.LowPart);
    DebugTrace( 0, Dbg, "  ->ByteOffset.HighPart = %8lx\n", IrpSp->Parameters.Read.ByteOffset.HighPart);

    //
    //  Extract starting Vbo and offset.
    //

    StartingByte = IrpSp->Parameters.Read.ByteOffset;

    StartingVbo = StartingByte.LowPart;

    ByteCount = IrpSp->Parameters.Read.Length;
    RequestedByteCount = ByteCount;

    //
    //  Check for a null request, and return immediately
    //

    if (ByteCount == 0) {

        Irp->IoStatus.Information = 0;
        FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
        return STATUS_SUCCESS;
    }

    //
    // Extract the nature of the read from the file object, and case on it
    //

    TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &FcbOrDcb, &Ccb);

    ASSERT( Vcb != NULL );

    //
    //  Save callers who try to do cached IO to the raw volume from themselves.
    //

    if (TypeOfOpen == UserVolumeOpen) {

        NonCachedIo = TRUE;
    }

    ASSERT(!(NonCachedIo == FALSE && TypeOfOpen == VirtualVolumeFile));

    //
    // Collect interesting statistics.  The FLAG_USER_IO bit will indicate
    // what type of io we're doing in the FatNonCachedIo function.
    //

    if (PagingIo) {
        CollectReadStats(Vcb, TypeOfOpen, ByteCount);

        if (TypeOfOpen == UserFileOpen) {
            SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO);
        } else {
            ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO);
        }
    }

    ASSERT(!FlagOn( IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT ));

    //
    //  Allocate if necessary and initialize a FAT_IO_CONTEXT block for
    //  all non cached Io.  For synchronous Io we use stack storage,
    //  otherwise we allocate pool.
    //

    if (NonCachedIo) {

        if (IrpContext->FatIoContext == NULL) {

            if (!Wait) {

                IrpContext->FatIoContext =
                    FsRtlAllocatePoolWithTag( NonPagedPool,
                                              sizeof(FAT_IO_CONTEXT),
                                              TAG_FAT_IO_CONTEXT );

            } else {

                IrpContext->FatIoContext = &StackFatIoContext;

                SetFlag( IrpContext->Flags, IRP_CONTEXT_STACK_IO_CONTEXT );
            }
        }

        RtlZeroMemory( IrpContext->FatIoContext, sizeof(FAT_IO_CONTEXT) );

        if (Wait) {

            KeInitializeEvent( &IrpContext->FatIoContext->Wait.SyncEvent,
                               NotificationEvent,
                               FALSE );

        } else {

            if (PagingIo) {

                IrpContext->FatIoContext->Wait.Async.ResourceThreadId =
                    ExGetCurrentResourceThread();

            } else {

                IrpContext->FatIoContext->Wait.Async.ResourceThreadId =
                    ((ULONG_PTR)IrpContext->FatIoContext) | 3;
            }

            IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
                ByteCount;

            IrpContext->FatIoContext->Wait.Async.FileObject = FileObject;
        }
    }


    //
    // These two cases correspond to either a general opened volume, ie.
    // open ("a:"), or a read of the volume file (boot sector + fat(s))
    //

    if ((TypeOfOpen == VirtualVolumeFile) ||
        (TypeOfOpen == UserVolumeOpen)) {

        LBO StartingLbo;

        StartingLbo = StartingByte.QuadPart;

        DebugTrace(0, Dbg, "Type of read is User Volume or virtual volume file\n", 0);

        if (TypeOfOpen == UserVolumeOpen) {

            //
            //  Verify that the volume for this handle is still valid
            //

            //
            //  Verify that the volume for this handle is still valid, permitting
            //  operations to proceed on dismounted volumes via the handle which
            //  performed the dismount.
            //

            if (!FlagOn( Ccb->Flags, CCB_FLAG_COMPLETE_DISMOUNT | CCB_FLAG_SENT_FORMAT_UNIT )) {

                FatQuickVerifyVcb( IrpContext, Vcb );
            }

            //
            //  If the caller previously sent a format unit command, then we will allow
            //  their read/write requests to ignore the verify flag on the device, since some
            //  devices send a media change event after format unit, but we don't want to 
            //  process it yet since we're probably in the process of formatting the
            //  media.
            //

            if (FlagOn( Ccb->Flags, CCB_FLAG_SENT_FORMAT_UNIT )) {

                SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_OVERRIDE_VERIFY );
            }

            if (!FlagOn( Ccb->Flags, CCB_FLAG_DASD_FLUSH_DONE )) {

                (VOID)ExAcquireResourceExclusiveLite( &Vcb->Resource, TRUE );

                try {

                    //
                    //  If the volume isn't locked, flush it.
                    //

                    if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_LOCKED)) {

                        FatFlushVolume( IrpContext, Vcb, Flush );
                    }

                } finally {

                    ExReleaseResourceLite( &Vcb->Resource );
                }

                SetFlag( Ccb->Flags, CCB_FLAG_DASD_FLUSH_DONE );
            }

            if (!FlagOn( Ccb->Flags, CCB_FLAG_ALLOW_EXTENDED_DASD_IO )) {

                LBO VolumeSize;

                //
                //  Make sure we don't try to read past end of volume,
                //  reducing the byte count if necessary.
                //

                VolumeSize = (LBO) Vcb->Bpb.BytesPerSector *
                             (Vcb->Bpb.Sectors != 0 ? Vcb->Bpb.Sectors :
                                                      Vcb->Bpb.LargeSectors);

                if (StartingLbo >= VolumeSize) {
                    Irp->IoStatus.Information = 0;
                    FatCompleteRequest( IrpContext, Irp, STATUS_END_OF_FILE );
                    return STATUS_END_OF_FILE;
                }

                if (ByteCount > VolumeSize - StartingLbo) {

                    ByteCount = RequestedByteCount = (ULONG) (VolumeSize - StartingLbo);

                    //
                    //  For async reads we had set the byte count in the FatIoContext
                    //  above, so fix that here.
                    //

                    if (!Wait) {

                        IrpContext->FatIoContext->Wait.Async.RequestedByteCount =
                            ByteCount;
                    }
                }
            }

            //
            //  For DASD we have to probe and lock the user's buffer
            //

            FatLockUserBuffer( IrpContext, Irp, IoWriteAccess, ByteCount );


        } else {
示例#21
0
NTSTATUS
UfxClientDeviceCreate(
    _In_ WDFDRIVER Driver,
    _In_ PWDFDEVICE_INIT DeviceInit
    )
/*++

Routine Description:

    Worker routine called to create a device and its software resources.

Arguments:

    Driver - WDF driver object

    DeviceInit - Pointer to an opaque init structure. Memory for this
                 structure will be freed by the framework when the WdfDeviceCreate
                 succeeds. So don't access the structure after that point.

Return Value:

    Appropriate NTSTATUS value

--*/
{
    WDF_OBJECT_ATTRIBUTES DeviceAttributes;
    WDFDEVICE WdfDevice;
    NTSTATUS Status;
    WDF_PNPPOWER_EVENT_CALLBACKS PnpCallbacks;
    WDF_DMA_ENABLER_CONFIG DmaConfig;
    PCONTROLLER_CONTEXT ControllerContext;

    PAGED_CODE();

    TraceEntry();

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DeviceAttributes, CONTROLLER_CONTEXT);

    //
    // Do UFX-specific initialization
    //
    Status = UfxFdoInit(Driver, DeviceInit, &DeviceAttributes);
    CHK_NT_MSG(Status, "Failed UFX initialization");

    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpCallbacks);
    PnpCallbacks.EvtDevicePrepareHardware = OnEvtDevicePrepareHardware;
    PnpCallbacks.EvtDeviceReleaseHardware = OnEvtDeviceReleaseHardware;
    PnpCallbacks.EvtDeviceD0Entry = OnEvtDeviceD0Entry;
    PnpCallbacks.EvtDeviceD0Exit = OnEvtDeviceD0Exit;
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &PnpCallbacks);

    Status = WdfDeviceCreate(&DeviceInit, &DeviceAttributes, &WdfDevice);
    CHK_NT_MSG(Status, "Failed to create wdf device");

    ControllerContext = DeviceGetControllerContext(WdfDevice);

    KeInitializeEvent(&ControllerContext->DetachEvent,
                      NotificationEvent,
                      FALSE);

    WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&ControllerContext->IdleSettings, IdleCanWakeFromS0);
    ControllerContext->IdleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint;
    ControllerContext->IdleSettings.IdleTimeout = IDLE_TIMEOUT;
    ControllerContext->IdleSettings.DxState = PowerDeviceD3;

    Status = WdfDeviceAssignS0IdleSettings(WdfDevice, &ControllerContext->IdleSettings);
    LOG_NT_MSG(Status, "Failed to set S0 Idle Settings");

    //
    // Create and initialize device's default queue
    //
    Status = DefaultQueueCreate(WdfDevice);
    CHK_NT_MSG(Status, "Failed to intialize default queue");

    //
    // Set alignment required by controller
    //
    WdfDeviceSetAlignmentRequirement(WdfDevice, UFX_CLIENT_ALIGNMENT);

    //
    // Create and Initialize DMA Enabler object for the device.
    //
    WDF_DMA_ENABLER_CONFIG_INIT(
                        &DmaConfig,
                        WdfDmaProfileScatterGatherDuplex,
                        MAX_DMA_LENGTH);
    //
    // Version 3 is required to perform multiple
    // simultaneous transfers.
    //
    DmaConfig.WdmDmaVersionOverride = 3;

    Status = WdfDmaEnablerCreate(
                            WdfDevice,
                            &DmaConfig,
                            WDF_NO_OBJECT_ATTRIBUTES,
                            &ControllerContext->DmaEnabler);
    CHK_NT_MSG(Status, "Failed to create DMA enabler object");

    //
    // Create UFXDEVICE object
    //
    Status = UfxDevice_DeviceCreate(WdfDevice);
    CHK_NT_MSG(Status, "Failed to create UFX Device object");

    //
    // Create DPC Lock
    //
    Status = WdfSpinLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &ControllerContext->DpcLock);
    CHK_NT_MSG(Status, "Failed to create DPC lock");

    Status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &ControllerContext->InitializeDefaultEndpointLock);
    CHK_NT_MSG(Status, "Failed to create Ep0 init lock");

End:
    TraceExit();
    return Status;
}
示例#22
0
NTSTATUS
NTAPI
PciPdoCreate(IN PPCI_FDO_EXTENSION DeviceExtension,
             IN PCI_SLOT_NUMBER Slot,
             OUT PDEVICE_OBJECT *PdoDeviceObject)
{
    WCHAR DeviceName[32];
    UNICODE_STRING DeviceString;
    NTSTATUS Status;
    PDEVICE_OBJECT DeviceObject;
    PPCI_PDO_EXTENSION PdoExtension;
    ULONG SequenceNumber;
    PAGED_CODE();

    /* Pick an atomically unique sequence number for this device */
    SequenceNumber = InterlockedIncrement(&PciPdoSequenceNumber);

    /* Create the standard PCI device name for a PDO */
    swprintf(DeviceName, L"\\Device\\NTPNP_PCI%04d", SequenceNumber);
    RtlInitUnicodeString(&DeviceString, DeviceName);

    /* Create the actual device now */
    Status = IoCreateDevice(DeviceExtension->FunctionalDeviceObject->DriverObject,
                            sizeof(PCI_PDO_EXTENSION),
                            &DeviceString,
                            FILE_DEVICE_BUS_EXTENDER,
                            0,
                            0,
                            &DeviceObject);
    ASSERT(NT_SUCCESS(Status));

    /* Get the extension for it */
    PdoExtension = (PPCI_PDO_EXTENSION)DeviceObject->DeviceExtension;
    DPRINT1("PCI: New PDO (b=0x%x, d=0x%x, f=0x%x) @ %p, ext @ %p\n",
            DeviceExtension->BaseBus,
            Slot.u.bits.DeviceNumber,
            Slot.u.bits.FunctionNumber,
            DeviceObject,
            DeviceObject->DeviceExtension);

    /* Configure the extension */
    PdoExtension->ExtensionType = PciPdoExtensionType;
    PdoExtension->IrpDispatchTable = &PciPdoDispatchTable;
    PdoExtension->PhysicalDeviceObject = DeviceObject;
    PdoExtension->Slot = Slot;
    PdoExtension->PowerState.CurrentSystemState = PowerDeviceD0;
    PdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0;
    PdoExtension->ParentFdoExtension = DeviceExtension;

    /* Initialize the lock for arbiters and other interfaces */
    KeInitializeEvent(&PdoExtension->SecondaryExtLock, SynchronizationEvent, TRUE);

    /* Initialize the state machine */
    PciInitializeState((PPCI_FDO_EXTENSION)PdoExtension);

    /* Add the PDO to the parent's list */
    PdoExtension->Next = NULL;
    PciInsertEntryAtTail((PSINGLE_LIST_ENTRY)&DeviceExtension->ChildPdoList,
                         (PPCI_FDO_EXTENSION)PdoExtension,
                         &DeviceExtension->ChildListLock);

    /* And finally return it to the caller */
    *PdoDeviceObject = DeviceObject;
    return STATUS_SUCCESS;
}
示例#23
0
NDIS_STATUS
FakeNDISReceiveHandler (
	NDIS_HANDLE ProtocolBindingContext,
	NDIS_HANDLE MacReceiveContext,
	PUCHAR pHeaderBuffer,
	UINT HeaderBufferSize,
	PUCHAR pLookaheadBuffer,
	UINT LookaheadBufferSize,
	UINT PacketSize
	)
/*++

Routine Description:

	Filters network packets received.


Arguments:

	ProtocolBindingContext - ...

	MacReceiveContext - ...

	pHeaderBuffer - packet header

	HeaderBufferSize - packet header length

	pLookaheadBuffer - look ahead buffer after packet header

	LookaheadBufferSize - length of look ahead buffer

	PacketSize - length of packet, exclude packet header


Return Value:

	...


Author:

	xiaonie

	2012/07/12


--*/
{
	PLIST_ENTRY pEntry;
	PNDIS_HOOK_LIST_NODE pNode;
	KIRQL irql;
	ULONG ulFunAddr = 0;
	// PVOID MacHandle = NULL;
	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
	PNDIS_PACKET pNdisPacket = NULL;
	PNDIS_BUFFER pNdisBuffer = NULL;
	PUCHAR pBuffer = NULL;
	ULONG ulLen;
	KEVENT evt;

	KeAcquireSpinLock(&g_lock, &irql);
	for (pEntry = g_linkListHead.Flink; pEntry != &g_linkListHead; pEntry = pEntry->Flink) {
		pNode = CONTAINING_RECORD(pEntry, NDIS_HOOK_LIST_NODE, ListEntry);
		if (pNode->ProtocolBindingContext == ProtocolBindingContext) {
			ulFunAddr = pNode->ulRealReceiveHandler;
			// MacHandle = pNode->MacHandle;
			break;
		}
	}
	KeReleaseSpinLock(&g_lock, irql);

	if (ulFunAddr == 0) {
		DbgPrint("\r\n Attention: FunAddr == 0(0: FakeNDISReceiveHandler)\r\n");
		// return NDIS_STATUS_SUCCESS;
		return NDIS_STATUS_NOT_ACCEPTED;
	}


	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	if (PacketSize + HeaderBufferSize < PacketSize || PacketSize < LookaheadBufferSize) {	// PacketSize not valid
		DbgPrint("\r\n Attention: PacketSize not valid!(0: FakeNDISReceiveHandler)\r\n");
		return NDIS_STATUS_NOT_ACCEPTED;
	}

	// allocate buffer to hold network packet
	status = NdisAllocateMemoryWithTag(&pBuffer, HeaderBufferSize + PacketSize, '!nmN');
	if (status != NDIS_STATUS_SUCCESS/* || pBuffer == NULL*/)
		return NDIS_STATUS_NOT_ACCEPTED;

	// copy packet header to buffer
	NdisMoveMemory(pBuffer, pHeaderBuffer, HeaderBufferSize);

	if (PacketSize == LookaheadBufferSize)		// Lookahead buffer contains a complete packet
	{
		//
		//	path 1 of 3, tested ok!
		//
		NdisMoveMemory(pBuffer + HeaderBufferSize, pLookaheadBuffer, PacketSize);

		// do the filtering work
		if (TRUE == RabbitHole(pBuffer, HeaderBufferSize + PacketSize)) {
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		NdisFreeMemory(pBuffer, 0, 0);

	}
	else										// Lookahead buffer contains an incomplete packet
	{
		//
		// get the full packet
		//
		// DbgPrint("Get Full Packet!\r\n");

		//if (MacHandle == NULL) {
		//	DbgPrint("MacHandle == NULL!(0: FakeNDISReceiveHandler)\r\n");
		//	NdisFreeMemory(pBuffer, 0, 0);
		//	return NDIS_STATUS_NOT_ACCEPTED;
		//}

		// make pBuffer a NDIS buffer to hold data
		NdisAllocateBuffer(&status, &pNdisBuffer, g_BufferPool, pBuffer + HeaderBufferSize, PacketSize);
		if (status != NDIS_STATUS_SUCCESS/* || pNdisBuffer == NULL*/) {
			DbgPrint("allocate pNdisBuffer(size = %d) failed in FakeNDISReceiveHandler!\r\n", PacketSize);
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		// allocate a NIDS packet to chain buffer in.
		NdisAllocatePacket(&status, &pNdisPacket, g_PacketPool);
		if (status != NDIS_STATUS_SUCCESS/* || pNdisPacket == NULL*/) {
			DbgPrint("allocate pNdisPacket failed in FakeNDISReceiveHandler!\r\n");
			NdisFreeBuffer(pNdisBuffer);
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		NDIS_SET_PACKET_STATUS(pNdisPacket, STATUS_SUCCESS);

		// Bring explosives.
		KeInitializeEvent(&evt, NotificationEvent, FALSE);
		*(PKEVENT *)(pNdisPacket->ProtocolReserved) = &evt;

		NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);

		// try to get complete packet
		NdisTransferData(&status, pNode->pOpenBlock, MacReceiveContext, 0, PacketSize, pNdisPacket, &ulLen);

		if (status == NDIS_STATUS_PENDING) {			// wait for the right time
			//
			// Path 2 of 3, not tested yet! Warning: An Error may occur!
			//
			DbgPrint("NdisTransferData is pending in FakeNDISReceiveHandler!\r\n", status);
			KeWaitForSingleObject(&evt, Executive, KernelMode, FALSE, NULL);
		} else if (status != NDIS_STATUS_SUCCESS) {
			DbgPrint("NdisTransferData failed(status == 0x%08x) in FakeNDISReceiveHandler!\r\n", status);
			NdisFreePacket(pNdisPacket);
			NdisFreeBuffer(pNdisBuffer);
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		//
		// Path 3 of 3, Filtering doesn't seem to work properly.
		//
		// do the filtering work
		if (TRUE == FilterPacket_ReceiveHandler(pBuffer, HeaderBufferSize, pNdisPacket)) {
			NdisFreePacket(pNdisPacket);
			NdisFreeBuffer(pNdisBuffer);
			NdisFreeMemory(pBuffer, 0, 0);
			return NDIS_STATUS_NOT_ACCEPTED;
		}

		NdisFreePacket(pNdisPacket);
		NdisFreeBuffer(pNdisBuffer);
		NdisFreeMemory(pBuffer, 0, 0);
	}

	// call the original NDIS routine.
	__asm {
		pushad;
		push	PacketSize;
		push	LookaheadBufferSize;
		push	pLookaheadBuffer;
		push	HeaderBufferSize;
		push	pHeaderBuffer;
		push	MacReceiveContext;
		push	ProtocolBindingContext;
		mov		eax, ulFunAddr;
		call	eax;
		mov		status, eax;
		popad;
	}

	return status;
}
示例#24
0
static
VOID
TestEventConcurrent(
    IN PKEVENT Event,
    IN EVENT_TYPE Type,
    IN KIRQL OriginalIrql,
    PSET_EVENT_FUNCTION SetEvent,
    KPRIORITY PriorityIncrement,
    LONG ExpectedState,
    BOOLEAN SatisfiesAll)
{
    NTSTATUS Status;
    THREAD_DATA Threads[5];
    const INT ThreadCount = sizeof Threads / sizeof Threads[0];
    KPRIORITY Priority;
    LARGE_INTEGER LongTimeout, ShortTimeout;
    INT i;
    KWAIT_BLOCK WaitBlock[MAXIMUM_WAIT_OBJECTS];
    PVOID ThreadObjects[MAXIMUM_WAIT_OBJECTS];
    LONG State;
    PKTHREAD Thread = KeGetCurrentThread();

    LongTimeout.QuadPart = -100 * MILLISECOND;
    ShortTimeout.QuadPart = -1 * MILLISECOND;

    KeInitializeEvent(Event, Type, FALSE);

    for (i = 0; i < ThreadCount; ++i)
    {
        Threads[i].Event = Event;
        Threads[i].Signal = FALSE;
        Status = PsCreateSystemThread(&Threads[i].Handle, GENERIC_ALL, NULL, NULL, NULL, WaitForEventThread, &Threads[i]);
        ok_eq_hex(Status, STATUS_SUCCESS);
        Status = ObReferenceObjectByHandle(Threads[i].Handle, SYNCHRONIZE, PsThreadType, KernelMode, (PVOID *)&Threads[i].Thread, NULL);
        ok_eq_hex(Status, STATUS_SUCCESS);
        ThreadObjects[i] = Threads[i].Thread;
        Priority = KeQueryPriorityThread(Threads[i].Thread);
        ok_eq_long(Priority, 8L);
        while (!Threads[i].Signal)
        {
            Status = KeDelayExecutionThread(KernelMode, FALSE, &ShortTimeout);
            ok_eq_hex(Status, STATUS_SUCCESS);
        }
        CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, ThreadObjects, i + 1);
    }

    /* the threads shouldn't wake up on their own */
    Status = KeDelayExecutionThread(KernelMode, FALSE, &ShortTimeout);
    ok_eq_hex(Status, STATUS_SUCCESS);

    for (i = 0; i < ThreadCount; ++i)
    {
        CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, ThreadObjects + i, ThreadCount - i);
        State = SetEvent(Event, PriorityIncrement + i, FALSE);

        ok_eq_long(State, 0L);
        CheckEvent(Event, Type, ExpectedState, FALSE, OriginalIrql, ThreadObjects + i + 1, SatisfiesAll ? 0 : ThreadCount - i - 1);
        Status = KeWaitForMultipleObjects(ThreadCount, ThreadObjects, SatisfiesAll ? WaitAll : WaitAny, Executive, KernelMode, FALSE, &LongTimeout, WaitBlock);
        ok_eq_hex(Status, STATUS_WAIT_0 + i);
        if (SatisfiesAll)
        {
            for (; i < ThreadCount; ++i)
            {
                Priority = KeQueryPriorityThread(Threads[i].Thread);
                ok_eq_long(Priority, max(min(8L + PriorityIncrement, 15L), 8L));
            }
            break;
        }
        Priority = KeQueryPriorityThread(Threads[i].Thread);
        ok_eq_long(Priority, max(min(8L + PriorityIncrement + i, 15L), 8L));
        /* replace the thread with the current thread - which will never signal */
        if (!skip((Status & 0x3F) < ThreadCount, "Index out of bounds"))
            ThreadObjects[Status & 0x3F] = Thread;
        Status = KeWaitForMultipleObjects(ThreadCount, ThreadObjects, WaitAny, Executive, KernelMode, FALSE, &ShortTimeout, WaitBlock);
        ok_eq_hex(Status, STATUS_TIMEOUT);
    }

    for (i = 0; i < ThreadCount; ++i)
    {
        ObDereferenceObject(Threads[i].Thread);
        Status = ZwClose(Threads[i].Handle);
        ok_eq_hex(Status, STATUS_SUCCESS);
    }
}
示例#25
0
NTSTATUS
FatPnpRemove (
    PIRP_CONTEXT IrpContext,
    PIRP Irp,
    PVCB Vcb
    )

/*++

Routine Description:

    This routine handles the PnP remove operation.  This is our notification
    that the underlying storage device for the volume we have is gone, and
    an excellent indication that the volume will never reappear. The filesystem
    is responsible for initiation or completion of the dismount.
    
Arguments:

    Irp - Supplies the Irp to process
    
    Vcb - Supplies the volume being removed.

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    KEVENT Event;
    BOOLEAN VcbDeleted;
    
    //
    //  REMOVE - a storage device is now gone.  We either got
    //  QUERY'd and said yes OR got a SURPRISE OR a storage
    //  stack failed to spin back up from a sleep/stop state
    //  (the only case in which this will be the first warning).
    //
    //  Note that it is entirely unlikely that we will be around
    //  for a REMOVE in the first two cases, as we try to intiate
    //  dismount.
    //
    
    //
    //  Acquire the global resource so that we can try to vaporize
    //  the volume, and the vcb resource itself.
    //

#if __NDAS_FAT_SECONDARY__
	if (FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT))
		FatAcquireExclusiveSecondaryVcb( IrpContext, Vcb );
	else
		FatAcquireExclusiveVcb( IrpContext, Vcb );
#else
	FatAcquireExclusiveVcb( &IrpContext, Vcb );
#endif

    //
    //  The device will be going away.  Remove our lock (benign
    //  if we never had it).
    //

    (VOID) FatUnlockVolumeInternal( IrpContext, Vcb, NULL );
    
    //
    //  We need to pass this down before starting the dismount, which
    //  could disconnect us immediately from the stack.
    //
    
    //
    //  Get the next stack location, and copy over the stack location
    //

    IoCopyCurrentIrpStackLocationToNext( Irp );

    //
    //  Set up the completion routine
    //

    KeInitializeEvent( &Event, NotificationEvent, FALSE );
    IoSetCompletionRoutine( Irp,
                            FatPnpCompletionRoutine,
                            &Event,
                            TRUE,
                            TRUE,
                            TRUE );

    //
    //  Send the request and wait.
    //

    Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);

    if (Status == STATUS_PENDING) {

        KeWaitForSingleObject( &Event,
                               Executive,
                               KernelMode,
                               FALSE,
                               NULL );

        Status = Irp->IoStatus.Status;
    }

    try {
        
        //
        //  Knock as many files down for this volume as we can.
        //

        FatFlushAndCleanVolume( IrpContext, Irp, Vcb, NoFlush );

        //
        //  Now make our dismount happen.  This may not vaporize the
        //  Vcb, of course, since there could be any number of handles
        //  outstanding if we were not preceeded by a QUERY.
        //
        //  PnP will take care of disconnecting this stack if we
        //  couldn't get off of it immediately.
        //

        VcbDeleted = FatCheckForDismount( IrpContext, Vcb, TRUE );

    } finally {
        
        //
        //  Release the Vcb if it could still remain.
        //

        if (!VcbDeleted) {

#if __NDAS_FAT_SECONDARY__
			if (FlagOn(IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT)) {
				FatReleaseSecondaryVcb( IrpContext, Vcb );
			} else {
				FatReleaseVcb( IrpContext, Vcb );
			}
#else
			FatReleaseVcb( IrpContext, Vcb );
#endif       
        }

        FatReleaseGlobal( IrpContext );
    }

    //
    //  Cleanup our IrpContext and complete the IRP.
    //

    FatCompleteRequest( IrpContext, Irp, Status );

    return Status;
}
示例#26
0
static
VOID
TestEventFunctional(
    IN PKEVENT Event,
    IN EVENT_TYPE Type,
    IN KIRQL OriginalIrql)
{
    LONG State;
    PKTHREAD Thread = KeGetCurrentThread();

    memset(Event, 0x55, sizeof *Event);
    KeInitializeEvent(Event, Type, FALSE);
    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0);

    memset(Event, 0x55, sizeof *Event);
    KeInitializeEvent(Event, Type, TRUE);
    CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0);

    Event->Header.SignalState = 0x12345678L;
    CheckEvent(Event, Type, 0x12345678L, FALSE, OriginalIrql, (PVOID *)NULL, 0);

    State = KePulseEvent(Event, 0, FALSE);
    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0);
    ok_eq_long(State, 0x12345678L);

    Event->Header.SignalState = 0x12345678L;
    KeClearEvent(Event);
    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0);

    State = KeSetEvent(Event, 0, FALSE);
    CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0);
    ok_eq_long(State, 0L);

    State = KeResetEvent(Event);
    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0);
    ok_eq_long(State, 1L);

    Event->Header.SignalState = 0x23456789L;
    State = KeSetEvent(Event, 0, FALSE);
    CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0);
    ok_eq_long(State, 0x23456789L);

    Event->Header.SignalState = 0x3456789AL;
    State = KeResetEvent(Event);
    CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0);
    ok_eq_long(State, 0x3456789AL);

    /* Irql is raised to DISPATCH_LEVEL here, which kills checked build,
     * a spinlock is acquired and never released, which kills MP build */
    if ((OriginalIrql <= DISPATCH_LEVEL || !KmtIsCheckedBuild) &&
        !KmtIsMultiProcessorBuild)
    {
        Event->Header.SignalState = 0x456789ABL;
        State = KeSetEvent(Event, 0, TRUE);
        CheckEvent(Event, Type, 1L, TRUE, DISPATCH_LEVEL, (PVOID *)NULL, 0);
        ok_eq_long(State, 0x456789ABL);
        ok_eq_uint(Thread->WaitIrql, OriginalIrql);
        /* repair the "damage" */
        Thread->WaitNext = FALSE;
        KmtSetIrql(OriginalIrql);

        Event->Header.SignalState = 0x56789ABCL;
        State = KePulseEvent(Event, 0, TRUE);
        CheckEvent(Event, Type, 0L, TRUE, DISPATCH_LEVEL, (PVOID *)NULL, 0);
        ok_eq_long(State, 0x56789ABCL);
        ok_eq_uint(Thread->WaitIrql, OriginalIrql);
        /* repair the "damage" */
        Thread->WaitNext = FALSE;
        KmtSetIrql(OriginalIrql);
    }

    ok_irql(OriginalIrql);
    KmtSetIrql(OriginalIrql);
}
示例#27
0
NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue)
{
	NTSTATUS status;
	EncryptedIoQueueBuffer *buffer;
	int i;

	queue->StartPending = TRUE;
	queue->ThreadExitRequested = FALSE;

	queue->OutstandingIoCount = 0;
	queue->IoThreadPendingRequestCount = 0;

	queue->FirstPoolBuffer = NULL;
	KeInitializeMutex (&queue->BufferPoolMutex, 0);

	KeInitializeEvent (&queue->NoOutstandingIoEvent, SynchronizationEvent, FALSE);
	KeInitializeEvent (&queue->PoolBufferFreeEvent, SynchronizationEvent, FALSE);
	KeInitializeEvent (&queue->QueueResumedEvent, SynchronizationEvent, FALSE);

	queue->FragmentBufferA = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE);
	if (!queue->FragmentBufferA)
		goto noMemory;

	queue->FragmentBufferB = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE);
	if (!queue->FragmentBufferB)
		goto noMemory;

	KeInitializeEvent (&queue->FragmentBufferAFreeEvent, SynchronizationEvent, TRUE);
	KeInitializeEvent (&queue->FragmentBufferBFreeEvent, SynchronizationEvent, TRUE);

	queue->ReadAheadBufferValid = FALSE;
	queue->ReadAheadBuffer = TCalloc (TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE);
	if (!queue->ReadAheadBuffer)
		goto noMemory;

	// Preallocate buffers
	for (i = 0; i < TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT; ++i)
	{
		if (i < TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT && !GetPoolBuffer (queue, sizeof (EncryptedIoQueueItem)))
			goto noMemory;

		if (!GetPoolBuffer (queue, sizeof (EncryptedIoRequest)))
			goto noMemory;
	}

	for (buffer = queue->FirstPoolBuffer; buffer != NULL; buffer = buffer->NextBuffer)
	{
		buffer->InUse = FALSE;
	}

	// Main thread
	InitializeListHead (&queue->MainThreadQueue);
	KeInitializeSpinLock (&queue->MainThreadQueueLock);
	KeInitializeEvent (&queue->MainThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE);

	status = TCStartThread (MainThreadProc, queue, &queue->MainThread);
	if (!NT_SUCCESS (status))
		goto err;

	// IO thread
	InitializeListHead (&queue->IoThreadQueue);
	KeInitializeSpinLock (&queue->IoThreadQueueLock);
	KeInitializeEvent (&queue->IoThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE);

	status = TCStartThread (IoThreadProc, queue, &queue->IoThread);
	if (!NT_SUCCESS (status))
	{
		queue->ThreadExitRequested = TRUE;
		TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent);
		goto err;
	}

	// Completion thread
	InitializeListHead (&queue->CompletionThreadQueue);
	KeInitializeSpinLock (&queue->CompletionThreadQueueLock);
	KeInitializeEvent (&queue->CompletionThreadQueueNotEmptyEvent, SynchronizationEvent, FALSE);

	status = TCStartThread (CompletionThreadProc, queue, &queue->CompletionThread);
	if (!NT_SUCCESS (status))
	{
		queue->ThreadExitRequested = TRUE;
		TCStopThread (queue->MainThread, &queue->MainThreadQueueNotEmptyEvent);
		TCStopThread (queue->IoThread, &queue->IoThreadQueueNotEmptyEvent);
		goto err;
	}

#ifdef TC_TRACE_IO_QUEUE
	GetElapsedTimeInit (&queue->LastPerformanceCounter);
#endif

	queue->StopPending = FALSE;
	queue->StartPending = FALSE;

	Dump ("Queue started\n");
	return STATUS_SUCCESS;

noMemory:
	status = STATUS_INSUFFICIENT_RESOURCES;

err:
	if (queue->FragmentBufferA)
		TCfree (queue->FragmentBufferA);
	if (queue->FragmentBufferB)
		TCfree (queue->FragmentBufferB);
	if (queue->ReadAheadBuffer)
		TCfree (queue->ReadAheadBuffer);

	FreePoolBuffers (queue);

	queue->StartPending = FALSE;
	return status;
}
示例#28
0
NTSTATUS
CdCommonWrite (
    _Inout_ PIRP_CONTEXT IrpContext,
    _Inout_ PIRP Irp
    )

/*++

Routine Description:

    This is the common entry point for NtWriteFile calls.  For synchronous requests,
    CommonWrite will complete the request in the current thread.  If not
    synchronous the request will be passed to the Fsp if there is a need to
    block.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The result of this operation.

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );

    TYPE_OF_OPEN TypeOfOpen;
    PFCB Fcb;
    PCCB Ccb;

    BOOLEAN Wait;
    ULONG SynchronousIo;
    PVOID UserBuffer;

    LONGLONG StartingOffset;
    LONGLONG ByteRange;
    ULONG ByteCount;
    ULONG WriteByteCount;
    ULONG OriginalByteCount;

    BOOLEAN ReleaseFile = TRUE;

    CD_IO_CONTEXT LocalIoContext;

    PAGED_CODE();

    //
    //  If this is a zero length write then return SUCCESS immediately.
    //

    if (IrpSp->Parameters.Write.Length == 0) {

        CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
        return STATUS_SUCCESS;
    }

    //
    //  Decode the file object and verify we support write on this.  It
    //  must be a volume file.
    //

    TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );

    // Internal lock object is acquired if return status is STATUS_PENDING
    _Analysis_suppress_lock_checking_(Fcb->Resource);

    if (TypeOfOpen != UserVolumeOpen) {

        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
        return STATUS_INVALID_DEVICE_REQUEST;
    }

    //
    //  Examine our input parameters to determine if this is noncached and/or
    //  a paging io operation.
    //

    Wait = BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    SynchronousIo = FlagOn( IrpSp->FileObject->Flags, FO_SYNCHRONOUS_IO );


    //
    //  Extract the range of the Io.
    //

    StartingOffset = IrpSp->Parameters.Write.ByteOffset.QuadPart;
    OriginalByteCount = ByteCount = IrpSp->Parameters.Write.Length;

    ByteRange = StartingOffset + ByteCount;

    //
    //  Acquire the file shared to perform the write.
    //

    CdAcquireFileShared( IrpContext, Fcb );

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Verify the Fcb.  Allow writes if this is a DASD handle that is 
        //  dismounting the volume.
        //

        if (!FlagOn( Ccb->Flags, CCB_FLAG_DISMOUNT_ON_CLOSE ))  {

            CdVerifyFcbOperation( IrpContext, Fcb );
        }

        if (!FlagOn( Ccb->Flags, CCB_FLAG_ALLOW_EXTENDED_DASD_IO )) {

            //
            //  Complete the request if it begins beyond the end of file.
            //

            if (StartingOffset >= Fcb->FileSize.QuadPart) {

                try_return( Status = STATUS_END_OF_FILE );
            }

            //
            //  Truncate the write if it extends beyond the end of the file.
            //

            if (ByteRange > Fcb->FileSize.QuadPart) {

                ByteCount = (ULONG) (Fcb->FileSize.QuadPart - StartingOffset);
                ByteRange = Fcb->FileSize.QuadPart;
            }
        }

        //
        //  If we have an unaligned transfer then post this request if
        //  we can't wait.  Unaligned means that the starting offset
        //  is not on a sector boundary or the write is not integral
        //  sectors.
        //

        WriteByteCount = BlockAlign( Fcb->Vcb, ByteCount );

        if (SectorOffset( StartingOffset ) ||
            SectorOffset( WriteByteCount ) ||
            (WriteByteCount > OriginalByteCount)) {

            if (!Wait) {

                CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
            }

            //
            //  Make sure we don't overwrite the buffer.
            //

            WriteByteCount = ByteCount;
        }

        //
        //  Initialize the IoContext for the write.
        //  If there is a context pointer, we need to make sure it was
        //  allocated and not a stale stack pointer.
        //

        if (IrpContext->IoContext == NULL ||
            !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO )) {

            //
            //  If we can wait, use the context on the stack.  Otherwise
            //  we need to allocate one.
            //

            if (Wait) {

                IrpContext->IoContext = &LocalIoContext;
                ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );

            } else {

                IrpContext->IoContext = CdAllocateIoContext();
                SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
            }
        }

        RtlZeroMemory( IrpContext->IoContext, sizeof( CD_IO_CONTEXT ) );

        //
        //  Store whether we allocated this context structure in the structure
        //  itself.
        //

        IrpContext->IoContext->AllocatedContext =
            BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );

        if (Wait) {

            KeInitializeEvent( &IrpContext->IoContext->SyncEvent,
                               NotificationEvent,
                               FALSE );

        } else {

            IrpContext->IoContext->ResourceThreadId = ExGetCurrentResourceThread();
            IrpContext->IoContext->Resource = Fcb->Resource;
            IrpContext->IoContext->RequestedByteCount = ByteCount;
        }

        Irp->IoStatus.Information = WriteByteCount;

        //
        //  Set the FO_MODIFIED flag here to trigger a verify when this
        //  handle is closed.  Note that we can err on the conservative
        //  side with no problem, i.e. if we accidently do an extra
        //  verify there is no problem.
        //

        SetFlag( IrpSp->FileObject->Flags, FO_FILE_MODIFIED );

        //
        //  Dasd access is always non-cached. Call the Dasd write routine to
        //  perform the actual write.
        //

        Status = CdVolumeDasdWrite( IrpContext, Fcb, StartingOffset, WriteByteCount );

        //
        //  Don't complete this request now if STATUS_PENDING was returned.
        //

        if (Status == STATUS_PENDING) {

            Irp = NULL;
            ReleaseFile = FALSE;

        //
        //  Test is we should zero part of the buffer or update the
        //  synchronous file position.
        //

        } else {

            //
            //  Convert any unknown error code to IO_ERROR.
            //

            if (!NT_SUCCESS( Status )) {

                //
                //  Set the information field to zero.
                //

                Irp->IoStatus.Information = 0;

                //
                //  Raise if this is a user induced error.
                //

                if (IoIsErrorUserInduced( Status )) {

                    CdRaiseStatus( IrpContext, Status );
                }

                Status = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR );

            //
            //  Check if there is any portion of the user's buffer to zero.
            //

            } else if (WriteByteCount != ByteCount) {

                CdMapUserBuffer( IrpContext, &UserBuffer );
                
                SafeZeroMemory( IrpContext,
                                Add2Ptr( UserBuffer,
                                         ByteCount,
                                         PVOID ),
                                WriteByteCount - ByteCount );

                Irp->IoStatus.Information = ByteCount;
            }

            //
            //  Update the file position if this is a synchronous request.
            //

            if (SynchronousIo && NT_SUCCESS( Status )) {

                IrpSp->FileObject->CurrentByteOffset.QuadPart = ByteRange;
            }
        }

    try_exit:  NOTHING;
    } finally {

        //
        //  Release the Fcb.
        //

        if (ReleaseFile) {

            CdReleaseFile( IrpContext, Fcb );
        }
    }

    //
    //  Post the request if we got CANT_WAIT.
    //

    if (Status == STATUS_CANT_WAIT) {

        Status = CdFsdPostRequest( IrpContext, Irp );

    //
    //  Otherwise complete the request.
    //

    } else {

        CdCompleteRequest( IrpContext, Irp, Status );
    }

    return Status;
}
示例#29
0
文件: entry.c 项目: hoangduit/reactos
NTSTATUS
NTAPI
WdmAudInstallDevice(
    IN  PDRIVER_OBJECT  DriverObject)
{
    UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\wdmaud");
    UNICODE_STRING SymlinkName = RTL_CONSTANT_STRING(L"\\DosDevices\\wdmaud");
    PDEVICE_OBJECT DeviceObject;
    NTSTATUS Status;
    PWDMAUD_DEVICE_EXTENSION DeviceExtension;

    DPRINT("WdmAudInstallDevice called\n");

    Status = IoCreateDevice(DriverObject,
                            sizeof(WDMAUD_DEVICE_EXTENSION),
                            &DeviceName,
                            FILE_DEVICE_KS,
                            0,
                            FALSE,
                            &DeviceObject);

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("IoCreateDevice failed with %x\n", Status);
        return Status;
    }

    /* get device extension */
    DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    RtlZeroMemory(DeviceExtension, sizeof(WDMAUD_DEVICE_EXTENSION));

    /* allocate work item */
    DeviceExtension->WorkItem = IoAllocateWorkItem(DeviceObject);
    if (!DeviceExtension->WorkItem)
    {
        /* failed to allocate work item */
        IoDeleteDevice(DeviceObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* register device interfaces */
    Status = WdmAudRegisterDeviceInterface(DeviceObject, DeviceExtension);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("WdmRegisterDeviceInterface failed with %x\n", Status);
        IoDeleteDevice(DeviceObject);
        return Status;
    }

    /* initialize sysaudio device list */
    InitializeListHead(&DeviceExtension->SysAudioDeviceList);

    /* initialize client context device list */
    InitializeListHead(&DeviceExtension->WdmAudClientList);

    /* initialize spinlock */
    KeInitializeSpinLock(&DeviceExtension->Lock);

    /* initialization completion event */
    KeInitializeEvent(&DeviceExtension->InitializationCompletionEvent, NotificationEvent, FALSE);

    /* initialize timer */
    IoInitializeTimer(DeviceObject, WdmAudTimerRoutine, (PVOID)WdmAudTimerRoutine);

    /* find available sysaudio devices */
    Status = WdmAudOpenSysAudioDevices(DeviceObject, DeviceExtension);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status);
        IoDeleteSymbolicLink(&SymlinkName);
        IoDeleteDevice(DeviceObject);
        return Status;
    }

    /* allocate ks device header */
    Status = KsAllocateDeviceHeader(&DeviceExtension->DeviceHeader, 0, NULL);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status);
        IoDeleteSymbolicLink(&SymlinkName);
        IoDeleteDevice(DeviceObject);
        return Status;
    }

    /* start the timer */
    IoStartTimer(DeviceObject);

    DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
    DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;

    return STATUS_SUCCESS;
}
示例#30
0
文件: init.c 项目: MelcherSt/dokany
NTSTATUS
DokanCreateDiskDevice(__in PDRIVER_OBJECT DriverObject, __in ULONG MountId,
                      __in PWCHAR MountPoint, __in PWCHAR UNCName,
                      __in PWCHAR BaseGuid, __in PDOKAN_GLOBAL DokanGlobal,
                      __in DEVICE_TYPE DeviceType,
                      __in ULONG DeviceCharacteristics,
                      __in BOOLEAN UseMountManager, __out PDokanDCB *Dcb) {
  WCHAR diskDeviceNameBuf[MAXIMUM_FILENAME_LENGTH];
  WCHAR symbolicLinkNameBuf[MAXIMUM_FILENAME_LENGTH];
  WCHAR mountPointBuf[MAXIMUM_FILENAME_LENGTH];
  PDEVICE_OBJECT diskDeviceObject;
  PDEVICE_OBJECT volDeviceObject;
  PDokanDCB dcb;
  PDokanVCB vcb;
  UNICODE_STRING diskDeviceName;
  NTSTATUS status;
  BOOLEAN isNetworkFileSystem = (DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM);
  DOKAN_CONTROL dokanControl;

  // make DeviceName and SymboliLink
  if (isNetworkFileSystem) {
#ifdef DOKAN_NET_PROVIDER
    RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_NET_DEVICE_NAME);
    RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_NET_SYMBOLIC_LINK_NAME);
#else
    RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_NET_DEVICE_NAME);
    RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
    RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_NET_SYMBOLIC_LINK_NAME);
    RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
#endif

  } else {
    RtlStringCchCopyW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_DISK_DEVICE_NAME);
    RtlStringCchCatW(diskDeviceNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
    RtlStringCchCopyW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH,
                      DOKAN_SYMBOLIC_LINK_NAME);
    RtlStringCchCatW(symbolicLinkNameBuf, MAXIMUM_FILENAME_LENGTH, BaseGuid);
  }

  RtlInitUnicodeString(&diskDeviceName, diskDeviceNameBuf);

  //
  // Create DeviceObject for the Disk Device
  //
  if (!isNetworkFileSystem) {
    status =
        IoCreateDeviceSecure(DriverObject,          // DriverObject
                             sizeof(DokanDCB),      // DeviceExtensionSize
                             &diskDeviceName,       // DeviceName
                             FILE_DEVICE_DISK,      // DeviceType
                             DeviceCharacteristics, // DeviceCharacteristics
                             FALSE,                 // Not Exclusive
                             &sddl,                 // Default SDDL String
                             NULL,                  // Device Class GUID
                             &diskDeviceObject);    // DeviceObject
  } else {
    status = IoCreateDevice(DriverObject,          // DriverObject
                            sizeof(DokanDCB),      // DeviceExtensionSize
                            NULL,                  // DeviceName
                            FILE_DEVICE_UNKNOWN,   // DeviceType
                            DeviceCharacteristics, // DeviceCharacteristics
                            FALSE,                 // Not Exclusive
                            &diskDeviceObject);    // DeviceObject
  }

  if (!NT_SUCCESS(status)) {
    DDbgPrint("  %s failed: 0x%x\n",
              isNetworkFileSystem ? "IoCreateDevice(FILE_DEVICE_UNKNOWN)"
                                  : "IoCreateDeviceSecure(FILE_DEVICE_DISK)",
              status);
    return status;
  }

  //
  // Initialize the device extension.
  //
  dcb = diskDeviceObject->DeviceExtension;
  *Dcb = dcb;
  dcb->DeviceObject = diskDeviceObject;
  dcb->Global = DokanGlobal;

  dcb->Identifier.Type = DCB;
  dcb->Identifier.Size = sizeof(DokanDCB);

  dcb->MountId = MountId;
  dcb->DeviceType = FILE_DEVICE_DISK;
  dcb->DeviceCharacteristics = DeviceCharacteristics;
  KeInitializeEvent(&dcb->KillEvent, NotificationEvent, FALSE);

  //
  // Establish user-buffer access method.
  //
  diskDeviceObject->Flags |= DO_DIRECT_IO;

  // initialize Event and Event queue
  DokanInitIrpList(&dcb->PendingIrp);
  DokanInitIrpList(&dcb->PendingEvent);
  DokanInitIrpList(&dcb->NotifyEvent);

  KeInitializeEvent(&dcb->ReleaseEvent, NotificationEvent, FALSE);

  // "0" means not mounted
  dcb->Mounted = 0;

  ExInitializeResourceLite(&dcb->Resource);

  dcb->CacheManagerNoOpCallbacks.AcquireForLazyWrite = &DokanNoOpAcquire;
  dcb->CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &DokanNoOpRelease;
  dcb->CacheManagerNoOpCallbacks.AcquireForReadAhead = &DokanNoOpAcquire;
  dcb->CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &DokanNoOpRelease;

  dcb->UseMountManager = UseMountManager;
  if (wcscmp(MountPoint, L"") != 0) {
    RtlStringCchCopyW(mountPointBuf, MAXIMUM_FILENAME_LENGTH,
                      L"\\DosDevices\\");
    if (wcslen(MountPoint) < 4) {
      mountPointBuf[12] = towupper(MountPoint[0]);
      mountPointBuf[13] = L':';
      mountPointBuf[14] = L'\0';
      if (isNetworkFileSystem) {
        dcb->UseMountManager = FALSE;
      }
    } else {
      dcb->UseMountManager = FALSE;
      RtlStringCchCatW(mountPointBuf, MAXIMUM_FILENAME_LENGTH, MountPoint);
    }
  } else {
    RtlStringCchCopyW(mountPointBuf, MAXIMUM_FILENAME_LENGTH, L"");
  }

  dcb->DiskDeviceName = DokanAllocateUnicodeString(diskDeviceNameBuf);
  dcb->SymbolicLinkName = DokanAllocateUnicodeString(symbolicLinkNameBuf);
  dcb->MountPoint = DokanAllocateUnicodeString(mountPointBuf);
  if (UNCName != NULL) {
    dcb->UNCName = DokanAllocateUnicodeString(UNCName);
  }

  if (dcb->DiskDeviceName == NULL || dcb->SymbolicLinkName == NULL ||
      dcb->MountPoint == NULL || (dcb->UNCName == NULL && UNCName != NULL)) {
    DDbgPrint("  Failed to allocate memory for device naming");
    FreeDcbNames(dcb);
    ExDeleteResourceLite(&dcb->Resource);
    IoDeleteDevice(diskDeviceObject);
    return STATUS_INSUFFICIENT_RESOURCES;
  }
  DDbgPrint("DiskDeviceName: %wZ - SymbolicLinkName: %wZ - MountPoint: %wZ\n",
            dcb->DiskDeviceName, dcb->SymbolicLinkName, dcb->MountPoint);

  DDbgPrint("  IoCreateDevice DeviceType: %d\n", DeviceType);

  // Directly create volume device and init vcb here because it has strong
  // dependency with fs/disk
  // Otherwise we would have done this work when mounting the volume

  if (!isNetworkFileSystem) {
    status = IoCreateDevice(DriverObject,          // DriverObject
                            sizeof(DokanVCB),      // DeviceExtensionSize
                            NULL,                  // DeviceName
                            DeviceType,            // DeviceType
                            DeviceCharacteristics, // DeviceCharacteristics
                            FALSE,                 // Not Exclusive
                            &volDeviceObject);     // DeviceObject
  } else {
    status =
        IoCreateDeviceSecure(DriverObject,          // DriverObject
                             sizeof(DokanVCB),      // DeviceExtensionSize
                             &diskDeviceName,       // DeviceName
                             DeviceType,            // DeviceType
                             DeviceCharacteristics, // DeviceCharacteristics
                             FALSE,                 // Not Exclusive
                             &sddl,                 // Default SDDL String
                             NULL,                  // Device Class GUID
                             &volDeviceObject);     // DeviceObject
  }

  if (!NT_SUCCESS(status)) {
    DDbgPrint("  IoCreateDevice failed: 0x%x\n", status);
    ExDeleteResourceLite(&dcb->Resource);
    IoDeleteDevice(diskDeviceObject);
    FreeDcbNames(dcb);
    return status;
  }

  vcb = volDeviceObject->DeviceExtension;
  vcb->Identifier.Type = VCB;
  vcb->Identifier.Size = sizeof(DokanVCB);

  vcb->DeviceObject = volDeviceObject;
  vcb->Dcb = dcb;
  dcb->Vcb = vcb;

  InitializeListHead(&vcb->NextFCB);

  InitializeListHead(&vcb->DirNotifyList);
  FsRtlNotifyInitializeSync(&vcb->NotifySync);

  ExInitializeFastMutex(&vcb->AdvancedFCBHeaderMutex);

#if _WIN32_WINNT >= 0x0501
  FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader,
                           &vcb->AdvancedFCBHeaderMutex);
#else
  if (DokanFsRtlTeardownPerStreamContexts) {
    FsRtlSetupAdvancedHeader(&vcb->VolumeFileHeader,
                             &vcb->AdvancedFCBHeaderMutex);
  }
#endif

  //
  // Create a symbolic link for userapp to interact with the driver.
  //
  status = IoCreateSymbolicLink(dcb->SymbolicLinkName, dcb->DiskDeviceName);

  if (!NT_SUCCESS(status)) {
    ExDeleteResourceLite(&dcb->Resource);
    IoDeleteDevice(diskDeviceObject);
    FreeDcbNames(dcb);
    DDbgPrint("  IoCreateSymbolicLink returned 0x%x\n", status);
    return status;
  }
  DDbgPrint("SymbolicLink: %wZ -> %wZ created\n", dcb->SymbolicLinkName,
            dcb->DiskDeviceName);

  //
  // Establish user-buffer access method.
  //
  volDeviceObject->Flags |= DO_DIRECT_IO;

  DokanInitVpb(diskDeviceObject->Vpb, diskDeviceObject, volDeviceObject);

  // Mark devices as initialized
  diskDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  volDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

  ObReferenceObject(volDeviceObject);
  ObReferenceObject(diskDeviceObject);

  // DokanRegisterMountedDeviceInterface(diskDeviceObject, dcb);

  // Save to the global mounted list
  RtlZeroMemory(&dokanControl, sizeof(dokanControl));
  RtlStringCchCopyW(dokanControl.DeviceName,
                    sizeof(dokanControl.DeviceName) / sizeof(WCHAR),
                    diskDeviceNameBuf);
  RtlStringCchCopyW(dokanControl.MountPoint,
                    sizeof(dokanControl.MountPoint) / sizeof(WCHAR),
                    mountPointBuf);
  dokanControl.Type = DeviceType;
  dokanControl.DeviceObject = volDeviceObject;
  InsertMountEntry(DokanGlobal, &dokanControl);

  dcb->Mounted = 1;

  if (dcb->UseMountManager) {
    status = DokanSendVolumeArrivalNotification(dcb->DiskDeviceName);
    if (!NT_SUCCESS(status)) {
      DDbgPrint("  DokanSendVolumeArrivalNotification failed: 0x%x\n", status);
      if (diskDeviceObject->Vpb) {
        diskDeviceObject->Vpb->DeviceObject = NULL;
        diskDeviceObject->Vpb->RealDevice = NULL;
        diskDeviceObject->Vpb->Flags = 0;
      }
      ExDeleteResourceLite(&dcb->Resource);
      IoDeleteDevice(diskDeviceObject);
      FreeDcbNames(dcb);
      return status;
    }
  }

  DokanCreateMountPoint(dcb);

  if (isNetworkFileSystem) {
    // Run FsRtlRegisterUncProvider in System thread.
    HANDLE handle;
    PKTHREAD thread;
    OBJECT_ATTRIBUTES objectAttribs;

    InitializeObjectAttributes(&objectAttribs, NULL, OBJ_KERNEL_HANDLE, NULL,
                               NULL);
    status = PsCreateSystemThread(
        &handle, THREAD_ALL_ACCESS, &objectAttribs, NULL, NULL,
        (PKSTART_ROUTINE)DokanRegisterUncProvider, dcb);
    if (!NT_SUCCESS(status)) {
      DDbgPrint("PsCreateSystemThread failed: 0x%X\n", status);
    } else {
      ObReferenceObjectByHandle(handle, THREAD_ALL_ACCESS, NULL, KernelMode,
                                &thread, NULL);
      ZwClose(handle);
      KeWaitForSingleObject(thread, Executive, KernelMode, FALSE, NULL);
      ObDereferenceObject(thread);
    }
  }
  // DokanRegisterDeviceInterface(DriverObject, diskDeviceObject, dcb);

  return STATUS_SUCCESS;
}