Пример #1
0
NTSTATUS bus_plugin_dev(ioctl_usbvbus_plugin * plugin, PFDO_DEVICE_DATA  fdodata,
		PFILE_OBJECT fo)
{
    PDEVICE_OBJECT      pdo;
    PPDO_DEVICE_DATA    pdodata, old_pdodata;
    NTSTATUS            status;
    ULONG               len;
    PLIST_ENTRY         entry;
    unsigned long i;

    PAGED_CODE ();

    Bus_KdPrint (fdodata, BUS_DBG_PNP_INFO,
                  ("Exposing PDO\n"
                   "======addr:  %d\n"
                   "======vendor:product: %04x:%04x\n",
                   plugin->addr,
		   plugin->vendor, plugin->product));

    if(plugin->addr <= 0)
        return STATUS_INVALID_PARAMETER;

    ExAcquireFastMutex (&fdodata->Mutex);

    for (entry = fdodata->ListOfPDOs.Flink;
         entry != &fdodata->ListOfPDOs;
         entry = entry->Flink) {

        pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
        if (plugin->addr == pdodata->SerialNo &&
            pdodata->DevicePnPState != SurpriseRemovePending)
        {
	    ExReleaseFastMutex (&fdodata->Mutex);
	    return STATUS_INVALID_PARAMETER;
        }
    }

    ExReleaseFastMutex (&fdodata->Mutex);

    // Create the PDO
    //


    Bus_KdPrint(fdodata, BUS_DBG_PNP_NOISE,
                 ("fdodata->NextLowerDriver = 0x%p\n", fdodata->NextLowerDriver));

    //
    // PDO must have a name. You should let the system auto generate a
    // name by specifying FILE_AUTOGENERATED_DEVICE_NAME in the
    // DeviceCharacteristics parameter. Let us create a secure deviceobject,
    // in case the child gets installed as a raw device (RawDeviceOK), to prevent
    // an unpriviledged user accessing our device. This function is avaliable
    // in a static WDMSEC.LIB and can be used in Win2k, XP, and Server 2003
    // Just make sure that  the GUID specified here is not a setup class GUID.
    // If you specify a setup class guid, you must make sure that class is
    // installed before enumerating the PDO.
    //

    status = IoCreateDeviceSecure(fdodata->Self->DriverObject,
                sizeof (PDO_DEVICE_DATA),
                NULL,
                FILE_DEVICE_BUS_EXTENDER,
                FILE_AUTOGENERATED_DEVICE_NAME |FILE_DEVICE_SECURE_OPEN,
                FALSE,
                &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX, // allow normal users to access the devices
                (LPCGUID)&GUID_SD_BUSENUM_PDO,
                &pdo);
    if (!NT_SUCCESS (status)) {
        return status;
    }

    pdodata = (PPDO_DEVICE_DATA) pdo->DeviceExtension;

#define HARDWARE_IDS_TPL L"USB\\Vid_%04x&Pid_%04x&Rev_%04xZUSB\\Vid_%04x&Pid_%04xZ"

    len = sizeof(HARDWARE_IDS_TPL);
    pdodata->HardwareIDs =
            ExAllocatePoolWithTag (NonPagedPool, len, BUSENUM_POOL_TAG);
    if (NULL == pdodata->HardwareIDs) {
        IoDeleteDevice(pdo);
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlStringCchPrintfW(pdodata->HardwareIDs, len/sizeof(wchar_t),
		HARDWARE_IDS_TPL,
	        plugin->vendor, plugin->product, plugin->version,
	        plugin->vendor, plugin->product);
    for(i=0;i<len/sizeof(wchar_t);i++){
	    if('Z'==pdodata->HardwareIDs[i])
		    pdodata->HardwareIDs[i]=0;
    }
#define COMPATIBLE_IDS_TPL L"USB\\Class_%02x&SubClass_%02x&Prot_%02xZUSB\\Class_%02x&SubClass_%02xZUSB\\Class_%02xZ"
#define COMPATIBLE_COMPOSITE_IDS_TPL L"USB\\Class_%02x&SubClass_%02x&Prot_%02xZUSB\\Class_%02x&SubClass_%02xZUSB\\Class_%02xZUSB\\COMPOSITEZ"
    if(plugin->inum>1)
	   len = sizeof(COMPATIBLE_COMPOSITE_IDS_TPL);
    else
	   len = sizeof(COMPATIBLE_IDS_TPL);
    pdodata->compatible_ids =
            ExAllocatePoolWithTag (NonPagedPool, len, BUSENUM_POOL_TAG);
    
	if (NULL == pdodata->compatible_ids) {
		ExFreePool(pdodata->HardwareIDs);
        IoDeleteDevice(pdo);
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(pdodata->compatible_ids, len);

    pdodata->compatible_ids_len = len;
    RtlStringCchPrintfW(pdodata->compatible_ids, len/sizeof(wchar_t),
		(plugin->inum>1)?COMPATIBLE_COMPOSITE_IDS_TPL:COMPATIBLE_IDS_TPL,
	        plugin->int0_class, plugin->int0_subclass, plugin->int0_protocol,
		plugin->int0_class, plugin->int0_subclass,
		plugin->int0_class);
    for(i=0;i<len/sizeof(wchar_t);i++){
	    if('Z'==pdodata->compatible_ids[i])
		    pdodata->compatible_ids[i]=0;
    }
    old_pdodata = (PPDO_DEVICE_DATA) InterlockedCompareExchangePointer(&(fo->FsContext), pdodata, 0);
    if(old_pdodata){
	    KdPrint(("you can't plugin again"));
	    ExFreePool(pdodata->HardwareIDs);
	    ExFreePool(pdodata->compatible_ids);
	   IoDeleteDevice(pdo);
           return STATUS_INVALID_PARAMETER;
    }
    pdodata->SerialNo = plugin->addr;
    pdodata->fo = fo;
    pdodata->devid = plugin->devid;
    pdodata->speed = plugin->speed;
    bus_init_pdo (pdo, fdodata);

    //
    // Device Relation changes if a new pdo is created. So let
    // the PNP system now about that. This forces it to send bunch of pnp
    // queries and cause the function driver to be loaded.
    //

    IoInvalidateDeviceRelations (fdodata->UnderlyingPDO, BusRelations);

    return status;
}
Пример #2
0
// for pdo
NTSTATUS DoPdoPnP(PDEVICE_OBJECT pDevice,PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PPdoExt pPdoExt = static_cast<PPdoExt>(pDevice->DeviceExtension);

	PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);

	switch(pIoStack->MinorFunction)
	{
	case IRP_MN_START_DEVICE:
		// set power state
		pPdoExt->m_devPowerState = PowerDeviceD0;
		POWER_STATE state;
		state.DeviceState = PowerDeviceD0;
		PoSetPowerState(pDevice,DevicePowerState,state);

		// set pnp state directly
	case IRP_MN_STOP_DEVICE:
	case IRP_MN_QUERY_STOP_DEVICE:
	case IRP_MN_QUERY_REMOVE_DEVICE:
		SetNewPnpState(pPdoExt,pIoStack->MinorFunction);
		break;

		// check prev state
	case IRP_MN_CANCEL_REMOVE_DEVICE:
		if(pPdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_REMOVE_DEVICE)
		{
			RestorePnpState(pPdoExt);
		}
		break;

		// the same
	case IRP_MN_CANCEL_STOP_DEVICE:
		if(pPdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_STOP_DEVICE)
		{
			RestorePnpState(pPdoExt);
		}
		break;

		// remove
	case IRP_MN_REMOVE_DEVICE:
		{
			// delete only if we have reported the device physical removal
			if(pPdoExt->m_bReportMissing)
			{
				SetNewPnpState(pPdoExt,IRP_MN_REMOVE_DEVICE);

				PDEVICE_OBJECT pFdo = pPdoExt->m_pParentFdo;
				if(pFdo)
				{
					PFdoExt pFdoExt = static_cast<PFdoExt>(pFdo->DeviceExtension);

					// update fdo's pointer
					ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo);
					pFdoExt->m_pEnumPdo = NULL;
					ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);
				}

				// delete device
				IoDeleteDevice(pDevice);
			}

			// if it's present
			if(pPdoExt->m_bPresent)
			{
				// set it as stopped
				SetNewPnpState(pPdoExt,IRP_MN_STOP_DEVICE);
			}
		}
		break;

		// query caps
	case IRP_MN_QUERY_CAPABILITIES:
		{
			PDEVICE_CAPABILITIES pCaps = pIoStack->Parameters.DeviceCapabilities.Capabilities;

			// version check
			if(pCaps->Version != 1 || pCaps->Size < sizeof(DEVICE_CAPABILITIES))
			{
				status = STATUS_UNSUCCESSFUL; 
				break;
			}

			IO_STATUS_BLOCK     ioStatus;
			KEVENT              pnpEvent;
			PDEVICE_OBJECT      pTargetObject;
			PIO_STACK_LOCATION  pIrpStack;
			PIRP                pPnpIrp;

			DEVICE_CAPABILITIES parentCaps;

			RtlZeroMemory(&parentCaps,sizeof(DEVICE_CAPABILITIES));
			parentCaps.Size = sizeof(DEVICE_CAPABILITIES);
			parentCaps.Version = 1;
			parentCaps.Address = -1;
			parentCaps.UINumber = -1;

			KeInitializeEvent(&pnpEvent,NotificationEvent,FALSE);

			pTargetObject = IoGetAttachedDeviceReference(
								static_cast<PFdoExt>(pPdoExt->m_pParentFdo->DeviceExtension)->m_pLowerDevice);

			// get parent fdo's caps
			pPnpIrp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,pTargetObject,NULL,0,NULL,&pnpEvent,&ioStatus);
			if(pPnpIrp == NULL) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
			else
			{
				pPnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
				pIrpStack = IoGetNextIrpStackLocation(pPnpIrp);

				RtlZeroMemory(pIrpStack,sizeof(IO_STACK_LOCATION));
				pIrpStack->MajorFunction = IRP_MJ_PNP;
				pIrpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
				pIrpStack->Parameters.DeviceCapabilities.Capabilities = pCaps;
				status = IoCallDriver(pTargetObject,pPnpIrp);
				if (status == STATUS_PENDING) 
				{
					KeWaitForSingleObject(&pnpEvent,Executive,KernelMode,FALSE,NULL);
					status = ioStatus.Status;
				}
			}

			// dec the ref of the fdo's stack upper device
			ObDereferenceObject(pTargetObject);

			// copy the device state
			RtlCopyMemory(pCaps->DeviceState,parentCaps.DeviceState,(PowerSystemShutdown + 1) * sizeof(DEVICE_POWER_STATE));

			// set our own supported device state
			pCaps->DeviceState[PowerSystemWorking] = PowerDeviceD0;

			if(pCaps->DeviceState[PowerSystemSleeping1] != PowerDeviceD0)
				pCaps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3;

			if(pCaps->DeviceState[PowerSystemSleeping2] != PowerDeviceD0)
				pCaps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3;

			if(pCaps->DeviceState[PowerSystemSleeping3] != PowerDeviceD0)
				pCaps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3;

			// donot support d1 and d2
			pCaps->DeviceD1 = pCaps->DeviceD2 = FALSE;

			// no wake
			pCaps->DeviceWake = PowerDeviceUnspecified;
			pCaps->SystemWake = PowerSystemUnspecified;

			pCaps->WakeFromD0 = FALSE;
			pCaps->WakeFromD1 = FALSE;
			pCaps->WakeFromD2 = FALSE;
			pCaps->WakeFromD3 = FALSE;

			// no latency
			pCaps->D1Latency = 0;
			pCaps->D2Latency = 0;
			pCaps->D3Latency = 0;

			// can eject
			pCaps->EjectSupported = TRUE;

			// don't disable
			pCaps->HardwareDisabled = FALSE;

			// can be removed
			pCaps->Removable = TRUE;

			// don't display surprise remove warning dlg
			pCaps->SurpriseRemovalOK = TRUE;

			// no unique id
			pCaps->UniqueID = FALSE;

			// nead user action for install
			pCaps->SilentInstall = FALSE;

			// bus address
			pCaps->Address = 0;

			// ui display number
			pCaps->UINumber = 0;
		}
		break;

		// query pdo id
	case IRP_MN_QUERY_ID:
		{
			switch(pIoStack->Parameters.QueryId.IdType)
			{
			case BusQueryInstanceID:
				{
					PVOID buffer = ExAllocatePoolWithTag(PagedPool,10,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}

					RtlStringCchPrintfW(static_cast<PWCHAR>(buffer),10,L"%04d",0);
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tBusQueryInstanceID\n");
				}
				break;

			case BusQueryDeviceID:
				{
					PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_DEVICE_ID_LENGTH,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}
					RtlCopyMemory(buffer,PDO_DEVICE_ID,PDO_DEVICE_ID_LENGTH);
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tBusQueryDeviceID\n");
				}
				break;

			case BusQueryHardwareIDs:
				{
					PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_HARDWARE_IDS_LENGTH,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}
					RtlCopyMemory(buffer,PDO_HARDWARE_IDS,PDO_HARDWARE_IDS_LENGTH);
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tBusQueryHardwareIDs\n");
				}
				break;

			case BusQueryCompatibleIDs:
				{
					PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_COMPATIBLE_IDS_LENGTH,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}
					RtlCopyMemory(buffer,PDO_COMPATIBLE_IDS,PDO_COMPATIBLE_IDS_LENGTH);
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tBusQueryCompatibleIDs\n");
				}
				break;
			}
		}
		break;

		// query text
	case IRP_MN_QUERY_DEVICE_TEXT:
		{
			switch (pIoStack->Parameters.QueryDeviceText.DeviceTextType) 
			{
			case DeviceTextDescription:
				if(!pIrp->IoStatus.Information) 
				{
					PVOID buffer = ExAllocatePoolWithTag (PagedPool,PDO_TEXT_LENGTH,'suBT');
					if(!buffer) 
					{
						status = STATUS_INSUFFICIENT_RESOURCES;
						break;
					}

					RtlStringCchPrintfW(static_cast<PWCHAR>(buffer),PDO_TEXT_LENGTH,L"%ws",PDO_TEXT);
					
					pIrp->IoStatus.Information = PtrToUlong(buffer);
					devDebugPrint("\tDeviceTextDescription\n");
				}
				break;

			default:
				status = pIrp->IoStatus.Status;
				break;
			}
		}
		break;

		// boot resource
	case IRP_MN_QUERY_RESOURCES:
		{
			PCM_RESOURCE_LIST pResList = static_cast<PCM_RESOURCE_LIST>(ExAllocatePoolWithTag(PagedPool,
																			sizeof(CM_RESOURCE_LIST),'suBT'));

			if(pResList)
			{
				// shareed busnumber resource 
				RtlZeroMemory(pResList,sizeof(CM_RESOURCE_LIST));

				pResList->Count = 1;
				pResList->List[0].BusNumber = 0;
				pResList->List[0].InterfaceType = Internal;
				pResList->List[0].PartialResourceList.Count = 1;
				pResList->List[0].PartialResourceList.Revision = 1;
				pResList->List[0].PartialResourceList.Version = 1;
				pResList->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareShared;
				pResList->List[0].PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeBusNumber;
				pResList->List[0].PartialResourceList.PartialDescriptors[0].u.BusNumber.Length = 1;

				pIrp->IoStatus.Information = PtrToUlong(pResList);
			}
			else
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
		}
		break;

		// resource requirements
	case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
		{
			PIO_RESOURCE_REQUIREMENTS_LIST pList = static_cast<PIO_RESOURCE_REQUIREMENTS_LIST>(
										ExAllocatePoolWithTag(PagedPool,sizeof(IO_RESOURCE_REQUIREMENTS_LIST),'suBT'));

			if(pList)
			{
				RtlZeroMemory(pList,sizeof(IO_RESOURCE_REQUIREMENTS_LIST));

				pList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
				pList->AlternativeLists = 1;
				pList->InterfaceType = InterfaceTypeUndefined;
				pList->BusNumber = 0;
				pList->List[0].Version = 1;
				pList->List[0].Revision = 1;
				pList->List[0].Count = 1;
				pList->List[0].Descriptors[0].Option = IO_RESOURCE_PREFERRED;
				pList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared;

				pList->List[0].Descriptors[0].Type = CmResourceTypeBusNumber;
				pList->List[0].Descriptors[0].u.BusNumber.MaxBusNumber = 0x10;
				pList->List[0].Descriptors[0].u.BusNumber.Length = 1;

				pIrp->IoStatus.Information = PtrToUlong(pList);
			}
			else
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
			}
		}
		break;

		// bus info
	case IRP_MN_QUERY_BUS_INFORMATION:
		{
			PPNP_BUS_INFORMATION busInfo;

			busInfo = static_cast<PPNP_BUS_INFORMATION>(ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION),'suBT'));

			if (busInfo == NULL) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}

			busInfo->BusTypeGuid = GUID_TIAMO_BUS;

			busInfo->LegacyBusType = Internal;

			busInfo->BusNumber = 0;

			pIrp->IoStatus.Information = PtrToUlong(busInfo);
		}
		break;

		// usage
	case IRP_MN_DEVICE_USAGE_NOTIFICATION:
		status = STATUS_UNSUCCESSFUL;
		break;

	case IRP_MN_EJECT:
		{
			// device physical removed
			pPdoExt->m_bPresent = FALSE;
		}
		break;

	//case IRP_MN_QUERY_INTERFACE:
	//	break;

		// target relations
	case IRP_MN_QUERY_DEVICE_RELATIONS:
		{
			if(pIoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
			{
				/*switch(pIoStack->Parameters.QueryDeviceRelations.Type)
				{
				case EjectionRelations:
				devDebugPrint("\tquery EjectionRelations\n");
				break;
				case PowerRelations:
				devDebugPrint("\tquery PowerRelations\n");
				break;
				case RemovalRelations:
				devDebugPrint("\tquery RemovalRelations\n");
				break;
				case BusDeviceRelation:
				devDebugPrint("\tquery BusDeviceRelation\n");
				break;
				case SingleBusRelations:
				devDebugPrint("\tquery SingleBusRelations\n");
				break;
				}*/
				break;
			}

			PDEVICE_RELATIONS pRel = static_cast<PDEVICE_RELATIONS>(ExAllocatePoolWithTag(PagedPool,sizeof(DEVICE_RELATIONS),'suBT'));
			if(!pRel) 
			{
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}

			pRel->Count = 1;
			pRel->Objects[0] = pDevice;
			ObReferenceObject(pDevice);

			status = STATUS_SUCCESS;
			pIrp->IoStatus.Information = PtrToUlong(pRel);
		}
		break;

	default:
		status = pIrp->IoStatus.Status;
		break;
	}

	// pdo should complete the irp
	pIrp->IoStatus.Status = status;
	IoCompleteRequest (pIrp, IO_NO_INCREMENT);

	return status;
}
Пример #3
0
NTSTATUS
SecondaryRecoverySession (
	IN  PSECONDARY		Secondary
	)
{
	NTSTATUS			status;
	LONG				slotIndex;

	LARGE_INTEGER		timeOut;
	OBJECT_ATTRIBUTES	objectAttributes;

	ULONG				reconnectionTry;
    PLIST_ENTRY			ccblistEntry;
	BOOLEAN				isLocalAddress;


	SetFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

	ASSERT( FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ); 
	ASSERT( Secondary->ThreadHandle );

	ASSERT( IsListEmpty(&Secondary->RequestQueue) );

	for (slotIndex=0; slotIndex < Secondary->Thread.SessionContext.SessionSlotCount; slotIndex++) {

		ASSERT( Secondary->Thread.SessionSlot[slotIndex] == NULL );
	}	

	if (Secondary->ThreadHandle) {

		ASSERT( Secondary->ThreadObject );
		
		timeOut.QuadPart = -NDASNTFS_TIME_OUT;
		status = KeWaitForSingleObject( Secondary->ThreadObject,
										Executive,
										KernelMode,
										FALSE,
										&timeOut );

		if(status != STATUS_SUCCESS) {

			ASSERT( NDASNTFS_BUG );
			return status;
		}

		DebugTrace( 0, Dbg2, ("Secondary_Stop: thread stoped\n") );

		ObDereferenceObject( Secondary->ThreadObject );

		Secondary->ThreadHandle = 0;
		Secondary->ThreadObject = 0;

		RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );
	}

	for (status = STATUS_UNSUCCESSFUL, reconnectionTry = 0; reconnectionTry < MAX_RECONNECTION_TRY; reconnectionTry++) {

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_TARGET_DEVICE_STOPPED)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_FLAG_SHUTDOWN)) {

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (FlagOn(Secondary->VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN)) {

			//DebugTrace( 0, Dbg2, ("SecondaryToPrimary NDAS_NTFS_DEVICE_FLAG_SHUTDOWN\n") ); 
			//DbgPrint( "SecondaryToPrimary NDAS_NTFS_DEVICE_FLAG_SHUTDOWN\n" ); 

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );
			return STATUS_UNSUCCESSFUL;
		}

		if (Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY) {

			status = STATUS_SUCCESS;

		} else {

			status = ((PVOLUME_DEVICE_OBJECT) NdasNtfsFileSystemDeviceObject)->
						NdfsCallback.SecondaryToPrimary( Secondary->VolDo->Vcb.Vpb->RealDevice, TRUE );

			if (status == STATUS_NO_SUCH_DEVICE) {

				NDASNTFS_ASSERT( FlagOn(Secondary->VolDo->Vcb.VcbState, VCB_STATE_TARGET_DEVICE_STOPPED) );
				ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

				return STATUS_UNSUCCESSFUL;
			}
		}


		//NtfsDebugTraceLevel = 0;

		DebugTrace( 0, Dbg2, ("SecondaryToPrimary status = %x\n", status) ); 

		if (status == STATUS_SUCCESS) {

			PVCB				vcb = &Secondary->VolDo->Vcb;
			TOP_LEVEL_CONTEXT	topLevelContext;
			PTOP_LEVEL_CONTEXT	threadTopLevelContext;
			PIRP_CONTEXT		tempIrpContext = NULL;

			SetFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	


			DebugTrace( 0, Dbg2, ("Vcb->State = %X\n", vcb->VcbState) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );

			tempIrpContext = NULL;

			threadTopLevelContext = NtfsInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			NtfsInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            NtfsUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );

			SetFlag( tempIrpContext->NdasNtfsFlags, NDAS_NTFS_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
						
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;

			try {
			
				status = CleanUpVcb( tempIrpContext, vcb );
			
			} finally {
                
				NtfsCompleteRequest( tempIrpContext, NULL, 0 );
				ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			ASSERT( status == STATUS_SUCCESS );
			ASSERT( FlagOn(vcb->VcbState, VCB_STATE_MOUNT_COMPLETED) );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	

			ClearFlag( Secondary->Flags, SECONDARY_FLAG_CLEANUP_VOLUME );


			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->CloseCount) );

			Secondary->VolDo->NetdiskEnableMode = NETDISK_SECONDARY2PRIMARY; 

			tempIrpContext = NULL;

			threadTopLevelContext = NtfsInitializeTopLevelIrp( &topLevelContext, TRUE, FALSE );
			ASSERT( threadTopLevelContext == &topLevelContext );

			NtfsInitializeIrpContext( NULL, TRUE, &tempIrpContext );
            NtfsUpdateIrpContextWithTopLevel( tempIrpContext, threadTopLevelContext );

			ASSERT( FlagOn(tempIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL) );
			
			//tempIrpContext->TopLevelIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			//tempIrpContext->TopLevelIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			
			tempIrpContext->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
			tempIrpContext->MinorFunction = IRP_MN_MOUNT_VOLUME;
			tempIrpContext->Vcb			  = vcb;

			try {
			
				status = NdasNtfsMountVolume( tempIrpContext, vcb );
			
			} finally {
                
				NtfsCompleteRequest( tempIrpContext, NULL, 0 );
				ASSERT( IoGetTopLevelIrp() != (PIRP) &topLevelContext );
				tempIrpContext = NULL;
			}

			NDASNTFS_ASSERT( status == STATUS_SUCCESS );

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&NtfsData.Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&NtfsData.Resource) );	

			ASSERT( !ExIsResourceAcquiredExclusiveLite(&vcb->Resource) );			
			ASSERT( !ExIsResourceAcquiredSharedLite(&vcb->Resource) );	

			DebugTrace( 0, Dbg2, ("Vcb->TargetDeviceObject->ReferenceCount = %X\n", vcb->TargetDeviceObject->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->Vpb->ReferenceCount = %X\n", vcb->Vpb->ReferenceCount) );
			DebugTrace( 0, Dbg2, ("Vcb->CloseCount = %d\n", vcb->CloseCount) );

			if (vcb->MftScb) {
			
				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftScb->Header.Resource) );	
			}

			if (vcb->Mft2Scb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->Mft2Scb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->Mft2Scb->Header.Resource) );	
			}

			if (vcb->LogFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->LogFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->LogFileScb->Header.Resource) );			
			}

			if (vcb->VolumeDasdScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->VolumeDasdScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->VolumeDasdScb->Header.Resource) );			
			}

			if (vcb->AttributeDefTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->AttributeDefTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->AttributeDefTableScb->Header.Resource) );			
			}

			if (vcb->UpcaseTableScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UpcaseTableScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UpcaseTableScb->Header.Resource) );			
			}

			if (vcb->RootIndexScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->RootIndexScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->RootIndexScb->Header.Resource) );			
			}

			if (vcb->BitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BitmapScb->Header.Resource) );			
			}

			if (vcb->BadClusterFileScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->BadClusterFileScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->BadClusterFileScb->Header.Resource) );		
			}

			if (vcb->MftBitmapScb) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->MftBitmapScb->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->MftBitmapScb->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorStream) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorStream->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorStream->Header.Resource) );			
			}

			if (vcb->UsnJournal) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->UsnJournal->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->UsnJournal->Header.Resource) );			
			}

			if (vcb->ExtendDirectory) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->ExtendDirectory->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->ExtendDirectory->Header.Resource) );			
			}

			if (vcb->SecurityDescriptorHashIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityDescriptorHashIndex->Header.Resource) );			
			}

			if (vcb->SecurityIdIndex) {

				ASSERT( !ExIsResourceAcquiredExclusiveLite(vcb->SecurityIdIndex->Header.Resource) );			
				ASSERT( !ExIsResourceAcquiredSharedLite(vcb->SecurityIdIndex->Header.Resource) );			
			}
		}

		status = ((PVOLUME_DEVICE_OBJECT) NdasNtfsFileSystemDeviceObject)->
						NdfsCallback.QueryPrimaryAddress( &Secondary->VolDo->NetdiskPartitionInformation, &Secondary->PrimaryAddress, &isLocalAddress );

		DebugTrace( 0, Dbg2, ("RecoverSession: LfsTable_QueryPrimaryAddress status = %X\n", status) );
	
		if (status == STATUS_SUCCESS && !(Secondary->VolDo->NetdiskEnableMode == NETDISK_SECONDARY && isLocalAddress)) {

			DebugTrace( 0, Dbg, ("SessionRecovery: Found PrimaryAddress :%02x:%02x:%02x:%02x:%02x:%02x/%d\n",
								  Secondary->PrimaryAddress.Node[0],
								  Secondary->PrimaryAddress.Node[1],
								  Secondary->PrimaryAddress.Node[2],
								  Secondary->PrimaryAddress.Node[3],
								  Secondary->PrimaryAddress.Node[4],
								  Secondary->PrimaryAddress.Node[5],
								  NTOHS(Secondary->PrimaryAddress.Port)) );
		
		} else {

			continue;
		}	
		
		KeInitializeEvent( &Secondary->ReadyEvent, NotificationEvent, FALSE );
		KeInitializeEvent( &Secondary->RequestEvent, NotificationEvent, FALSE );

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

		status = PsCreateSystemThread( &Secondary->ThreadHandle,
									   THREAD_ALL_ACCESS,
									   &objectAttributes,
									   NULL,
									   NULL,
									   SecondaryThreadProc,
									   Secondary );

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASNTFS_UNEXPECTED );
			break;
		}

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

		if (!NT_SUCCESS(status)) {

			ASSERT( NDASNTFS_INSUFFICIENT_RESOURCES );
			break;
		}

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

		if(status != STATUS_SUCCESS) {

			ASSERT( NDASNTFS_BUG );
			break;
		}

		KeClearEvent( &Secondary->ReadyEvent );

		InterlockedIncrement( &Secondary->SessionId );	

		ExAcquireFastMutex( &Secondary->FastMutex );

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

			ExReleaseFastMutex( &Secondary->FastMutex );

			if(Secondary->Thread.SessionStatus == STATUS_DISK_CORRUPT_ERROR) {

				status = STATUS_SUCCESS;
				break;
			}

			timeOut.QuadPart = -NDASNTFS_TIME_OUT;
			status = KeWaitForSingleObject( Secondary->ThreadObject,
											Executive,
											KernelMode,
											FALSE,
											&timeOut );

			if(status != STATUS_SUCCESS) {

				ASSERT( NDASNTFS_BUG );
				return status;
			}

			DebugTrace( 0, Dbg, ("Secondary_Stop: thread stoped\n") );

			ObDereferenceObject( Secondary->ThreadObject );

			Secondary->ThreadHandle = 0;
			Secondary->ThreadObject = 0;

			RtlZeroMemory( &Secondary->Thread.Flags, sizeof(SECONDARY) - FIELD_OFFSET(SECONDARY, Thread.Flags) );

			continue;
		} 

		ExReleaseFastMutex( &Secondary->FastMutex );

		status = STATUS_SUCCESS;

		DebugTrace( 0, Dbg2, ("SessionRecovery Success Secondary = %p\n", Secondary) );

		break;
	}
Пример #4
0
VOID
SecondaryTryClose (
	IN PSECONDARY	Secondary
	)
{
	PIRP_CONTEXT	irpContext;

	BOOLEAN			secondaryResourceAcquired = FALSE;
	BOOLEAN			acquiredVcb = FALSE;
	BOOLEAN			wait;

	irpContext = FatAllocateIrpContext();

	if (irpContext == NULL) {

		return;
	}

	DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles start\n") );

	try {

		RtlZeroMemory( irpContext, sizeof(IRP_CONTEXT) );
		SetFlag( irpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
		SetFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
		irpContext->Vcb = &Secondary->VolDo->Vcb;

		secondaryResourceAcquired = SecondaryAcquireResourceSharedLite( irpContext, 
																		&Secondary->VolDo->Resource, 
																		FALSE );
		if (secondaryResourceAcquired == FALSE) {

			leave;
		}

		wait = BooleanFlagOn( irpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

		acquiredVcb = FatAcquireExclusiveVcb( irpContext, irpContext->Vcb );

		if (acquiredVcb == FALSE) {

			leave;
		}

		FsRtlEnterFileSystem();
		FatFspClose( &Secondary->VolDo->Vcb );
		FsRtlExitFileSystem();

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles FatFspClose, Secondary->VolDo->Vcb.SecondaryOpenCount = %d\n", 
							    Secondary->VolDo->Vcb.SecondaryOpenFileCount) );

		SetFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		Secondary_TryCloseFilExts( Secondary );

	} finally {

		ClearFlag( irpContext->NdasFatFlags, NDAS_FAT_IRP_CONTEXT_FLAG_TRY_CLOSE_FILES );

		if (acquiredVcb) {

			FatReleaseVcb( irpContext, irpContext->Vcb );
		}

		DebugTrace2( 0, Dbg, ("Secondary_TryCloseFiles exit\n") );

		ExAcquireFastMutex( &Secondary->FastMutex );		
		Secondary->TryCloseActive = FALSE;
		ExReleaseFastMutex( &Secondary->FastMutex );

		if (secondaryResourceAcquired)
			SecondaryReleaseResourceLite( NULL, &Secondary->VolDo->Resource );

		Secondary_Dereference(Secondary);

		FatFreeIrpContext(irpContext);
	}

	return;
}
Пример #5
0
NTSTATUS
FatCommonPnp (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

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

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    
    PIO_STACK_LOCATION IrpSp;

    PVOLUME_DEVICE_OBJECT OurDeviceObject;
    PVCB Vcb;

    //
    //  Force everything to wait.
    //
    
    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
    
    //
    //  Get the current Irp stack location.
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    //  Find our Vcb.  This is tricky since we have no file object in the Irp.
    //

    OurDeviceObject = (PVOLUME_DEVICE_OBJECT) IrpSp->DeviceObject;

    //
    //  Take the global lock to synchronise against volume teardown.
    //

    FatAcquireExclusiveGlobal( IrpContext );    
    
    //
    //  Make sure this device object really is big enough to be a volume device
    //  object.  If it isn't, we need to get out before we try to reference some
    //  field that takes us past the end of an ordinary device object.
    //
    
    if (OurDeviceObject->DeviceObject.Size != sizeof(VOLUME_DEVICE_OBJECT) ||
        NodeType( &OurDeviceObject->Vcb ) != FAT_NTC_VCB) {
        
        //
        //  We were called with something we don't understand.
        //

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

#if __NDAS_FAT__
	if (OurDeviceObject->NetdiskEnableMode == NETDISK_SECONDARY)
		SetFlag( IrpContext->NdFatFlags, ND_FAT_IRP_CONTEXT_FLAG_SECONDARY_CONTEXT );
#endif

    Vcb = &OurDeviceObject->Vcb;

    //
    //  Case on the minor code.
    //
 
#if __NDAS_FAT_SECONDARY__

		if ( ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Secondary &&
		   	( ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode == NETDISK_SECONDARY || 
			  ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode == NETDISK_SECONDARY2PRIMARY )  )
		{
			PSECONDARY	Secondary = ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->Secondary;

			Status = STATUS_SUCCESS;

			Secondary_Reference( Secondary );

			switch ( IrpSp->MinorFunction ) {

			case IRP_MN_QUERY_REMOVE_DEVICE: {

				DebugTrace2( 0, Dbg, ("FatCommonPnp: IRP_MN_QUERY_REMOVE_DEVICE NetdiskEnableMode = %d\n", ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) );

				ExAcquireFastMutex( &Secondary->FastMutex );	

				if (!Secondary->TryCloseActive) {
				
					Secondary->TryCloseActive = TRUE;
					ExReleaseFastMutex( &Secondary->FastMutex );
					Secondary_Reference( Secondary );
					//FatDebugTraceLevel |= DEBUG_TRACE_CLOSE;
					SecondaryTryClose( IrpContext, Secondary );
					//FatDebugTraceLevel &= ~DEBUG_TRACE_CLOSE;
				
				} else {
				
					ExReleaseFastMutex( &Secondary->FastMutex );
				}

				if (Vcb->SecondaryOpenFileCount) {

					LARGE_INTEGER interval;

					// Wait all files closed
					interval.QuadPart = (1 * HZ);      //delay 1 seconds
					KeDelayExecutionThread(KernelMode, FALSE, &interval);
				}

#if 0
				if (Vcb->SecondaryOpenFileCount) {

					LONG		ccbCount;
					PLIST_ENTRY	ccbListEntry;
					PVOID		restartKey;
					PFCB		fcb;

					ExAcquireFastMutex( &Secondary->RecoveryCcbQMutex );

				    for (ccbCount = 0, ccbListEntry = Secondary->RecoveryCcbQueue.Flink; 
						 ccbListEntry != &Secondary->RecoveryCcbQueue; 
						 ccbListEntry = ccbListEntry->Flink, ccbCount++);

					ExReleaseFastMutex( &Secondary->RecoveryCcbQMutex );

					ASSERT( !IsListEmpty(&Secondary->RecoveryCcbQueue) );
					ASSERT( ccbCount == Vcb->SecondaryOpenFileCount );

					DebugTrace2( 0, Dbg, ("IRP_MN_QUERY_REMOVE_DEVICE: Vcb->SecondaryCloseCount = %d, Vcb->CloseCount = %d, ccbCount = %d\n",
                                         Vcb->SecondaryOpenFileCount, Vcb->OpenCount, ccbCount) );

					restartKey = NULL;
					fcb = NdFatGetNextFcbTableEntry( &Secondary->VolDo->Vcb, &restartKey );
					ASSERT( fcb != NULL || !IsListEmpty(&Secondary->DeletedFcbQueue) );

					Status = STATUS_UNSUCCESSFUL;
				}
#endif

				break;
			}

			case IRP_MN_REMOVE_DEVICE: {

				PVOID			restartKey;
				PFCB			fcb;

				DebugTrace2( 0, Dbg, ("FatCommonPnp: IRP_MN_REMOVE_DEVICE NetdiskEnableMode = %d\n", ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) );

#if 0
				restartKey = NULL;
				fcb = NdFatGetNextFcbTableEntry( &Secondary->VolDo->Vcb, &restartKey );
				
				ASSERT( fcb == NULL && IsListEmpty(&Secondary->DeletedFcbQueue) );

#endif

				if (Vcb->SecondaryOpenFileCount) {

					ASSERT( NDFAT_BUG );
					Status =  STATUS_UNSUCCESSFUL;
				}

				break;
			
			}
			default: {

				DebugTrace2( 0, Dbg, ("FatCommonPnp: IrpSp-MinorFunction = %d NetdiskEnableMode = %d\n", 
									   IrpSp->MinorFunction, ((PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject)->NetdiskEnableMode) );


				if (IrpSp->MinorFunction != IRP_MN_QUERY_DEVICE_RELATIONS) {

					if (IrpSp->FileObject && IS_SECONDARY_FILEOBJECT(IrpSp->FileObject)) {

						ASSERT( FALSE );
					}
				}
				
				Status =  STATUS_SUCCESS;
				break;
			}
			}

			Secondary_Dereference( Secondary );	

			if (!NT_SUCCESS(Status)) {

				FatCompleteRequest( NULL, Irp, Status );
				return Status;
			} 
		}

#endif

    switch ( IrpSp->MinorFunction ) {

        case IRP_MN_QUERY_REMOVE_DEVICE:
            
            Status = FatPnpQueryRemove( IrpContext, Irp, Vcb );
            break;
        
        case IRP_MN_SURPRISE_REMOVAL:
        
            Status = FatPnpSurpriseRemove( IrpContext, Irp, Vcb );
            break;

        case IRP_MN_REMOVE_DEVICE:

            Status = FatPnpRemove( IrpContext, Irp, Vcb );
            break;

        case IRP_MN_CANCEL_REMOVE_DEVICE:
    
            Status = FatPnpCancelRemove( IrpContext, Irp, Vcb );
            break;

        default:

            FatReleaseGlobal( IrpContext );
            
            //
            //  Just pass the IRP on.  As we do not need to be in the
            //  way on return, ellide ourselves out of the stack.
            //
            
            IoSkipCurrentIrpStackLocation( Irp );
    
            Status = IoCallDriver(Vcb->TargetDeviceObject, Irp);
            
            //
            //  Cleanup our Irp Context.  The driver has completed the Irp.
            //
        
            FatCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
            
            break;
    }
        
    return Status;
}
Пример #6
0
VOID
Bus_InitializePdo (
    PDEVICE_OBJECT      Pdo,
    PFDO_DEVICE_DATA    FdoData
    )
{
    PPDO_DEVICE_DATA pdoData;
    int acpistate;
    DEVICE_POWER_STATE ntState;

    PAGED_CODE ();

    pdoData = (PPDO_DEVICE_DATA)  Pdo->DeviceExtension;

    DPRINT("pdo 0x%p, extension 0x%p\n", Pdo, pdoData);

    if (pdoData->AcpiHandle)
        acpi_bus_get_power(pdoData->AcpiHandle, &acpistate);
    else
        acpistate = ACPI_STATE_D0;

    switch(acpistate)
    {
        case ACPI_STATE_D0:
            ntState = PowerDeviceD0;
            break;
        case ACPI_STATE_D1:
            ntState = PowerDeviceD1;
            break;
        case ACPI_STATE_D2:
            ntState = PowerDeviceD2;
            break;
        case ACPI_STATE_D3:
            ntState = PowerDeviceD3;
            break;
        default:
            DPRINT1("Unknown power state (%d) returned by acpi\n",acpistate);
            ntState = PowerDeviceUnspecified;
            break;
    }

    //
    // Initialize the rest
    //
    pdoData->Common.IsFDO = FALSE;
    pdoData->Common.Self =  Pdo;

    pdoData->ParentFdo = FdoData->Common.Self;


    INITIALIZE_PNP_STATE(pdoData->Common);

    pdoData->Common.DevicePowerState = ntState;
    pdoData->Common.SystemPowerState = FdoData->Common.SystemPowerState;

    Pdo->Flags |= DO_POWER_PAGABLE;

    ExAcquireFastMutex (&FdoData->Mutex);
    InsertTailList(&FdoData->ListOfPDOs, &pdoData->Link);
    FdoData->NumPDOs++;
    ExReleaseFastMutex (&FdoData->Mutex);

    // This should be the last step in initialization.
    Pdo->Flags &= ~DO_DEVICE_INITIALIZING;

}
Пример #7
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;
}
Пример #8
0
VOID
Readonly_Close (
	IN  PREADONLY	Readonly
	)
{
	NTSTATUS		status;
	LARGE_INTEGER	timeOut;

	PLIST_ENTRY			readonlyRequestEntry;
	PREADONLY_REQUEST	readonlyRequest;


	SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("Readonly close Readonly = %p\n", Readonly) );

	ExAcquireFastMutex( &Readonly->FastMutex );

	ASSERT( !FlagOn(Readonly->Flags, READONLY_FLAG_RECONNECTING) );

	if (FlagOn(Readonly->Flags, READONLY_FLAG_CLOSED)) {

		//ASSERT( FALSE );
		ExReleaseFastMutex( &Readonly->FastMutex );
		return;
	}

	SetFlag( Readonly->Flags, READONLY_FLAG_CLOSED );

	ExReleaseFastMutex( &Readonly->FastMutex );

	FsRtlNotifyUninitializeSync( &Readonly->NotifySync );

	if (Readonly->ThreadHandle == NULL) {

		//ASSERT( FALSE );
		Readonly_Dereference( Readonly );
		return;
	}

	ASSERT( Readonly->ThreadObject != NULL );

	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("Readonly close READONLY_REQ_DISCONNECT Readonly = %p\n", Readonly) );

	readonlyRequest = AllocReadonlyRequest( Readonly, 0, FALSE );
	readonlyRequest->RequestType = READONLY_REQ_DISCONNECT;

	QueueingReadonlyRequest( Readonly, readonlyRequest );

	readonlyRequest = AllocReadonlyRequest( Readonly, 0, FALSE );
	readonlyRequest->RequestType = READONLY_REQ_DOWN;

	QueueingReadonlyRequest( Readonly, readonlyRequest );

	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("Readonly close READONLY_REQ_DISCONNECT end Readonly = %p\n", Readonly) );

	timeOut.QuadPart = -LFS_TIME_OUT;

	status = KeWaitForSingleObject( Readonly->ThreadObject,
									Executive,
									KernelMode,
									FALSE,
									&timeOut );

	if (status == STATUS_SUCCESS) {
	   
		SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("Readonly_Close: thread stoped Readonly = %p\n", Readonly) );

		ObDereferenceObject( Readonly->ThreadObject );

		Readonly->ThreadHandle = NULL;
		Readonly->ThreadObject = NULL;
	
	} else {

		ASSERT( LFS_BUG );
		return;
	}

	if (!IsListEmpty(&Readonly->FcbQueue))
		NDAS_ASSERT( FALSE );

	if (!IsListEmpty(&Readonly->CcbQueue))
		NDAS_ASSERT( FALSE );

	if (!IsListEmpty(&Readonly->RequestQueue))
		NDAS_ASSERT( FALSE );

	while (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue,
															   &Readonly->RequestQSpinLock)) {

		PREADONLY_REQUEST readonlyRequest2;

		InitializeListHead( readonlyRequestEntry );
			
		readonlyRequest2 = CONTAINING_RECORD( readonlyRequestEntry,
											   READONLY_REQUEST,
											   ListEntry );
        
		readonlyRequest2->ExecuteStatus = STATUS_IO_DEVICE_ERROR;
		
		if (readonlyRequest2->Synchronous == TRUE)
			KeSetEvent( &readonlyRequest2->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferenceReadonlyRequest( readonlyRequest2 );
	}
	
	Readonly_Dereference( Readonly );

	return;
}
Пример #9
0
VOID
ReadonlyThreadProc (
	IN	PREADONLY	Readonly
	)
{
	BOOLEAN		readonlyThreadTerminate = FALSE;
	PLIST_ENTRY	readonlyRequestEntry;

	
	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThreadProc: Start Readonly = %p\n", Readonly) );
	
	Readonly_Reference( Readonly );
	
	Readonly->Thread.Flags = READONLY_THREAD_FLAG_INITIALIZING;

	ExAcquireFastMutex( &Readonly->FastMutex );		
	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_START );
	ClearFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_INITIALIZING );
	ExReleaseFastMutex( &Readonly->FastMutex );
			
	KeSetEvent( &Readonly->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	readonlyThreadTerminate = FALSE;
	
	while (readonlyThreadTerminate == FALSE) {

		PKEVENT			events[2];
		LONG			eventCount;
		NTSTATUS		eventStatus;
		LARGE_INTEGER	timeOut;
		

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;
		events[eventCount++] = &Readonly->RequestEvent;

		timeOut.QuadPart = -LFS_READONLY_THREAD_FLAG_TIME_OUT;

		eventStatus = KeWaitForMultipleObjects(	eventCount,
												events,
												WaitAny,
												Executive,
												KernelMode,
												TRUE,
												&timeOut,
												NULL );

		if (eventStatus == STATUS_TIMEOUT) {

			ReadonlyTryCloseCcb( Readonly );
			ReadonlyDismountVolumeStart( Readonly );
			continue;
		}

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
		ASSERT( eventCount < THREAD_WAIT_OBJECTS );
		
		if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) {

			ASSERT( LFS_UNEXPECTED );
			SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_ERROR );
			readonlyThreadTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			while (!FlagOn(Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED) && 
				   (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue,
																	    &Readonly->RequestQSpinLock))) {

				PREADONLY_REQUEST	readonlyRequest;


				InitializeListHead( readonlyRequestEntry );

				readonlyRequest = CONTAINING_RECORD( readonlyRequestEntry,
													  READONLY_REQUEST,
													  ListEntry );

				if (!(readonlyRequest->RequestType == READONLY_REQ_DISCONNECT ||
					  readonlyRequest->RequestType == READONLY_REQ_DOWN		  ||
					  readonlyRequest->RequestType == READONLY_REQ_SEND_MESSAGE)) {

					ASSERT( FALSE );

					ExAcquireFastMutex( &Readonly->FastMutex );
					SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED | READONLY_THREAD_FLAG_ERROR );
					ExReleaseFastMutex( &Readonly->FastMutex );

					ExInterlockedInsertHeadList( &Readonly->RequestQueue,
												 &readonlyRequest->ListEntry,
												 &Readonly->RequestQSpinLock );

					readonlyThreadTerminate = TRUE;
					break;
				}

				if (readonlyRequest->RequestType == READONLY_REQ_DISCONNECT) {
				
					if (readonlyRequest->Synchronous == TRUE)
						KeSetEvent(&readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE);
					else
						DereferenceReadonlyRequest( readonlyRequest );

					continue;
				}

				if (readonlyRequest->RequestType == READONLY_REQ_DOWN) {

					SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThread READONLY_REQ_DOWN Readonly = %p\n", Readonly) );

					ExAcquireFastMutex( &Readonly->FastMutex );		
					SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED );
					ExReleaseFastMutex( &Readonly->FastMutex );

					ASSERT( IsListEmpty(&Readonly->RequestQueue) );

					if (readonlyRequest->Synchronous == TRUE)
						KeSetEvent( &readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferenceReadonlyRequest( readonlyRequest );

					readonlyThreadTerminate = TRUE;
					break;
				}

				ASSERT( readonlyRequest->RequestType == READONLY_REQ_SEND_MESSAGE );
				ASSERT( readonlyRequest->Synchronous == TRUE );

			} // while 
		
		} else {

			NDAS_ASSERT( FALSE );
		}
	}

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	ExAcquireFastMutex( &Readonly->FastMutex );

	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED );

	while (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue,
															   &Readonly->RequestQSpinLock)) {

		PREADONLY_REQUEST readonlyRequest;

		InitializeListHead( readonlyRequestEntry );
			
		readonlyRequest = CONTAINING_RECORD( readonlyRequestEntry,
											  READONLY_REQUEST,
											  ListEntry );
        
		readonlyRequest->ExecuteStatus = STATUS_IO_DEVICE_ERROR;
		
		if (readonlyRequest->Synchronous == TRUE)
			KeSetEvent( &readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferenceReadonlyRequest( readonlyRequest );
	}

	ExReleaseFastMutex( &Readonly->FastMutex );

	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE,
				   ("ReadonlyThreadProc: PsTerminateSystemThread Readonly = %p, IsListEmpty(&Readonly->RequestQueue) = %d\n", 
				     Readonly, IsListEmpty(&Readonly->RequestQueue)) );
	
	ExAcquireFastMutex( &Readonly->FastMutex );
	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_TERMINATED );
	ExReleaseFastMutex( &Readonly->FastMutex );
	
	Readonly_Dereference( Readonly );

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
	
	PsTerminateSystemThread( STATUS_SUCCESS );
}
Пример #10
0
//
// Checks to see if a supplied region is exempted from being allocated into
//
BOOLEAN IsRegionExempted(
		IN PVOID RegionBase,
		IN ULONG RegionSize,
		OUT PULONG EndDisplacement OPTIONAL)
{
	PLIST_ENTRY Current;
	BOOLEAN     Exempted = FALSE;

	//
	// Acquire the region exemption list mutex
	//
	ExAcquireFastMutex(
			&RegionExemptionListMutex);

	//
	// Enumerate through all of the region exemptions
	//
	for (Current = RegionExemptionList.Flink;
	     (Current != &RegionExemptionList) && (!Exempted);
	     Current = Current->Flink)
	{
		PREGION_EXEMPTION Exemption = (PREGION_EXEMPTION)Current;

		Exempted = (
			(IsAddressInsideRange(
				RegionBase,
				Exemption->Base,
				Exemption->Size)) ||
			(IsAddressInsideRange(
				Exemption->Base,
				RegionBase,
				RegionSize))) ? TRUE : FALSE;

		// 
		// If this region is exempted and the caller requested a displacement
		// calculation, pass one back to them such that they can optimize their
		// search by knowing how much to add to their region base to get outside
		// of the exempted region.
		//
		if ((Exempted) &&
		    (EndDisplacement))
		{
			//
			// The number of bytes that will have to be incremented by to get the
			// supplied region out of the area of the exempted region is calculated
			// by subtracting the end of the exempted region from the start of the
			// supplied region.
			//
			*EndDisplacement = (ULONG)((Exemption->Base + Exemption->Size) - (ULONG_PTR)RegionBase);

			//
			// Assert that the end of the exempted region is always greater than
			// the region base, which should always be true.
			//
			ASSERT((Exemption->Base + Exemption->Size) > (ULONG_PTR)RegionBase);
		}
	}

	//
	// Release the region exemption list mutex
	//
	ExReleaseFastMutex(
			&RegionExemptionListMutex);

	return Exempted;
}
Пример #11
0
BOOLEAN
ReadonlyPassThrough (
    IN  PDEVICE_OBJECT				DeviceObject,
    IN  PIRP						Irp,
	IN  PFILESPY_DEVICE_EXTENSION	DevExt,
	OUT PNTSTATUS					NtStatus
	)
{
	NTSTATUS			status = STATUS_SUCCESS;
	BOOLEAN				result = FALSE;
    PIO_STACK_LOCATION	irpSp = IoGetCurrentIrpStackLocation( Irp );
	PFILE_OBJECT		fileObject = irpSp->FileObject;
	BOOLEAN				fastMutexAcquired = FALSE;


	UNREFERENCED_PARAMETER( DeviceObject );

	ASSERT( DevExt->LfsDeviceExt.ReferenceCount );
	LfsDeviceExt_Reference( &DevExt->LfsDeviceExt );	

	PrintIrp( LFS_DEBUG_READONLY_NOISE, __FUNCTION__, &DevExt->LfsDeviceExt, Irp );

	ASSERT( KeGetCurrentIrql() <= APC_LEVEL );

	ExAcquireFastMutex( &DevExt->LfsDeviceExt.FastMutex );
	fastMutexAcquired = TRUE;

	try {

		if (!FlagOn(DevExt->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTED)) {

			result = FALSE;
			leave;
		}

		ASSERT( DevExt->LfsDeviceExt.AttachedToDeviceObject == DevExt->NLExtHeader.AttachedToDeviceObject );

		if (DevExt->LfsDeviceExt.AttachedToDeviceObject == NULL) {

			NDAS_ASSERT( FALSE );

			result = FALSE;
			leave;
		}

		if (!(FlagOn(DevExt->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_MOUNTED) && !FlagOn(DevExt->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTED))) {

			ASSERT( DevExt->LfsDeviceExt.Readonly == NULL || ReadonlyLookUpCcb(DevExt->LfsDeviceExt.Readonly, fileObject) == NULL );
			
			result = FALSE;
			leave;
		}

		switch (irpSp->MajorFunction) {

		case IRP_MJ_PNP:

			break;

		default: 

			ExReleaseFastMutex( &DevExt->LfsDeviceExt.FastMutex );
			fastMutexAcquired = FALSE;

			if (DevExt->LfsDeviceExt.Readonly) {

				status = ReadonlyRedirectIrp( DevExt, Irp, &result );
			
			} else {

				result = FALSE;
			}

			leave;
		}

		if (irpSp->MajorFunction == IRP_MJ_PNP) {

			PrintIrp( LFS_DEBUG_READONLY_NOISE, __FUNCTION__, &DevExt->LfsDeviceExt, Irp );

			if (irpSp->MinorFunction == IRP_MN_SURPRISE_REMOVAL) {

				if (DevExt->LfsDeviceExt.NetdiskPartition == NULL) {

					NDAS_ASSERT( FALSE );
				
				} else {

					SetFlag( DevExt->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_SURPRISE_REMOVED );

					ExReleaseFastMutex( &DevExt->LfsDeviceExt.FastMutex );
					fastMutexAcquired = FALSE;

					NetdiskManager_SurpriseRemoval( GlobalLfs.NetdiskManager,
													DevExt->LfsDeviceExt.NetdiskPartition,
													DevExt->LfsDeviceExt.NetdiskEnabledMode );
				}

				DevExt->LfsDeviceExt.NetdiskPartition = NULL;			

				result = FALSE;
				leave;

			}

			// Need to test much whether this is okay..
	
			if (irpSp->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || irpSp->MinorFunction == IRP_MN_REMOVE_DEVICE) {

				result = FALSE;
				leave;
			
			} else if (irpSp->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE) {

				KEVENT				waitEvent;

				ExReleaseFastMutex( &DevExt->LfsDeviceExt.FastMutex );
				fastMutexAcquired = FALSE;

				if (DevExt->LfsDeviceExt.Readonly) {

					ReadonlyTryCloseCcb( DevExt->LfsDeviceExt.Readonly );

					if (!IsListEmpty(&DevExt->LfsDeviceExt.Readonly->FcbQueue)) {

						LARGE_INTEGER interval;
				
						// Wait all files closed
						interval.QuadPart = (1 * DELAY_ONE_SECOND);      //delay 1 seconds
						KeDelayExecutionThread( KernelMode, FALSE, &interval );
					}
			
					if (!IsListEmpty(&DevExt->LfsDeviceExt.Readonly->FcbQueue)) {

						status = Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
						Irp->IoStatus.Information = 0;
						IoCompleteRequest( Irp, IO_DISK_INCREMENT );
				
						result = TRUE;
						leave;
					} 
				}

				SetFlag( DevExt->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTING );

				IoCopyCurrentIrpStackLocationToNext( Irp );
				KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );

				IoSetCompletionRoutine( Irp,
										ReadonlyPassThroughCompletion,
										&waitEvent,
										TRUE,
										TRUE,
										TRUE );

				status = IoCallDriver( DevExt->LfsDeviceExt.AttachedToDeviceObject, Irp );

				if (status == STATUS_PENDING) {

					status = KeWaitForSingleObject( &waitEvent, Executive, KernelMode, FALSE, NULL );
					ASSERT( status == STATUS_SUCCESS );
				}

				ASSERT( KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Irp->IoStatus.Status) );
	
				SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, 
							   ("%s: lfsDeviceExt = %p, IRP_MN_QUERY_REMOVE_DEVICE Irp->IoStatus.Status = %x\n",
								__FUNCTION__, &DevExt->LfsDeviceExt, Irp->IoStatus.Status) );

				ClearFlag( DevExt->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTING );

				if (NT_SUCCESS(Irp->IoStatus.Status)) {

					ASSERT( !FlagOn(DevExt->LfsDeviceExt.Flags, LFS_DEVICE_FLAG_DISMOUNTED) );
					LfsDismountVolume( &DevExt->LfsDeviceExt );
				}

				status = Irp->IoStatus.Status;
				IoCompleteRequest( Irp, IO_NO_INCREMENT );

				result = TRUE;
				leave;
			}

			result = FALSE;
			leave;
		}

	} finally {

		if (fastMutexAcquired)
			ExReleaseFastMutex( &DevExt->LfsDeviceExt.FastMutex );

		LfsDeviceExt_Dereference( &DevExt->LfsDeviceExt );
		*NtStatus = status;
	}

	return result;
}
Пример #12
0
NTSTATUS
Bus_FDO_PnP (
    __in PDEVICE_OBJECT       DeviceObject,
    __in PIRP                 Irp,
    __in PIO_STACK_LOCATION   IrpStack,
    __in PFDO_DEVICE_DATA     DeviceData
    )
/*++
Routine Description:

    Handle requests from the Plug & Play system for the BUS itself

--*/
{
    NTSTATUS            status;
    ULONG               length, prevcount, numPdosPresent;
    PLIST_ENTRY         entry, listHead, nextEntry;
    PPDO_DEVICE_DATA    pdoData;
    PDEVICE_RELATIONS   relations, oldRelations;

    PAGED_CODE ();

    Bus_IncIoCount (DeviceData);

    switch (IrpStack->MinorFunction) {

    case IRP_MN_START_DEVICE:

        //
        // Send the Irp down and wait for it to come back.
        // Do not touch the hardware until then.
        //
        status = Bus_SendIrpSynchronously (DeviceData->NextLowerDriver, Irp);

        if (NT_SUCCESS(status)) {

            //
            // Initialize your device with the resources provided
            // by the PnP manager to your device.
            //
            status = Bus_StartFdo (DeviceData, Irp);
        }

        //
        // We must now complete the IRP, since we stopped it in the
        // completion routine with MORE_PROCESSING_REQUIRED.
        //

        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        Bus_DecIoCount (DeviceData);

        return status;

    case IRP_MN_QUERY_STOP_DEVICE:

        //
        // The PnP manager is trying to stop the device
        // for resource rebalancing. Fail this now if you
        // cannot stop the device in response to STOP_DEVICE.
        //
        SET_NEW_PNP_STATE(DeviceData, StopPending);
        Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP.
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:

        //
        // The PnP Manager sends this IRP, at some point after an
        // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a
        // device that the device will not be stopped for
        // resource reconfiguration.
        //
        //
        // First check to see whether you have received cancel-stop
        // without first receiving a query-stop. This could happen if
        //  someone above us fails a query-stop and passes down the subsequent
        // cancel-stop.
        //

        if (StopPending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-stop, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
            ASSERT(DeviceData->DevicePnPState == Started);
        }
        Irp->IoStatus.Status = STATUS_SUCCESS; // We must not fail the IRP.
        break;

    case IRP_MN_STOP_DEVICE:

        //
        // Stop device means that the resources given during Start device
        // are now revoked. Note: You must not fail this Irp.
        // But before you relieve resources make sure there are no I/O in
        // progress. Wait for the existing ones to be finished.
        // To do that, first we will decrement this very operation.
        // When the counter goes to 1, Stop event is set.
        //

        Bus_DecIoCount(DeviceData);

        KeWaitForSingleObject(
                   &DeviceData->StopEvent,
                   Executive, // Waiting reason of a driver
                   KernelMode, // Waiting in kernel mode
                   FALSE, // No allert
                   NULL); // No timeout

        //
        // Increment the counter back because this IRP has to
        // be sent down to the lower stack.
        //

        Bus_IncIoCount (DeviceData);

        //
        // Free resources given by start device.
        //

        SET_NEW_PNP_STATE(DeviceData, Stopped);

        //
        // We don't need a completion routine so fire and forget.
        //
        // Set the current stack location to the next stack location and
        // call the next device object.
        //

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        //
        // If we were to fail this call then we would need to complete the
        // IRP here.  Since we are not, set the status to SUCCESS and
        // call the next driver.
        //

        SET_NEW_PNP_STATE(DeviceData, RemovePending);

        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        //
        // If we were to fail this call then we would need to complete the
        // IRP here.  Since we are not, set the status to SUCCESS and
        // call the next driver.
        //

        //
        // First check to see whether you have received cancel-remove
        // without first receiving a query-remove. This could happen if
        // someone above us fails a query-remove and passes down the
        // subsequent cancel-remove.
        //

        if (RemovePending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-remove, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        Irp->IoStatus.Status = STATUS_SUCCESS;// You must not fail the IRP.
        break;

    case IRP_MN_SURPRISE_REMOVAL:

        //
        // The device has been unexpectedly removed from the machine
        // and is no longer available for I/O. Bus_RemoveFdo clears
        // all the resources, frees the interface and de-registers
        // with WMI, but it doesn't delete the FDO. That's done
        // later in Remove device query.
        //

        SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
        Bus_RemoveFdo(DeviceData);

        ExAcquireFastMutex (&DeviceData->Mutex);

        listHead = &DeviceData->ListOfPDOs;

        for(entry = listHead->Flink,nextEntry = entry->Flink;
            entry != listHead;
            entry = nextEntry,nextEntry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            RemoveEntryList (&pdoData->Link);
            InitializeListHead (&pdoData->Link);
            pdoData->ParentFdo  = NULL;
            pdoData->ReportedMissing = TRUE;
        }

        ExReleaseFastMutex (&DeviceData->Mutex);

        Irp->IoStatus.Status = STATUS_SUCCESS; // You must not fail the IRP.
        break;

    case IRP_MN_REMOVE_DEVICE:

        //
        // The Plug & Play system has dictated the removal of this device.
        // We have no choice but to detach and delete the device object.
        //

        //
        // Check the state flag to see whether you are surprise removed
        //

        if (DeviceData->DevicePnPState != SurpriseRemovePending)
        {
            Bus_RemoveFdo(DeviceData);
        }

        SET_NEW_PNP_STATE(DeviceData, Deleted);

        //
        // Wait for all outstanding requests to complete.
        // We need two decrements here, one for the increment in
        // the beginning of this function, the other for the 1-biased value of
        // OutstandingIO.
        //

        Bus_DecIoCount (DeviceData);

        //
        // The requestCount is at least one here (is 1-biased)
        //

        Bus_DecIoCount (DeviceData);

        KeWaitForSingleObject (
                &DeviceData->RemoveEvent,
                Executive,
                KernelMode,
                FALSE,
                NULL);

        //
        // Typically the system removes all the  children before
        // removing the parent FDO. If for any reason child Pdos are
        // still present we will destroy them explicitly, with one exception -
        // we will not delete the PDOs that are in SurpriseRemovePending state.
        //

        ExAcquireFastMutex (&DeviceData->Mutex);

        listHead = &DeviceData->ListOfPDOs;

        for(entry = listHead->Flink,nextEntry = entry->Flink;
            entry != listHead;
            entry = nextEntry,nextEntry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            RemoveEntryList (&pdoData->Link);
            if (SurpriseRemovePending == pdoData->DevicePnPState)
            {
                //
                // We will reinitialize the list head so that we
                // wouldn't barf when we try to delink this PDO from
                // the parent's PDOs list, when the system finally
                // removes the PDO. Let's also not forget to set the
                // ReportedMissing flag to cause the deletion of the PDO.
                //
                Bus_KdPrint_Cont(DeviceData, BUS_DBG_PNP_INFO,
                ("\tFound a surprise removed device: 0x%p\n", pdoData->Self));
                InitializeListHead (&pdoData->Link);
                pdoData->ParentFdo  = NULL;
                pdoData->ReportedMissing = TRUE;
                continue;
            }
            DeviceData->NumPDOs--;
            Bus_DestroyPdo (pdoData->Self, pdoData);
        }

        ExReleaseFastMutex (&DeviceData->Mutex);

        //
        // We need to send the remove down the stack before we detach,
        // but we don't need to wait for the completion of this operation
        // (and to register a completion routine).
        //

        Irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation (Irp);
        status = IoCallDriver (DeviceData->NextLowerDriver, Irp);
        //
        // Detach from the underlying devices.
        //

        IoDetachDevice (DeviceData->NextLowerDriver);

        Bus_KdPrint_Cont(DeviceData, BUS_DBG_PNP_INFO,
                        ("\tDeleting FDO: 0x%p\n", DeviceObject));

        IoDeleteDevice (DeviceObject);

        return status;

    case IRP_MN_QUERY_DEVICE_RELATIONS:

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                   ("\tQueryDeviceRelation Type: %s\n",
                    DbgDeviceRelationString(\
                    IrpStack->Parameters.QueryDeviceRelations.Type)));

        if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) {
            //
            // We don't support any other Device Relations
            //
            break;
        }

        //
        // Tell the plug and play system about all the PDOs.
        //
        // There might also be device relations below and above this FDO,
        // so, be sure to propagate the relations from the upper drivers.
        //
        // No Completion routine is needed so long as the status is preset
        // to success.  (PDOs complete plug and play irps with the current
        // IoStatus.Status and IoStatus.Information as the default.)
        //

        ExAcquireFastMutex (&DeviceData->Mutex);

        oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
        if (oldRelations) {
            prevcount = oldRelations->Count;
            if (!DeviceData->NumPDOs) {
                //
                // There is a device relations struct already present and we have
                // nothing to add to it, so just call IoSkip and IoCall
                //
                ExReleaseFastMutex (&DeviceData->Mutex);
                break;
            }
        }
        else  {
            prevcount = 0;
        }

        //
        // Calculate the number of PDOs actually present on the bus
        //
        numPdosPresent = 0;
        for (entry = DeviceData->ListOfPDOs.Flink;
             entry != &DeviceData->ListOfPDOs;
             entry = entry->Flink) {
            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            if (pdoData->Present)
                numPdosPresent++;
        }

        //
        // Need to allocate a new relations structure and add our
        // PDOs to it.
        //

        length = sizeof(DEVICE_RELATIONS) +
                ((numPdosPresent + prevcount) * sizeof (PDEVICE_OBJECT)) -1;

        relations = (PDEVICE_RELATIONS) ExAllocatePoolWithTag (PagedPool,
                                        length, BUSENUM_POOL_TAG);

        if (NULL == relations) {
            //
            // Fail the IRP
            //
            ExReleaseFastMutex (&DeviceData->Mutex);
            Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
            Bus_DecIoCount (DeviceData);
            return status;

        }

        //
        // Copy in the device objects so far
        //
        if (prevcount) {
            RtlCopyMemory (relations->Objects, oldRelations->Objects,
                                      prevcount * sizeof (PDEVICE_OBJECT));
        }

        relations->Count = prevcount + numPdosPresent;

        //
        // For each PDO present on this bus add a pointer to the device relations
        // buffer, being sure to take out a reference to that object.
        // The Plug & Play system will dereference the object when it is done
        // with it and free the device relations buffer.
        //

        for (entry = DeviceData->ListOfPDOs.Flink;
             entry != &DeviceData->ListOfPDOs;
             entry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            if (pdoData->Present) {
                relations->Objects[prevcount] = pdoData->Self;
                ObReferenceObject (pdoData->Self);
                prevcount++;
            } else {
                pdoData->ReportedMissing = TRUE;
            }
        }

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                           ("\t#PDOS present = %d\n\t#PDOs reported = %d\n",
                             DeviceData->NumPDOs, relations->Count));

        //
        // Replace the relations structure in the IRP with the new
        // one.
        //
        if (oldRelations) {
            ExFreePool (oldRelations);
        }
        Irp->IoStatus.Information = (ULONG_PTR) relations;

        ExReleaseFastMutex (&DeviceData->Mutex);

        //
        // Set up and pass the IRP further down the stack
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    default:

        //
        // In the default case we merely call the next driver.
        // We must not modify Irp->IoStatus.Status or complete the IRP.
        //

        break;
    }

    IoSkipCurrentIrpStackLocation (Irp);
    status = IoCallDriver (DeviceData->NextLowerDriver, Irp);
    Bus_DecIoCount (DeviceData);
    return status;
}
Пример #13
0
NTSTATUS
Bus_EjectDevice (
    PBUSENUM_EJECT_HARDWARE     Eject,
    PFDO_DEVICE_DATA            FdoData
    )
/*++
Routine Description:
    The user application has told us to eject the device from the bus.
    In a real situation the driver gets notified by an interrupt when the
    user presses the Eject button on the device.

Arguments:

    Eject   - pointer to Eject hardware structure.
    FdoData - contains the list to iterate over

Returns:

    STATUS_SUCCESS upon successful removal from the list
    STATUS_INVALID_PARAMETER if the removal was unsuccessful

--*/
{
    PLIST_ENTRY         entry;
    PPDO_DEVICE_DATA    pdoData;
    BOOLEAN             found = FALSE, ejectAll;

    PAGED_CODE ();

    ejectAll = (0 == Eject->SerialNo);

    ExAcquireFastMutex (&FdoData->Mutex);

    if (ejectAll) {
        Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE,
                      ("Ejecting all the pdos!\n"));
    } else {
        Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE,
                      ("Ejecting %d\n", Eject->SerialNo));
    }

    if (FdoData->NumPDOs == 0) {
        //
        // Somebody in user space isn't playing nice!!!
        //
        Bus_KdPrint (FdoData, BUS_DBG_IOCTL_ERROR,
                      ("No devices to eject!\n"));
        ExReleaseFastMutex (&FdoData->Mutex);
        return STATUS_NO_SUCH_DEVICE;
    }

    //
    // Scan the list to find matching PDOs
    //
    for (entry = FdoData->ListOfPDOs.Flink;
         entry != &FdoData->ListOfPDOs;
         entry = entry->Flink) {

        pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);

        Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE,
                      ("found device %d\n", pdoData->SerialNo));

        if (ejectAll || Eject->SerialNo == pdoData->SerialNo) {
            Bus_KdPrint (FdoData, BUS_DBG_IOCTL_INFO,
                          ("Ejected %d\n", pdoData->SerialNo));
            found = TRUE;
            IoRequestDeviceEject(pdoData->Self);
            if (!ejectAll) {
                break;
            }
        }
    }
    ExReleaseFastMutex (&FdoData->Mutex);

    if (found) {
        return STATUS_SUCCESS;
    }

    Bus_KdPrint (FdoData, BUS_DBG_IOCTL_ERROR,
                  ("Device %d is not present\n", Eject->SerialNo));

    return STATUS_INVALID_PARAMETER;
}
Пример #14
0
NTSTATUS
bus_unplug_dev (
    int addr,
    PFDO_DEVICE_DATA            fdodata
    )
{
    PLIST_ENTRY         entry;
    PPDO_DEVICE_DATA    pdodata;
    int found=0, all;

    PAGED_CODE ();

    if(addr<0||addr>127)
	return STATUS_INVALID_PARAMETER;

    all = (0 == addr);

    ExAcquireFastMutex (&fdodata->Mutex);

    if (all) {
        Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE,
                      ("Plugging out all the devices!\n"));
    } else {
        Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE,
                      ("Plugging out %d\n", addr));
    }

    if (fdodata->NumPDOs == 0) {
        //
        // We got a 2nd plugout...somebody in user space isn't playing nice!!!
        //
        Bus_KdPrint (fdodata, BUS_DBG_IOCTL_ERROR,
                      ("BAD BAD BAD...2 removes!!! Send only one!\n"));
        ExReleaseFastMutex (&fdodata->Mutex);
        return STATUS_NO_SUCH_DEVICE;
    }

    for (entry = fdodata->ListOfPDOs.Flink;
         entry != &fdodata->ListOfPDOs;
         entry = entry->Flink) {

        pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);

        Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE,
                      ("found device %d\n", pdodata->SerialNo));

        if (all || addr == pdodata->SerialNo) {
            Bus_KdPrint (fdodata, BUS_DBG_IOCTL_INFO,
                          ("Plugging out %d\n", pdodata->SerialNo));
            pdodata->Present = FALSE;
			complete_pending_read_irp(pdodata);
            found = 1;
            if (!all) {
                break;
            }
        }
    }

    ExReleaseFastMutex (&fdodata->Mutex);

    if (found) {
        IoInvalidateDeviceRelations (fdodata->UnderlyingPDO, BusRelations);

		ExAcquireFastMutex (&fdodata->Mutex);

		for (entry = fdodata->ListOfPDOs.Flink;
			 entry != &fdodata->ListOfPDOs;
			 entry = entry->Flink) {

			pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);

			if( pdodata->Present ==FALSE){
				complete_pending_irp(pdodata);
				SET_NEW_PNP_STATE(pdodata,PNP_DEVICE_REMOVED);
				IoInvalidateDeviceState(pdodata->Self);
			}
		}
		ExReleaseFastMutex (&fdodata->Mutex);

		Bus_KdPrint (fdodata, BUS_DBG_IOCTL_ERROR,
                  ("Device %d plug out finished\n", addr));
		return  STATUS_SUCCESS;
    }


    return STATUS_INVALID_PARAMETER;
}
Пример #15
0
VOID
ExFreeToPagedLookasideList(
    IN PPAGED_LOOKASIDE_LIST Lookaside,
    IN PVOID Entry
)

/*++

Routine Description:

    This function inserts (pushes) the specified entry into the specified
    paged lookaside list.

Arguments:

    Lookaside - Supplies a pointer to a paged lookaside list structure.

    Entry - Supples a pointer to the entry that is inserted in the
        lookaside list.

Return Value:

    None.

--*/

{

    Lookaside->L.TotalFrees += 1;

#if !defined(_PPC_)

    if (Isx86FeaturePresent(KF_CMPXCHG8B)) {
        if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
            Lookaside->L.FreeMisses += 1;
            (Lookaside->L.Free)(Entry);

        } else {
            ExInterlockedPushEntrySList(&Lookaside->L.ListHead,
                                        (PSINGLE_LIST_ENTRY)Entry,
                                        NULL);
        }

        return;
    }

#endif

    ExAcquireFastMutex(&Lookaside->Lock);
    if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
        ExReleaseFastMutex(&Lookaside->Lock);
        Lookaside->L.FreeMisses += 1;
        (Lookaside->L.Free)(Entry);

    } else {
        PushEntryList(&Lookaside->L.ListHead.Next, (PSINGLE_LIST_ENTRY)Entry);
        Lookaside->L.ListHead.Depth += 1;
        ExReleaseFastMutex(&Lookaside->Lock);
    }

    return;
}
Пример #16
0
PREADONLY
Readonly_Create (
	IN	PLFS_DEVICE_EXTENSION	LfsDeviceExt
	)
{
	NTSTATUS				status;
	PREADONLY				readonly;

	OBJECT_ATTRIBUTES		objectAttributes;
	LARGE_INTEGER			timeOut;
	

	readonly = ExAllocatePoolWithTag( NonPagedPool, sizeof(READONLY), LFS_ALLOC_TAG );
	
	if (readonly == NULL) {

		NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES );
		return NULL;
	}
	
	RtlZeroMemory( readonly, sizeof(READONLY) );

	readonly->Flags = READONLY_FLAG_INITIALIZING;

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

	ExInitializeFastMutex( &readonly->FastMutex );

	readonly->ReferenceCount = 1;

	LfsDeviceExt_Reference( LfsDeviceExt );
	readonly->LfsDeviceExt = LfsDeviceExt;

	readonly->ThreadHandle = NULL;

	InitializeListHead( &readonly->FcbQueue );
	KeInitializeSpinLock( &readonly->FcbQSpinLock );

	InitializeListHead( &readonly->CcbQueue );
    ExInitializeFastMutex( &readonly->CcbQMutex );

#if 0
	InitializeListHead( &readonly->RecoveryCcbQueue );
    ExInitializeFastMutex( &readonly->RecoveryCcbQMutex );

	InitializeListHead( &readonly->DeletedFcbQueue );
#endif

	KeQuerySystemTime( &readonly->TryCloseTime );

#if 0
	readonly->TryCloseWorkItem = IoAllocateWorkItem( (PDEVICE_OBJECT)VolDo );
#endif

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

#if 0
	////////////////////////////////////////
	InitializeListHead( &readonly->FcbQueue );
	ExInitializeFastMutex( &readonly->FcbQMutex );
	/////////////////////////////////////////
#endif

	KeInitializeEvent( &readonly->DiskmountReadyEvent, NotificationEvent, FALSE );

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

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

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

	if (!NT_SUCCESS(status)) {

		ASSERT( LFS_UNEXPECTED );
		Readonly_Close( readonly );
		
		return NULL;
	}

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

	if (!NT_SUCCESS(status)) {

		NDAS_ASSERT( NDAS_ASSERT_INSUFFICIENT_RESOURCES );
		Readonly_Close( readonly );
		
		return NULL;
	}

	readonly->SessionId ++;

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

	if (status != STATUS_SUCCESS) {
	
		NDAS_ASSERT( FALSE );
		Readonly_Close( readonly );
		
		return NULL;
	}

	KeClearEvent( &readonly->ReadyEvent );

	ExAcquireFastMutex( &readonly->FastMutex );

	if (!FlagOn(readonly->Thread.Flags, READONLY_THREAD_FLAG_START) ||
		FlagOn(readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED)) {

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

			Readonly_Close( readonly );
			return NULL;
		}
	} 

	ExReleaseFastMutex( &readonly->FastMutex );

	ClearFlag( readonly->Flags, READONLY_FLAG_INITIALIZING );
	SetFlag( readonly->Flags, READONLY_FLAG_START );

	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE,
				("Readonly_Create: The client thread are ready readonly = %p\n", readonly) );

	return readonly;
}
Пример #17
0
NTSTATUS
NdFatSecondaryCommonRead (
	IN PIRP_CONTEXT IrpContext,
	IN PIRP			Irp,
	IN ULONG		BytesToRead
	)
{
	NTSTATUS					status;

	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;
	
	PIO_STACK_LOCATION			irpSp = IoGetCurrentIrpStackLocation( Irp );
	PFILE_OBJECT				fileObject = irpSp->FileObject;

	struct Read					read;
	
	PSECONDARY_REQUEST			secondaryRequest = NULL;
	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

	LARGE_INTEGER				timeOut;

	TYPE_OF_OPEN				typeOfOpen;
	PVCB						vcb;
	PFCB						fcb;
	PCCB						ccb;
	BOOLEAN						fcbAcquired = FALSE;

	PUCHAR						outputBuffer;
	ULONG						totalReadLength;

	_U64						primaryFileHandle = 0;


	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );

	typeOfOpen = FatDecodeFileObject( fileObject, &vcb, &fcb, &ccb );

	ASSERT( typeOfOpen == UserFileOpen );

	if (FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

		/*if (FlagOn( fcb->FcbState, FCB_STATE_FILE_DELETED )) {
	
			ASSERT( FALSE );
			FatRaiseStatus( IrpContext, STATUS_FILE_DELETED, NULL, NULL );
					
		} else */{
					
			ASSERT( FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) );
			
			return STATUS_FILE_CORRUPT_ERROR;
		}
	}

    if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

		ASSERT( FALSE );
        DebugTrace2( 0, Dbg, ("Can't wait in create\n") );

        status = FatFsdPostRequest( IrpContext, Irp );

        DebugTrace2( -1, Dbg2, ("NdFatSecondaryCommonRead:  FatFsdPostRequest -> %08lx\n", status) );
        return status;
    }

	if (irpSp->Parameters.Read.ByteOffset.QuadPart == FILE_WRITE_TO_END_OF_FILE && 
		irpSp->Parameters.Read.ByteOffset.HighPart == -1) {

		read.ByteOffset = fcb->Header.FileSize;

	} else {

		read.ByteOffset = irpSp->Parameters.Read.ByteOffset;
	}

	read.Key	= 0;
	read.Length	= irpSp->Parameters.Read.Length;
	read.Length = BytesToRead;


	ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); 

	//FatAcquireSharedFcb( IrpContext, fcb );
	//fcbAcquired = TRUE;


	try {

		secondarySessionResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( IrpContext, 
													 &volDo->Secondary->SessionResource, 
													 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

		if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

			PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );	
		}

		outputBuffer = FatMapUserBuffer( IrpContext, Irp );
		totalReadLength = 0;

		do {

			ULONG						outputBufferLength;

			if (fcb->UncleanCount == 0) {

				DebugTrace( 0, Dbg2, "NdFatSecondaryCommonRead: fileName = %wZ\n", &fileObject->FileName );

				status = STATUS_FILE_CLOSED;
				break;
			}

			if (!FlagOn(ccb->NdFatFlags, ND_FAT_CLEANUP_COMPLETE)) {

				primaryFileHandle = ccb->PrimaryFileHandle;

			} else {

				PLIST_ENTRY	ccbListEntry;

				ExAcquireFastMutex( &fcb->CcbQMutex );
				
				for (primaryFileHandle = 0, ccbListEntry = fcb->CcbQueue.Flink; 
					 ccbListEntry != &fcb->CcbQueue; 
					 ccbListEntry = ccbListEntry->Flink) {

					if (!FlagOn(CONTAINING_RECORD(ccbListEntry, CCB, FcbListEntry)->NdFatFlags, ND_FAT_CLEANUP_COMPLETE)) {
						
						primaryFileHandle = CONTAINING_RECORD(ccbListEntry, CCB, FcbListEntry)->PrimaryFileHandle;
						break;
					}
				}

				ExReleaseFastMutex( &fcb->CcbQMutex );
			}

			ASSERT( primaryFileHandle );

			outputBufferLength = ((read.Length-totalReadLength) <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize) 
									? (read.Length-totalReadLength) : volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize;

			secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, 
															  IRP_MJ_READ,
															  volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize );

			if (secondaryRequest == NULL) {

				FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
			}

			ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
			INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_READ, 0 );

			ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
			ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

			//ndfsWinxpRequestHeader->IrpTag   = (_U32)Irp;
			ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_READ;
			ndfsWinxpRequestHeader->IrpMinorFunction = 0;

			ndfsWinxpRequestHeader->FileHandle = ccb->PrimaryFileHandle;

			ndfsWinxpRequestHeader->IrpFlags   = 0;
			ndfsWinxpRequestHeader->IrpSpFlags = 0;

			ndfsWinxpRequestHeader->Read.Length		= outputBufferLength;
			ndfsWinxpRequestHeader->Read.Key		= read.Key;
			ndfsWinxpRequestHeader->Read.ByteOffset = read.ByteOffset.QuadPart + totalReadLength;

			secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
			QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

			timeOut.QuadPart = -NDASFAT_TIME_OUT;
			status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
		
			if (status != STATUS_SUCCESS) {

				secondaryRequest = NULL;
				status = STATUS_IO_DEVICE_ERROR;
				leave;
			}

			KeClearEvent( &secondaryRequest->CompleteEvent );

			if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

				if (IrpContext->OriginatingIrp)
					PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );
			
				DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

				FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
			}

			ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;

			if (ndfsWinxpReplytHeader->Status == STATUS_END_OF_FILE) {
	
				ASSERT( ndfsWinxpReplytHeader->Information == 0 );

				if (!(read.ByteOffset.QuadPart & (((ULONG)vcb->Bpb.BytesPerSector) - 1))) {

		
					RtlZeroMemory( outputBuffer + totalReadLength,
								   read.Length - totalReadLength );

					totalReadLength = read.Length;
				
				} else {

					ASSERT( FALSE );
				}

				DereferenceSecondaryRequest( secondaryRequest );
				secondaryRequest = NULL;				
				
				break;
			}

			if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {

				ASSERT( totalReadLength == 0 );
				ASSERT( ndfsWinxpReplytHeader->Status == STATUS_FILE_CLOSED );
							
				DebugTrace2( 0, Dbg, ("ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );

				if (totalReadLength)
					status = STATUS_SUCCESS;
				else
					status = ndfsWinxpReplytHeader->Status;

				ASSERT( ndfsWinxpReplytHeader->Information == 0 );
				DereferenceSecondaryRequest( secondaryRequest );
				secondaryRequest = NULL;				
				
				break;
			}

			ASSERT( ndfsWinxpReplytHeader->Information <= outputBufferLength );
			ASSERT( outputBufferLength == 0 || outputBuffer );

			//if (fcb->Header.FileSize.LowPart < 100)
			//	DbgPrint( "data = %s\n", (_U8 *)(ndfsWinxpReplytHeader+1) );

			if (ndfsWinxpReplytHeader->Information && outputBuffer) {

				try {

					RtlCopyMemory( outputBuffer + totalReadLength,
								   (_U8 *)(ndfsWinxpReplytHeader+1),
								   ndfsWinxpReplytHeader->Information );

				} finally {

					if (AbnormalTermination()) {

						DebugTrace2( 0, Dbg2, ("RedirectIrpMajorRead: Exception - output buffer is not valid\n") );
						totalReadLength = read.Length; // Pretend that we read all the data.Buffer owner is already dead anyway..
						status = STATUS_SUCCESS;
					
					} else {
					
						if (ndfsWinxpReplytHeader->Status == STATUS_SUCCESS)
							totalReadLength += ndfsWinxpReplytHeader->Information;

						if (totalReadLength)
							status = STATUS_SUCCESS;
						else
							status = ndfsWinxpReplytHeader->Status;
					}
				}
			}

			//if (fcb->Header.FileSize.LowPart < 100)
			//	DbgPrint( "data = %s\n", outputBuffer );
		
			DereferenceSecondaryRequest( secondaryRequest );
			secondaryRequest = NULL;

		} while( totalReadLength < read.Length );


		if (status == STATUS_FILE_CLOSED) {

			_U64	fcbHandle;
			ULONG	dataSize;
			_U8		*ndfsWinxpRequestData;


			ASSERT( ccb );
			ASSERT( totalReadLength == 0 );
			ASSERT( secondaryRequest == NULL );

			if (ccb->CreateContext.RelatedFileHandle != 0) {

				ASSERT( FALSE );
				try_return( status = STATUS_FILE_CLOSED );
			}
				
			DebugTrace2( 0, Dbg, ("SecondaryRecoverySessionStart: ccb->Lcb->ExactCaseLink.LinkName = %wZ \n", &ccb->Fcb->FullFileName) );

			dataSize = ccb->CreateContext.EaLength + ccb->CreateContext.FileNameLength;

			secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary,
															  IRP_MJ_CREATE,
															  (dataSize >= DEFAULT_NDAS_MAX_DATA_SIZE) ? dataSize : DEFAULT_NDAS_MAX_DATA_SIZE );

			if (secondaryRequest == NULL) {

				ASSERT( FALSE );
				try_return( status = STATUS_FILE_CLOSED );
			}

			ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;

			INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader,
											NDFS_COMMAND_EXECUTE,
											volDo->Secondary,
											IRP_MJ_CREATE,
											(ccb->BufferLength + ccb->Fcb->FullFileName.Length) );

			ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
			ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

			ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_CREATE;
			ndfsWinxpRequestHeader->IrpMinorFunction = 0;

			ndfsWinxpRequestHeader->FileHandle = 0;

			ndfsWinxpRequestHeader->IrpFlags   = 0;
			ndfsWinxpRequestHeader->IrpSpFlags = 0; //irpSp->Flags;

			ndfsWinxpRequestHeader->Create.AllocationSize = 0;
			ndfsWinxpRequestHeader->Create.EaLength = 0;
			ndfsWinxpRequestHeader->Create.FileAttributes = 0;

			ndfsWinxpRequestHeader->Create.Options = 0; //irpSp->Parameters.Create.Options & ~FILE_DELETE_ON_CLOSE;
			ndfsWinxpRequestHeader->Create.Options &= 0x00FFFFFF;
			ndfsWinxpRequestHeader->Create.Options |= (FILE_OPEN << 24);

			ndfsWinxpRequestHeader->Create.FileNameLength 
				= (USHORT)(ccb->Fcb->FullFileName.Length + (ccb->BufferLength - ccb->CreateContext.EaLength));

			ndfsWinxpRequestHeader->Create.FileNameLength = ccb->CreateContext.FileNameLength;
			ndfsWinxpRequestHeader->Create.EaLength = 0; //ccb->CreateContext.EaLength;

			ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1);

			RtlCopyMemory( ndfsWinxpRequestData + ndfsWinxpRequestHeader->Create.EaLength,
						   ccb->Fcb->FullFileName.Buffer,
						   ccb->Fcb->FullFileName.Length );

			RtlCopyMemory( ndfsWinxpRequestData + ndfsWinxpRequestHeader->Create.EaLength + ccb->Fcb->FullFileName.Length,
						   ccb->Buffer + ccb->CreateContext.EaLength,
						   ccb->BufferLength - ccb->CreateContext.EaLength );

			secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
			QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );
				
			timeOut.QuadPart = -NDASFAT_TIME_OUT;
			status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );

			KeClearEvent(&secondaryRequest->CompleteEvent);

			if (status != STATUS_SUCCESS) {
		
				ASSERT( NDASFAT_BUG );

				secondaryRequest = NULL;
				ASSERT( FALSE );
				try_return( status );
			}

			if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

				status = secondaryRequest->ExecuteStatus;
				DereferenceSecondaryRequest( secondaryRequest );
				secondaryRequest = NULL;
				ASSERT( FALSE );

				FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
			}
				
			ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
		
			DebugTrace2( 0, Dbg, ("SecondaryRecoverySessionStart: ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );

			if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {

				ASSERT( FALSE );
				status = secondaryRequest->ExecuteStatus;
				DereferenceSecondaryRequest( secondaryRequest );
				secondaryRequest = NULL;
				try_return( status = STATUS_FILE_CLOSED );
			}

			primaryFileHandle = ndfsWinxpReplytHeader->Open.FileHandle;
			ASSERT( fcb->Handle == ndfsWinxpReplytHeader->Open.FcbHandle );

			DereferenceSecondaryRequest( secondaryRequest );
			secondaryRequest = NULL;

			do {

				ULONG						outputBufferLength;


				outputBufferLength = ((read.Length-totalReadLength) <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize) 
									? (read.Length-totalReadLength) : volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize;

				secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, 
																  IRP_MJ_READ,
																  volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize );

				if (secondaryRequest == NULL) {

					FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
				}

				ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
				INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_READ, 0 );

				ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
				ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

				//ndfsWinxpRequestHeader->IrpTag   = (_U32)Irp;
				ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_READ;
				ndfsWinxpRequestHeader->IrpMinorFunction = 0;

				ndfsWinxpRequestHeader->FileHandle = primaryFileHandle;

				ndfsWinxpRequestHeader->IrpFlags   = 0;
				ndfsWinxpRequestHeader->IrpSpFlags = 0;

				ndfsWinxpRequestHeader->Read.Length		= outputBufferLength;
				ndfsWinxpRequestHeader->Read.Key		= read.Key;
				ndfsWinxpRequestHeader->Read.ByteOffset = read.ByteOffset.QuadPart + totalReadLength;

				secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
				QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

				timeOut.QuadPart = -NDASFAT_TIME_OUT;
				status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
		
				if (status != STATUS_SUCCESS) {

					secondaryRequest = NULL;
					status = STATUS_IO_DEVICE_ERROR;
					leave;
				}

				KeClearEvent( &secondaryRequest->CompleteEvent );

				if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

					if (IrpContext->OriginatingIrp)
						PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );
			
					DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
				}

				ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;

				if (ndfsWinxpReplytHeader->Status == STATUS_END_OF_FILE) {
	
					ASSERT( ndfsWinxpReplytHeader->Information == 0 );

					if (!(read.ByteOffset.QuadPart & (((ULONG)vcb->Bpb.BytesPerSector) - 1))) {

		
						RtlZeroMemory( outputBuffer + totalReadLength,
									   read.Length - totalReadLength );

						totalReadLength = read.Length;
				
					} else {

						ASSERT( FALSE );
					}

					DereferenceSecondaryRequest( secondaryRequest );
					secondaryRequest = NULL;				
				
					break;
				}

				if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {

					ASSERT( FALSE );
			
					DebugTrace2( 0, Dbg2, ("ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );

					if (totalReadLength)
						status = STATUS_SUCCESS;
					else
						status = ndfsWinxpReplytHeader->Status;

					ASSERT( ndfsWinxpReplytHeader->Information == 0 );
					DereferenceSecondaryRequest( secondaryRequest );
					secondaryRequest = NULL;				
				
					break;
				}

				ASSERT( ndfsWinxpReplytHeader->Information <= outputBufferLength );
				ASSERT( outputBufferLength == 0 || outputBuffer );

				if (ndfsWinxpReplytHeader->Information && outputBuffer) {

					try {

						RtlCopyMemory( outputBuffer + totalReadLength,
									   (_U8 *)(ndfsWinxpReplytHeader+1),
									   ndfsWinxpReplytHeader->Information );

					} finally {

						if (AbnormalTermination()) {

							DebugTrace2( 0, Dbg2, ("RedirectIrpMajorRead: Exception - output buffer is not valid\n") );
							totalReadLength = read.Length; // Pretend that we read all the data.Buffer owner is already dead anyway..
							status = STATUS_SUCCESS;
					
						} else {
					
							if (ndfsWinxpReplytHeader->Status == STATUS_SUCCESS)
								totalReadLength += ndfsWinxpReplytHeader->Information;

							if (totalReadLength)
								status = STATUS_SUCCESS;
							else
								status = ndfsWinxpReplytHeader->Status;
						}
					}
				}
		
				DereferenceSecondaryRequest( secondaryRequest );
				secondaryRequest = NULL;

			} while( totalReadLength < read.Length );
			
			ASSERT( totalReadLength == read.Length );

			ClosePrimaryFile( volDo->Secondary, primaryFileHandle );
		}

try_exit:

		NOTHING;

	} finally {
Пример #18
0
PPHYSICAL_MEMORY_RANGE
MmGetPhysicalMemoryRanges (
    VOID
    )

/*++

Routine Description:

    This routine returns the virtual address of a nonpaged pool block which
    contains the physical memory ranges in the system.

    The returned block contains physical address and page count pairs.
    The last entry contains zero for both.

    The caller must understand that this block can change at any point before
    or after this snapshot.

    It is the caller's responsibility to free this block.

Arguments:

    None.

Return Value:

    NULL on failure.

Environment:

    Kernel mode.  PASSIVE level.  No locks held.

--*/

{
    ULONG i;
    KIRQL OldIrql;
    PPHYSICAL_MEMORY_RANGE p;
    PPHYSICAL_MEMORY_RANGE PhysicalMemoryBlock;

    ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);

    ExAcquireFastMutex (&MmDynamicMemoryMutex);

    i = sizeof(PHYSICAL_MEMORY_RANGE) * (MmPhysicalMemoryBlock->NumberOfRuns + 1);

    PhysicalMemoryBlock = ExAllocatePoolWithTag (NonPagedPool,
                                                 i,
                                                 'hPmM');

    if (PhysicalMemoryBlock == NULL) {
        ExReleaseFastMutex (&MmDynamicMemoryMutex);
        return NULL;
    }

    p = PhysicalMemoryBlock;

    LOCK_PFN (OldIrql);

    ASSERT (i == (sizeof(PHYSICAL_MEMORY_RANGE) * (MmPhysicalMemoryBlock->NumberOfRuns + 1)));

    for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i += 1) {
        p->BaseAddress.QuadPart = (LONGLONG)MmPhysicalMemoryBlock->Run[i].BasePage * PAGE_SIZE;
        p->NumberOfBytes.QuadPart = (LONGLONG)MmPhysicalMemoryBlock->Run[i].PageCount * PAGE_SIZE;
        p += 1;
    }

    p->BaseAddress.QuadPart = 0;
    p->NumberOfBytes.QuadPart = 0;

    UNLOCK_PFN (OldIrql);

    ExReleaseFastMutex (&MmDynamicMemoryMutex);

    return PhysicalMemoryBlock;
}
Пример #19
0
NTSTATUS
Bus_FDO_PnP (
    PDEVICE_OBJECT       DeviceObject,
    PIRP                 Irp,
    PIO_STACK_LOCATION   IrpStack,
    PFDO_DEVICE_DATA     DeviceData
    )
{
    NTSTATUS            status;
    ULONG               length, prevcount, numPdosPresent;
    PLIST_ENTRY         entry; 
    PPDO_DEVICE_DATA    pdoData;
    PDEVICE_RELATIONS   relations, oldRelations;

    PAGED_CODE ();

    switch (IrpStack->MinorFunction) {

    case IRP_MN_START_DEVICE:

        status = Bus_StartFdo (DeviceData, Irp);


        //
        // We must now complete the IRP, since we stopped it in the
        // completion routine with MORE_PROCESSING_REQUIRED.
        //

        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return status;

    case IRP_MN_QUERY_STOP_DEVICE:

        //
        // The PnP manager is trying to stop the device
        // for resource rebalancing. 
        //
        SET_NEW_PNP_STATE(DeviceData->Common, StopPending);
        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:

        //
        // The PnP Manager sends this IRP, at some point after an
        // IRP_MN_QUERY_STOP_DEVICE, to inform the drivers for a
        // device that the device will not be stopped for
        // resource reconfiguration.
        //
        //
        // First check to see whether you have received cancel-stop
        // without first receiving a query-stop. This could happen if
        //  someone above us fails a query-stop and passes down the subsequent
        // cancel-stop.
        //

        if (StopPending == DeviceData->Common.DevicePnPState)
        {
            //
            // We did receive a query-stop, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData->Common);
            ASSERT(DeviceData->Common.DevicePnPState == Started);
        }
        Irp->IoStatus.Status = STATUS_SUCCESS; // We must not fail the IRP.
        break;

    case IRP_MN_QUERY_DEVICE_RELATIONS:

        DPRINT("\tQueryDeviceRelation Type: %s\n",
                    DbgDeviceRelationString(\
                    IrpStack->Parameters.QueryDeviceRelations.Type));

        if (BusRelations != IrpStack->Parameters.QueryDeviceRelations.Type) {
            //
            // We don't support any other Device Relations
            //
            break;
        }


        ExAcquireFastMutex (&DeviceData->Mutex);

        oldRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
        if (oldRelations) {
            prevcount = oldRelations->Count;
            if (!DeviceData->NumPDOs) {
                //
                // There is a device relations struct already present and we have
                // nothing to add to it, so just call IoSkip and IoCall
                //
                ExReleaseFastMutex (&DeviceData->Mutex);
                break;
            }
        }
        else  {
            prevcount = 0;
        }

        //
        // Calculate the number of PDOs actually present on the bus
        //
        numPdosPresent = 0;
        for (entry = DeviceData->ListOfPDOs.Flink;
             entry != &DeviceData->ListOfPDOs;
             entry = entry->Flink) {
            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            numPdosPresent++;
        }

        //
        // Need to allocate a new relations structure and add our
        // PDOs to it.
        //

        length = sizeof(DEVICE_RELATIONS) +
                (((numPdosPresent + prevcount) - 1) * sizeof (PDEVICE_OBJECT));

        relations = ExAllocatePoolWithTag(PagedPool, length, 'IpcA');

        if (NULL == relations) {
            //
            // Fail the IRP
            //
            ExReleaseFastMutex (&DeviceData->Mutex);
            Irp->IoStatus.Status = status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
            return status;

        }

        //
        // Copy in the device objects so far
        //
        if (prevcount) {
            RtlCopyMemory (relations->Objects, oldRelations->Objects,
                                      prevcount * sizeof (PDEVICE_OBJECT));
        }

        relations->Count = prevcount + numPdosPresent;

        //
        // For each PDO present on this bus add a pointer to the device relations
        // buffer, being sure to take out a reference to that object.
        // The Plug & Play system will dereference the object when it is done
        // with it and free the device relations buffer.
        //

        for (entry = DeviceData->ListOfPDOs.Flink;
             entry != &DeviceData->ListOfPDOs;
             entry = entry->Flink) {

            pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
            relations->Objects[prevcount] = pdoData->Common.Self;
            ObReferenceObject (pdoData->Common.Self);
            prevcount++;
        }

        DPRINT("\t#PDOs present = %d\n\t#PDOs reported = %d\n",
                             DeviceData->NumPDOs, relations->Count);

        //
        // Replace the relations structure in the IRP with the new
        // one.
        //
        if (oldRelations) {
            ExFreePoolWithTag(oldRelations, 0);
        }
        Irp->IoStatus.Information = (ULONG_PTR) relations;

        ExReleaseFastMutex (&DeviceData->Mutex);

        //
        // Set up and pass the IRP further down the stack
        //
        Irp->IoStatus.Status = STATUS_SUCCESS;
        break;

    default:

        //
        // In the default case we merely call the next driver.
        // We must not modify Irp->IoStatus.Status or complete the IRP.
        //

        break;
    }

    IoSkipCurrentIrpStackLocation (Irp);
    status = IoCallDriver (DeviceData->NextLowerDriver, Irp);
    return STATUS_SUCCESS;
}
Пример #20
0
NTSTATUS
MmAddPhysicalMemory (
    IN PPHYSICAL_ADDRESS StartAddress,
    IN OUT PLARGE_INTEGER NumberOfBytes
    )

/*++

Routine Description:

    This routine adds the specified physical address range to the system.
    This includes initializing PFN database entries and adding it to the
    freelists.

Arguments:

    StartAddress  - Supplies the starting physical address.

    NumberOfBytes  - Supplies a pointer to the number of bytes being added.
                     If any bytes were added (ie: STATUS_SUCCESS is being
                     returned), the actual amount is returned here.

Return Value:

    NTSTATUS.

Environment:

    Kernel mode.  PASSIVE level.  No locks held.

--*/

{
    ULONG i;
    PMMPFN Pfn1;
    KIRQL OldIrql;
    LOGICAL Inserted;
    LOGICAL Updated;
    MMPTE TempPte;
    PMMPTE PointerPte;
    PMMPTE LastPte;
    PFN_NUMBER NumberOfPages;
    PFN_NUMBER start;
    PFN_NUMBER count;
    PFN_NUMBER StartPage;
    PFN_NUMBER EndPage;
    PFN_NUMBER PageFrameIndex;
    PFN_NUMBER Page;
    PFN_NUMBER LastPage;
    PFN_COUNT PagesNeeded;
    PPHYSICAL_MEMORY_DESCRIPTOR OldPhysicalMemoryBlock;
    PPHYSICAL_MEMORY_DESCRIPTOR NewPhysicalMemoryBlock;
    PPHYSICAL_MEMORY_RUN NewRun;
    LOGICAL PfnDatabaseIsPhysical;

    ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);

    ASSERT (BYTE_OFFSET(NumberOfBytes->LowPart) == 0);
    ASSERT (BYTE_OFFSET(StartAddress->LowPart) == 0);

    if (MI_IS_PHYSICAL_ADDRESS(MmPfnDatabase)) {

        //
        // The system must be configured for dynamic memory addition.  This is
        // critical as only then is the database guaranteed to be non-sparse.
        //
    
        if (MmDynamicPfn == FALSE) {
            return STATUS_NOT_SUPPORTED;
        }

        PfnDatabaseIsPhysical = TRUE;
    }
    else {
        PfnDatabaseIsPhysical = FALSE;
    }

    StartPage = (PFN_NUMBER)(StartAddress->QuadPart >> PAGE_SHIFT);
    NumberOfPages = (PFN_NUMBER)(NumberOfBytes->QuadPart >> PAGE_SHIFT);

    EndPage = StartPage + NumberOfPages;

    if (EndPage - 1 > MmHighestPossiblePhysicalPage) {

        //
        // Truncate the request into something that can be mapped by the PFN
        // database.
        //

        EndPage = MmHighestPossiblePhysicalPage + 1;
        NumberOfPages = EndPage - StartPage;
    }

    //
    // The range cannot wrap.
    //

    if (StartPage >= EndPage) {
        return STATUS_INVALID_PARAMETER_1;
    }

    ExAcquireFastMutex (&MmDynamicMemoryMutex);

    i = (sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
         (sizeof(PHYSICAL_MEMORY_RUN) * (MmPhysicalMemoryBlock->NumberOfRuns + 1)));

    NewPhysicalMemoryBlock = ExAllocatePoolWithTag (NonPagedPool,
                                                    i,
                                                    '  mM');

    if (NewPhysicalMemoryBlock == NULL) {
        ExReleaseFastMutex (&MmDynamicMemoryMutex);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // The range cannot overlap any ranges that are already present.
    //

    start = 0;

    LOCK_PFN (OldIrql);

    do {

        count = MmPhysicalMemoryBlock->Run[start].PageCount;
        Page = MmPhysicalMemoryBlock->Run[start].BasePage;

        if (count != 0) {

            LastPage = Page + count;

            if ((StartPage < Page) && (EndPage > Page)) {
                UNLOCK_PFN (OldIrql);
                ExReleaseFastMutex (&MmDynamicMemoryMutex);
                ExFreePool (NewPhysicalMemoryBlock);
                return STATUS_CONFLICTING_ADDRESSES;
            }

            if ((StartPage >= Page) && (StartPage < LastPage)) {
                UNLOCK_PFN (OldIrql);
                ExReleaseFastMutex (&MmDynamicMemoryMutex);
                ExFreePool (NewPhysicalMemoryBlock);
                return STATUS_CONFLICTING_ADDRESSES;
            }
        }

        start += 1;

    } while (start != MmPhysicalMemoryBlock->NumberOfRuns);

    //
    // Fill any gaps in the (sparse) PFN database needed for these pages,
    // unless the PFN database was physically allocated and completely
    // committed up front.
    //

    PagesNeeded = 0;

    if (PfnDatabaseIsPhysical == FALSE) {
        PointerPte = MiGetPteAddress (MI_PFN_ELEMENT(StartPage));
        LastPte = MiGetPteAddress ((PCHAR)(MI_PFN_ELEMENT(EndPage)) - 1);
    
        while (PointerPte <= LastPte) {
            if (PointerPte->u.Hard.Valid == 0) {
                PagesNeeded += 1;
            }
            PointerPte += 1;
        }
    
        if (MmAvailablePages < PagesNeeded) {
            UNLOCK_PFN (OldIrql);
            ExReleaseFastMutex (&MmDynamicMemoryMutex);
            ExFreePool (NewPhysicalMemoryBlock);
            return STATUS_INSUFFICIENT_RESOURCES;
        }
    
        TempPte = ValidKernelPte;
    
        PointerPte = MiGetPteAddress (MI_PFN_ELEMENT(StartPage));
    
        while (PointerPte <= LastPte) {
            if (PointerPte->u.Hard.Valid == 0) {
    
                PageFrameIndex = MiRemoveZeroPage(MI_GET_PAGE_COLOR_FROM_PTE (PointerPte));
    
                MiInitializePfn (PageFrameIndex, PointerPte, 0);
    
                TempPte.u.Hard.PageFrameNumber = PageFrameIndex;
                *PointerPte = TempPte;
            }
            PointerPte += 1;
        }
        MmResidentAvailablePages -= PagesNeeded;
    }

    //
    // If the new range is adjacent to an existing range, just merge it into
    // the old block.  Otherwise use the new block as a new entry will have to
    // be used.
    //

    NewPhysicalMemoryBlock->NumberOfRuns = MmPhysicalMemoryBlock->NumberOfRuns + 1;
    NewPhysicalMemoryBlock->NumberOfPages = MmPhysicalMemoryBlock->NumberOfPages + NumberOfPages;

    NewRun = &NewPhysicalMemoryBlock->Run[0];
    start = 0;
    Inserted = FALSE;
    Updated = FALSE;

    do {

        Page = MmPhysicalMemoryBlock->Run[start].BasePage;
        count = MmPhysicalMemoryBlock->Run[start].PageCount;

        if (Inserted == FALSE) {

            //
            // Note overlaps into adjacent ranges were already checked above.
            //

            if (StartPage == Page + count) {
                MmPhysicalMemoryBlock->Run[start].PageCount += NumberOfPages;
                OldPhysicalMemoryBlock = NewPhysicalMemoryBlock;
                MmPhysicalMemoryBlock->NumberOfPages += NumberOfPages;

                //
                // Coalesce below and above to avoid leaving zero length gaps
                // as these gaps would prevent callers from removing ranges
                // the span them.
                //

                if (start + 1 < MmPhysicalMemoryBlock->NumberOfRuns) {

                    start += 1;
                    Page = MmPhysicalMemoryBlock->Run[start].BasePage;
                    count = MmPhysicalMemoryBlock->Run[start].PageCount;

                    if (StartPage + NumberOfPages == Page) {
                        MmPhysicalMemoryBlock->Run[start - 1].PageCount +=
                            count;
                        MmPhysicalMemoryBlock->NumberOfRuns -= 1;

                        //
                        // Copy any remaining entries.
                        //
    
                        if (start != MmPhysicalMemoryBlock->NumberOfRuns) {
                            RtlMoveMemory (&MmPhysicalMemoryBlock->Run[start],
                                           &MmPhysicalMemoryBlock->Run[start + 1],
                                           (MmPhysicalMemoryBlock->NumberOfRuns - start) * sizeof (PHYSICAL_MEMORY_RUN));
                        }
                    }
                }
                Updated = TRUE;
                break;
            }

            if (StartPage + NumberOfPages == Page) {
                MmPhysicalMemoryBlock->Run[start].BasePage = StartPage;
                MmPhysicalMemoryBlock->Run[start].PageCount += NumberOfPages;
                OldPhysicalMemoryBlock = NewPhysicalMemoryBlock;
                MmPhysicalMemoryBlock->NumberOfPages += NumberOfPages;
                Updated = TRUE;
                break;
            }

            if (StartPage + NumberOfPages <= Page) {

                if (start + 1 < MmPhysicalMemoryBlock->NumberOfRuns) {

                    if (StartPage + NumberOfPages <= MmPhysicalMemoryBlock->Run[start + 1].BasePage) {
                        //
                        // Don't insert here - the new entry really belongs
                        // (at least) one entry further down.
                        //

                        continue;
                    }
                }

                NewRun->BasePage = StartPage;
                NewRun->PageCount = NumberOfPages;
                NewRun += 1;
                Inserted = TRUE;
                Updated = TRUE;
            }
        }

        *NewRun = MmPhysicalMemoryBlock->Run[start];
        NewRun += 1;

        start += 1;

    } while (start != MmPhysicalMemoryBlock->NumberOfRuns);

    //
    // If the memory block has not been updated, then the new entry must
    // be added at the very end.
    //

    if (Updated == FALSE) {
        ASSERT (Inserted == FALSE);
        NewRun->BasePage = StartPage;
        NewRun->PageCount = NumberOfPages;
        Inserted = TRUE;
    }

    //
    // Repoint the MmPhysicalMemoryBlock at the new chunk, free the old after
    // releasing the PFN lock.
    //

    if (Inserted == TRUE) {
        OldPhysicalMemoryBlock = MmPhysicalMemoryBlock;
        MmPhysicalMemoryBlock = NewPhysicalMemoryBlock;
    }

    //
    // Note that the page directory (page parent entries on Win64) must be
    // filled in at system boot so that already-created processes do not fault
    // when referencing the new PFNs.
    //

    //
    // Walk through the memory descriptors and add pages to the
    // free list in the PFN database.
    //

    PageFrameIndex = StartPage;
    Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);

    if (EndPage - 1 > MmHighestPhysicalPage) {
        MmHighestPhysicalPage = EndPage - 1;
    }

    while (PageFrameIndex < EndPage) {

        ASSERT (Pfn1->u2.ShareCount == 0);
        ASSERT (Pfn1->u3.e2.ShortFlags == 0);
        ASSERT (Pfn1->u3.e2.ReferenceCount == 0);
        ASSERT64 (Pfn1->UsedPageTableEntries == 0);
        ASSERT (Pfn1->OriginalPte.u.Long == ZeroKernelPte.u.Long);
        ASSERT (Pfn1->PteFrame == 0);
        ASSERT ((Pfn1->PteAddress == PFN_REMOVED) ||
                (Pfn1->PteAddress == (PMMPTE)(UINT_PTR)0));

        //
        // Set the PTE address to the physical page for
        // virtual address alignment checking.
        //

        Pfn1->PteAddress = (PMMPTE)(PageFrameIndex << PTE_SHIFT);

        MiInsertPageInList (MmPageLocationList[FreePageList],
                            PageFrameIndex);

        PageFrameIndex += 1;
        
        Pfn1 += 1;
    }

    MmResidentAvailablePages += NumberOfPages;
    MmNumberOfPhysicalPages += (PFN_COUNT)NumberOfPages;

    UNLOCK_PFN (OldIrql);

    //
    // Increase all commit limits to reflect the additional memory.
    //

    ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql);

    MmTotalCommitLimit += NumberOfPages;
    MmTotalCommitLimitMaximum += NumberOfPages;

    MmTotalCommittedPages += PagesNeeded;

    ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql);

    ExReleaseFastMutex (&MmDynamicMemoryMutex);

    ExFreePool (OldPhysicalMemoryBlock);

    //
    // Indicate number of bytes actually added to our caller.
    //

    NumberOfBytes->QuadPart = (ULONGLONG)NumberOfPages * PAGE_SIZE;

    return STATUS_SUCCESS;
}
Пример #21
0
VOID
Secondary_Close (
	IN  PSECONDARY	Secondary
	)
{
	NTSTATUS		status;
	LARGE_INTEGER	timeOut;

	PLIST_ENTRY			secondaryRequestEntry;
	PSECONDARY_REQUEST	secondaryRequest;


	DebugTrace2( 0, Dbg2, 
				   ("Secondary close Secondary = %p\n", Secondary) );

	ExAcquireFastMutex( &Secondary->FastMutex );

	if (FlagOn(Secondary->Flags, SECONDARY_FLAG_CLOSED)) {

		//ASSERT( FALSE );
		ExReleaseFastMutex( &Secondary->FastMutex );
		return;
	}

	SetFlag( Secondary->Flags, SECONDARY_FLAG_CLOSED );

	ExReleaseFastMutex( &Secondary->FastMutex );

	if (Secondary->ThreadHandle == NULL) {

		Secondary_Dereference( Secondary );
		return;
	}

	ASSERT( Secondary->ThreadObject != NULL );

	DebugTrace2( 0, Dbg, ("Secondary close SECONDARY_REQ_DISCONNECT Secondary = %p\n", Secondary) );

	secondaryRequest = AllocSecondaryRequest( Secondary, 0, FALSE );
	secondaryRequest->RequestType = SECONDARY_REQ_DISCONNECT;

	QueueingSecondaryRequest( Secondary, secondaryRequest );

	secondaryRequest = AllocSecondaryRequest( Secondary, 0, FALSE );
	secondaryRequest->RequestType = SECONDARY_REQ_DOWN;

	QueueingSecondaryRequest( Secondary, secondaryRequest );

	DebugTrace2( 0, Dbg, ("Secondary close SECONDARY_REQ_DISCONNECT end Secondary = %p\n", Secondary) );

	timeOut.QuadPart = -NDASFAT_TIME_OUT;

	status = KeWaitForSingleObject( Secondary->ThreadObject,
									Executive,
									KernelMode,
									FALSE,
									&timeOut );

	if (status == STATUS_SUCCESS) {
	   
		DebugTrace2( 0, Dbg, ("Secondary_Close: thread stoped Secondary = %p\n", Secondary));

		ObDereferenceObject( Secondary->ThreadObject );

		Secondary->ThreadHandle = NULL;
		Secondary->ThreadObject = NULL;
	
	} else {

		ASSERT( NDASFAT_BUG );
		return;
	}

	ASSERT( Secondary->VolDo->Vcb.SecondaryOpenFileCount == 0 );

	ASSERT( IsListEmpty(&Secondary->FcbQueue) );
	ASSERT( IsListEmpty(&Secondary->RecoveryCcbQueue) );
	ASSERT( IsListEmpty(&Secondary->RequestQueue) );

	while (secondaryRequestEntry = ExInterlockedRemoveHeadList(&Secondary->RequestQueue,
															   &Secondary->RequestQSpinLock)) {

		PSECONDARY_REQUEST secondaryRequest2;

		InitializeListHead( secondaryRequestEntry );
			
		secondaryRequest2 = CONTAINING_RECORD( secondaryRequestEntry,
											   SECONDARY_REQUEST,
											   ListEntry );
        
		secondaryRequest2->ExecuteStatus = STATUS_IO_DEVICE_ERROR;
		
		if (secondaryRequest2->Synchronous == TRUE)
			KeSetEvent( &secondaryRequest2->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferenceSecondaryRequest( secondaryRequest2 );
	}
	
	Secondary_Dereference( Secondary );

	return;
}
Пример #22
0
NTSTATUS
MmRemovePhysicalMemory (
    IN PPHYSICAL_ADDRESS StartAddress,
    IN OUT PLARGE_INTEGER NumberOfBytes
    )

/*++

Routine Description:

    This routine attempts to remove the specified physical address range
    from the system.

Arguments:

    StartAddress  - Supplies the starting physical address.

    NumberOfBytes  - Supplies a pointer to the number of bytes being removed.

Return Value:

    NTSTATUS.

Environment:

    Kernel mode.  PASSIVE level.  No locks held.

--*/

{
    ULONG i;
    ULONG Additional;
    PFN_NUMBER Page;
    PFN_NUMBER LastPage;
    PFN_NUMBER OriginalLastPage;
    PFN_NUMBER start;
    PFN_NUMBER PagesReleased;
    PMMPFN Pfn1;
    PMMPFN StartPfn;
    PMMPFN EndPfn;
    KIRQL OldIrql;
    PFN_NUMBER StartPage;
    PFN_NUMBER EndPage;
    PFN_COUNT NumberOfPages;
    SPFN_NUMBER MaxPages;
    PFN_NUMBER PageFrameIndex;
    PFN_NUMBER RemovedPages;
    LOGICAL Inserted;
    NTSTATUS Status;
    PMMPTE PointerPte;
    PMMPTE EndPte;
    PVOID VirtualAddress;
    PPHYSICAL_MEMORY_DESCRIPTOR OldPhysicalMemoryBlock;
    PPHYSICAL_MEMORY_DESCRIPTOR NewPhysicalMemoryBlock;
    PPHYSICAL_MEMORY_RUN NewRun;
    LOGICAL PfnDatabaseIsPhysical;

    ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);

    ASSERT (BYTE_OFFSET(NumberOfBytes->LowPart) == 0);
    ASSERT (BYTE_OFFSET(StartAddress->LowPart) == 0);

    if (MI_IS_PHYSICAL_ADDRESS(MmPfnDatabase)) {

        //
        // The system must be configured for dynamic memory addition.  This is
        // not strictly required to remove the memory, but it's better to check
        // for it now under the assumption that the administrator is probably
        // going to want to add this range of memory back in - better to give
        // the error now and refuse the removal than to refuse the addition
        // later.
        //
    
        if (MmDynamicPfn == FALSE) {
            return STATUS_NOT_SUPPORTED;
        }

        PfnDatabaseIsPhysical = TRUE;
    }
    else {
        PfnDatabaseIsPhysical = FALSE;
    }

    StartPage = (PFN_NUMBER)(StartAddress->QuadPart >> PAGE_SHIFT);
    NumberOfPages = (PFN_COUNT)(NumberOfBytes->QuadPart >> PAGE_SHIFT);

    EndPage = StartPage + NumberOfPages;

    if (EndPage - 1 > MmHighestPossiblePhysicalPage) {

        //
        // Truncate the request into something that can be mapped by the PFN
        // database.
        //

        EndPage = MmHighestPossiblePhysicalPage + 1;
        NumberOfPages = (PFN_COUNT)(EndPage - StartPage);
    }

    //
    // The range cannot wrap.
    //

    if (StartPage >= EndPage) {
        return STATUS_INVALID_PARAMETER_1;
    }

    StartPfn = MI_PFN_ELEMENT (StartPage);
    EndPfn = MI_PFN_ELEMENT (EndPage);

    ExAcquireFastMutex (&MmDynamicMemoryMutex);

#if DBG
    MiDynmemData[0] += 1;
#endif

    //
    // Decrease all commit limits to reflect the removed memory.
    //

    ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql);

    ASSERT (MmTotalCommitLimit <= MmTotalCommitLimitMaximum);

    if ((NumberOfPages + 100 > MmTotalCommitLimit - MmTotalCommittedPages) ||
        (MmTotalCommittedPages > MmTotalCommitLimit)) {

#if DBG
        MiDynmemData[1] += 1;
#endif
        ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql);
        ExReleaseFastMutex (&MmDynamicMemoryMutex);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    MmTotalCommitLimit -= NumberOfPages;
    MmTotalCommitLimitMaximum -= NumberOfPages;

    ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql);

    //
    // Check for outstanding promises that cannot be broken.
    //

    LOCK_PFN (OldIrql);

    MaxPages = MI_NONPAGABLE_MEMORY_AVAILABLE() - 100;

    if ((SPFN_NUMBER)NumberOfPages > MaxPages) {
#if DBG
        MiDynmemData[2] += 1;
#endif
        UNLOCK_PFN (OldIrql);
        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto giveup2;
    }

    MmResidentAvailablePages -= NumberOfPages;
    MmNumberOfPhysicalPages -= NumberOfPages;

    //
    // The range must be contained in a single entry.  It is permissible for
    // it to be part of a single entry, but it must not cross multiple entries.
    //

    Additional = (ULONG)-2;

    start = 0;
    do {

        Page = MmPhysicalMemoryBlock->Run[start].BasePage;
        LastPage = Page + MmPhysicalMemoryBlock->Run[start].PageCount;

        if ((StartPage >= Page) && (EndPage <= LastPage)) {
            if ((StartPage == Page) && (EndPage == LastPage)) {
                Additional = (ULONG)-1;
            }
            else if ((StartPage == Page) || (EndPage == LastPage)) {
                Additional = 0;
            }
            else {
                Additional = 1;
            }
            break;
        }

        start += 1;

    } while (start != MmPhysicalMemoryBlock->NumberOfRuns);

    if (Additional == (ULONG)-2) {
#if DBG
        MiDynmemData[3] += 1;
#endif
        MmResidentAvailablePages += NumberOfPages;
        MmNumberOfPhysicalPages += NumberOfPages;
        UNLOCK_PFN (OldIrql);
        Status = STATUS_CONFLICTING_ADDRESSES;
        goto giveup2;
    }

    for (Pfn1 = StartPfn; Pfn1 < EndPfn; Pfn1 += 1) {
        Pfn1->u3.e1.RemovalRequested = 1;
    }

    //
    // The free and zero lists must be pruned now before releasing the PFN
    // lock otherwise if another thread allocates the page from these lists,
    // the allocation will clear the RemovalRequested flag forever.
    //

    RemovedPages = MiRemovePhysicalPages (StartPage, EndPage);

    if (RemovedPages != NumberOfPages) {

#if DBG
retry:
#endif
    
        Pfn1 = StartPfn;
    
        InterlockedIncrement (&MiDelayPageFaults);
    
        for (i = 0; i < 5; i += 1) {
    
            UNLOCK_PFN (OldIrql);
    
            //
            // Attempt to move pages to the standby list.  Note that only the
            // pages with RemovalRequested set are moved.
            //
    
            MiTrimRemovalPagesOnly = TRUE;
    
            MiEmptyAllWorkingSets ();
    
            MiTrimRemovalPagesOnly = FALSE;
    
            MiFlushAllPages ();
    
            KeDelayExecutionThread (KernelMode, FALSE, &MmHalfSecond);
    
            LOCK_PFN (OldIrql);
    
            RemovedPages += MiRemovePhysicalPages (StartPage, EndPage);
    
            if (RemovedPages == NumberOfPages) {
                break;
            }
    
            //
            // RemovedPages doesn't include pages that were freed directly to
            // the bad page list via MiDecrementReferenceCount.  So use the above
            // check purely as an optimization - and walk here when necessary.
            //
    
            for ( ; Pfn1 < EndPfn; Pfn1 += 1) {
                if (Pfn1->u3.e1.PageLocation != BadPageList) {
                    break;
                }
            }
    
            if (Pfn1 == EndPfn) {
                RemovedPages = NumberOfPages;
                break;
            }
        }

        InterlockedDecrement (&MiDelayPageFaults);
    }

    if (RemovedPages != NumberOfPages) {
#if DBG
        MiDynmemData[4] += 1;
        if (MiShowStuckPages != 0) {

            RemovedPages = 0;
            for (Pfn1 = StartPfn; Pfn1 < EndPfn; Pfn1 += 1) {
                if (Pfn1->u3.e1.PageLocation != BadPageList) {
                    RemovedPages += 1;
                }
            }

            ASSERT (RemovedPages != 0);

            DbgPrint("MmRemovePhysicalMemory : could not get %d of %d pages\n",
                RemovedPages, NumberOfPages);

            if (MiShowStuckPages & 0x2) {

                ULONG PfnsPrinted;
                ULONG EnoughShown;
                PMMPFN FirstPfn;
                PFN_COUNT PfnCount;

                PfnCount = 0;
                PfnsPrinted = 0;
                EnoughShown = 100;
    
                if (MiShowStuckPages & 0x4) {
                    EnoughShown = (ULONG)-1;
                }
    
                DbgPrint("Stuck PFN list: ");
                for (Pfn1 = StartPfn; Pfn1 < EndPfn; Pfn1 += 1) {
                    if (Pfn1->u3.e1.PageLocation != BadPageList) {
                        if (PfnCount == 0) {
                            FirstPfn = Pfn1;
                        }
                        PfnCount += 1;
                    }
                    else {
                        if (PfnCount != 0) {
                            DbgPrint("%x -> %x ; ", FirstPfn - MmPfnDatabase,
                                                    (FirstPfn - MmPfnDatabase) + PfnCount - 1);
                            PfnsPrinted += 1;
                            if (PfnsPrinted == EnoughShown) {
                                break;
                            }
                            PfnCount = 0;
                        }
                    }
                }
                if (PfnCount != 0) {
                    DbgPrint("%x -> %x ; ", FirstPfn - MmPfnDatabase,
                                            (FirstPfn - MmPfnDatabase) + PfnCount - 1);
                }
                DbgPrint("\n");
            }
            if (MiShowStuckPages & 0x8) {
                DbgBreakPoint ();
            }
            if (MiShowStuckPages & 0x10) {
                goto retry;
            }
        }
#endif
        UNLOCK_PFN (OldIrql);
        Status = STATUS_NO_MEMORY;
        goto giveup;
    }

#if DBG
    for (Pfn1 = StartPfn; Pfn1 < EndPfn; Pfn1 += 1) {
        ASSERT (Pfn1->u3.e1.PageLocation == BadPageList);
    }
#endif

    //
    // All the pages in the range have been removed.  Update the physical
    // memory blocks and other associated housekeeping.
    //

    if (Additional == 0) {

        //
        // The range can be split off from an end of an existing chunk so no
        // pool growth or shrinkage is required.
        //

        NewPhysicalMemoryBlock = MmPhysicalMemoryBlock;
        OldPhysicalMemoryBlock = NULL;
    }
    else {

        //
        // The range cannot be split off from an end of an existing chunk so
        // pool growth or shrinkage is required.
        //

        UNLOCK_PFN (OldIrql);

        i = (sizeof(PHYSICAL_MEMORY_DESCRIPTOR) +
             (sizeof(PHYSICAL_MEMORY_RUN) * (MmPhysicalMemoryBlock->NumberOfRuns + Additional)));

        NewPhysicalMemoryBlock = ExAllocatePoolWithTag (NonPagedPool,
                                                        i,
                                                        '  mM');

        if (NewPhysicalMemoryBlock == NULL) {
            Status = STATUS_INSUFFICIENT_RESOURCES;
#if DBG
            MiDynmemData[5] += 1;
#endif
            goto giveup;
        }

        OldPhysicalMemoryBlock = MmPhysicalMemoryBlock;
        RtlZeroMemory (NewPhysicalMemoryBlock, i);

        LOCK_PFN (OldIrql);
    }

    //
    // Remove or split the requested range from the existing memory block.
    //

    NewPhysicalMemoryBlock->NumberOfRuns = MmPhysicalMemoryBlock->NumberOfRuns + Additional;
    NewPhysicalMemoryBlock->NumberOfPages = MmPhysicalMemoryBlock->NumberOfPages - NumberOfPages;

    NewRun = &NewPhysicalMemoryBlock->Run[0];
    start = 0;
    Inserted = FALSE;

    do {

        Page = MmPhysicalMemoryBlock->Run[start].BasePage;
        LastPage = Page + MmPhysicalMemoryBlock->Run[start].PageCount;

        if (Inserted == FALSE) {

            if ((StartPage >= Page) && (EndPage <= LastPage)) {

                if ((StartPage == Page) && (EndPage == LastPage)) {
                    ASSERT (Additional == -1);
                    start += 1;
                    continue;
                }
                else if ((StartPage == Page) || (EndPage == LastPage)) {
                    ASSERT (Additional == 0);
                    if (StartPage == Page) {
                        MmPhysicalMemoryBlock->Run[start].BasePage += NumberOfPages;
                    }
                    MmPhysicalMemoryBlock->Run[start].PageCount -= NumberOfPages;
                }
                else {
                    ASSERT (Additional == 1);

                    OriginalLastPage = LastPage;

                    MmPhysicalMemoryBlock->Run[start].PageCount =
                        StartPage - MmPhysicalMemoryBlock->Run[start].BasePage;

                    *NewRun = MmPhysicalMemoryBlock->Run[start];
                    NewRun += 1;

                    NewRun->BasePage = EndPage;
                    NewRun->PageCount = OriginalLastPage - EndPage;
                    NewRun += 1;

                    start += 1;
                    continue;
                }

                Inserted = TRUE;
            }
        }

        *NewRun = MmPhysicalMemoryBlock->Run[start];
        NewRun += 1;
        start += 1;

    } while (start != MmPhysicalMemoryBlock->NumberOfRuns);

    //
    // Repoint the MmPhysicalMemoryBlock at the new chunk.
    // Free the old block after releasing the PFN lock.
    //

    MmPhysicalMemoryBlock = NewPhysicalMemoryBlock;

    if (EndPage - 1 == MmHighestPhysicalPage) {
        MmHighestPhysicalPage = StartPage - 1;
    }

    //
    // Throw away all the removed pages that are currently enqueued.
    //

    for (Pfn1 = StartPfn; Pfn1 < EndPfn; Pfn1 += 1) {

        ASSERT (Pfn1->u3.e1.PageLocation == BadPageList);
        ASSERT (Pfn1->u3.e1.RemovalRequested == 1);

        MiUnlinkPageFromList (Pfn1);

        ASSERT (Pfn1->u1.Flink == 0);
        ASSERT (Pfn1->u2.Blink == 0);
        ASSERT (Pfn1->u3.e2.ReferenceCount == 0);
        ASSERT64 (Pfn1->UsedPageTableEntries == 0);

        Pfn1->PteAddress = PFN_REMOVED;
        Pfn1->u3.e2.ShortFlags = 0;
        Pfn1->OriginalPte.u.Long = ZeroKernelPte.u.Long;
        Pfn1->PteFrame = 0;
    }

    //
    // Now that the removed pages have been discarded, eliminate the PFN
    // entries that mapped them.  Straddling entries left over from an
    // adjacent earlier removal are not collapsed at this point.
    //
    //

    PagesReleased = 0;

    if (PfnDatabaseIsPhysical == FALSE) {

        VirtualAddress = (PVOID)ROUND_TO_PAGES(MI_PFN_ELEMENT(StartPage));
        PointerPte = MiGetPteAddress (VirtualAddress);
        EndPte = MiGetPteAddress (PAGE_ALIGN(MI_PFN_ELEMENT(EndPage)));

        while (PointerPte < EndPte) {
            PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte);
            Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);
            ASSERT (Pfn1->u2.ShareCount == 1);
            ASSERT (Pfn1->u3.e2.ReferenceCount == 1);
            Pfn1->u2.ShareCount = 0;
            MI_SET_PFN_DELETED (Pfn1);
#if DBG
            Pfn1->u3.e1.PageLocation = StandbyPageList;
#endif //DBG
            MiDecrementReferenceCount (PageFrameIndex);
    
            KeFlushSingleTb (VirtualAddress,
                             TRUE,
                             TRUE,
                             (PHARDWARE_PTE)PointerPte,
                             ZeroKernelPte.u.Flush);
    
            PagesReleased += 1;
            PointerPte += 1;
            VirtualAddress = (PVOID)((PCHAR)VirtualAddress + PAGE_SIZE);
        }

        MmResidentAvailablePages += PagesReleased;
    }

#if DBG
    MiDynmemData[6] += 1;
#endif

    UNLOCK_PFN (OldIrql);

    if (PagesReleased != 0) {
        MiReturnCommitment (PagesReleased);
    }

    ExReleaseFastMutex (&MmDynamicMemoryMutex);

    if (OldPhysicalMemoryBlock != NULL) {
        ExFreePool (OldPhysicalMemoryBlock);
    }

    NumberOfBytes->QuadPart = (ULONGLONG)NumberOfPages * PAGE_SIZE;

    return STATUS_SUCCESS;

giveup:

    //
    // All the pages in the range were not obtained.  Back everything out.
    //

    PageFrameIndex = StartPage;
    Pfn1 = MI_PFN_ELEMENT (PageFrameIndex);

    LOCK_PFN (OldIrql);

    while (PageFrameIndex < EndPage) {

        ASSERT (Pfn1->u3.e1.RemovalRequested == 1);

        Pfn1->u3.e1.RemovalRequested = 0;

        if ((Pfn1->u3.e1.PageLocation == BadPageList) &&
            (Pfn1->u3.e1.ParityError == 0)) {

            MiUnlinkPageFromList (Pfn1);
            MiInsertPageInList (MmPageLocationList[FreePageList],
                                PageFrameIndex);
        }

        Pfn1 += 1;
        PageFrameIndex += 1;
    }

    MmResidentAvailablePages += NumberOfPages;
    MmNumberOfPhysicalPages += NumberOfPages;

    UNLOCK_PFN (OldIrql);

giveup2:

    ExAcquireSpinLock (&MmChargeCommitmentLock, &OldIrql);
    MmTotalCommitLimit += NumberOfPages;
    MmTotalCommitLimitMaximum += NumberOfPages;
    ExReleaseSpinLock (&MmChargeCommitmentLock, OldIrql);

    ExReleaseFastMutex (&MmDynamicMemoryMutex);

    return Status;
}
Пример #23
0
NTSTATUS
NdFatSecondaryCommonWrite3 (
	IN PIRP_CONTEXT IrpContext,
	IN PIRP			Irp
	)
{
	NTSTATUS					status;

	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;
	
	PIO_STACK_LOCATION			irpSp = IoGetCurrentIrpStackLocation( Irp );
	PFILE_OBJECT				fileObject = irpSp->FileObject;

	struct Write				write;
	
	PSECONDARY_REQUEST			secondaryRequest = NULL;
	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

	LARGE_INTEGER				timeOut;

	TYPE_OF_OPEN				typeOfOpen;
	PVCB						vcb;
	PFCB						fcb;
	PCCB						ccb;
	BOOLEAN						fcbAcquired = FALSE;

	BOOLEAN						writeToEof;
	PUCHAR						inputBuffer;
	ULONG						totalWriteLength;


	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
	ASSERT (!FlagOn(Irp->Flags, IRP_PAGING_IO));
	
	typeOfOpen = FatDecodeFileObject( fileObject, &vcb, &fcb, &ccb );

	ASSERT( typeOfOpen == UserFileOpen );

	if (FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

		/*if (FlagOn( fcb->FcbState, FCB_STATE_FILE_DELETED )) {
	
			ASSERT( FALSE );
			FatRaiseStatus( IrpContext, STATUS_FILE_DELETED, NULL, NULL );
					
		} else */{
					
			ASSERT( FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) );

			status = STATUS_FILE_CORRUPT_ERROR;
	        FatCompleteRequest( IrpContext, Irp, status );
			return status;
		}
	}

	writeToEof = (irpSp->Parameters.Write.ByteOffset.QuadPart == FILE_WRITE_TO_END_OF_FILE && 
				  irpSp->Parameters.Write.ByteOffset.HighPart == -1);

	write.ByteOffset	= irpSp->Parameters.Write.ByteOffset;
	write.Key			= irpSp->Parameters.Write.Key;
	write.Length		= irpSp->Parameters.Write.Length;

	ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); 

	//FatAcquireSharedFcb( IrpContext, fcb );
	//fcbAcquired = TRUE;


	try {

		secondarySessionResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( IrpContext, 
													 &volDo->Secondary->SessionResource, 
													 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

		if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

			PrintIrp( Dbg, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );

			if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
	
				try_return( status = STATUS_FILE_LOCK_CONFLICT );
				
			} else {

				FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
			}
		}

		inputBuffer = FatMapUserBuffer( IrpContext, Irp );
		totalWriteLength = 0;

		do {

			ULONG	inputBufferLength;
			_U8		*ndfsWinxpRequestData;
			_U64	primaryFileHandle;

			if (fcb->UncleanCount == 0) {

				DebugTrace( 0, Dbg2, "NdFatSecondaryCommonWrite2: fileName = %wZ\n", &fileObject->FileName );

				totalWriteLength = write.Length;
				status = STATUS_FILE_CLOSED;
				break;
			}

			if (!FlagOn(ccb->NdFatFlags, ND_FAT_CLEANUP_COMPLETE)) {

				primaryFileHandle = ccb->PrimaryFileHandle;

			} else {

				PLIST_ENTRY	ccbListEntry;

				ExAcquireFastMutex( &fcb->CcbQMutex );
				
				for (primaryFileHandle = 0, ccbListEntry = fcb->CcbQueue.Flink; 
					 ccbListEntry != &fcb->CcbQueue; 
					 ccbListEntry = ccbListEntry->Flink) {

					if (!FlagOn(CONTAINING_RECORD(ccbListEntry, CCB, FcbListEntry)->NdFatFlags, ND_FAT_CLEANUP_COMPLETE)) {
						
						primaryFileHandle = CONTAINING_RECORD(ccbListEntry, CCB, FcbListEntry)->PrimaryFileHandle;
						break;
					}
				}

				ExReleaseFastMutex( &fcb->CcbQMutex );
			}

			ASSERT( primaryFileHandle );

			inputBufferLength = ((write.Length-totalWriteLength) <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize) 
									? (write.Length-totalWriteLength) : volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize;

			secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, 
															  IRP_MJ_WRITE,
															  volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize );

			if (secondaryRequest == NULL) {

				FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
			}

			ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
			INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_WRITE, inputBufferLength );

			ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
			ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

			//ndfsWinxpRequestHeader->IrpTag   = (_U32)Irp;
			ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_WRITE;
			ndfsWinxpRequestHeader->IrpMinorFunction = 0;

			ndfsWinxpRequestHeader->FileHandle = primaryFileHandle;

			ndfsWinxpRequestHeader->IrpFlags   = 0;
			ndfsWinxpRequestHeader->IrpSpFlags = 0;

			ndfsWinxpRequestHeader->Write.Length		= inputBufferLength;
			ndfsWinxpRequestHeader->Write.Key			= write.Key;
			if (writeToEof)
				ndfsWinxpRequestHeader->Write.ByteOffset = write.ByteOffset.QuadPart;
			else
				ndfsWinxpRequestHeader->Write.ByteOffset = write.ByteOffset.QuadPart + totalWriteLength;
			
			ndfsWinxpRequestHeader->Write.ForceWrite	= TRUE;


			DebugTrace2( 0, Dbg, ("ndfsWinxpRequestHeader->Write.ByteOffset = %I64d, ndfsWinxpRequestHeader->Write.Length = %d\n", 
								   ndfsWinxpRequestHeader->Write.ByteOffset, ndfsWinxpRequestHeader->Write.Length) );

			ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1);

			if (inputBufferLength) {

				try {

					RtlCopyMemory( ndfsWinxpRequestData,
								   inputBuffer + totalWriteLength,
								   inputBufferLength );

				} except (EXCEPTION_EXECUTE_HANDLER) {

					DebugTrace2( 0, Dbg2, ("RedirectIrp: Exception - Input buffer is not valid\n") );
					
					status = GetExceptionCode();
					break;
				}
			}

			//if (fcb->Header.FileSize.LowPart < 100)
			//	DbgPrint( "data = %s\n", ndfsWinxpRequestData );

			secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
			QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

			timeOut.QuadPart = -NDFAT_TIME_OUT;
			status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
		
			if (status != STATUS_SUCCESS) {

				secondaryRequest = NULL;
				status = STATUS_IO_DEVICE_ERROR;
				leave;
			}

			KeClearEvent( &secondaryRequest->CompleteEvent );

			if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

				if (IrpContext->OriginatingIrp)
					PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );
			
				DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

				if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
	
					try_return( status = STATUS_FILE_LOCK_CONFLICT );
				
				} else {

					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
				}
			}

			ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;

			if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {
			
				DebugTrace2( 0, Dbg, ("ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );

				if (totalWriteLength)
					status = STATUS_SUCCESS;
				else
					status = ndfsWinxpReplytHeader->Status;

				ASSERT( ndfsWinxpReplytHeader->Information == 0 );
				DereferenceSecondaryRequest( secondaryRequest );
				secondaryRequest = NULL;				
				
				break;
			}

			totalWriteLength += ndfsWinxpReplytHeader->Information;

			ASSERT( ndfsWinxpReplytHeader->Information <= inputBufferLength );
			ASSERT( ndfsWinxpReplytHeader->Information != 0 );
		
			DereferenceSecondaryRequest( secondaryRequest );
			secondaryRequest = NULL;

		} while( totalWriteLength < write.Length );

try_exit: NOTHING;

	} finally {

		if (!AbnormalTermination()) {
			
			if (totalWriteLength) {

				Irp->IoStatus.Information = totalWriteLength;
				Irp->IoStatus.Status = STATUS_SUCCESS;
		
			} else {
		
				Irp->IoStatus.Information = 0;
				Irp->IoStatus.Status = status;
			}
		}

		DebugTrace2( 0, Dbg, ("write.ByteOffset.QuadPart = %I64x, write.Length = %x, totalWriteRequestLength = %x lastStatus = %x\n", 
								write.ByteOffset.QuadPart, write.Length, totalWriteLength, status) );

		if (!FlagOn(ccb->NdFatFlags, ND_FAT_CLEANUP_COMPLETE) && Irp->IoStatus.Status != STATUS_SUCCESS) {

			DebugTrace2( 0, Dbg, ("write.ByteOffset.QuadPart = %I64x, write.Length = %x, totalWriteRequestLength = %x lastStatus = %x\n", 
								 write.ByteOffset.QuadPart, write.Length, totalWriteLength, status) );

			PrintIrp( Dbg, "RedirectIrpMajorWrite", NULL, Irp );
		}

		if (secondarySessionResourceAcquired == TRUE)
			SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource );

		if (fcbAcquired) {
             FatReleaseFcb( IrpContext, fcb );
        }

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}
			
	FatCompleteRequest( IrpContext, Irp, status );
	return status;
}
Пример #24
0
NTSTATUS 
MiniSecondaryNtfsPassThrough (
	IN  PSECONDARY				Secondary,
	IN OUT PFLT_CALLBACK_DATA	Data
	)
{
	NTSTATUS				status = FLT_PREOP_SUCCESS_NO_CALLBACK;
	//PIO_STACK_LOCATION	iopb = IoGetCurrentIrpStackLocation( Irp );
	PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
	PFILE_OBJECT			fileObject = iopb->TargetFileObject;

	BOOLEAN				fastMutexSet = FALSE;
	BOOLEAN				retry = FALSE;


	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );

	Secondary_Reference( Secondary );
 
	if (fileObject && fileObject->Flags & FO_DIRECT_DEVICE_OPEN) {

		NDASFS_ASSERT( LFS_REQUIRED );
		DbgPrint( "Direct device open\n" );
	}

	if (iopb->MajorFunction == IRP_MJ_CREATE					||	// 0x00
		iopb->MajorFunction == IRP_MJ_CLOSE					||	// 0x01
		iopb->MajorFunction == IRP_MJ_READ						||  // 0x03
		iopb->MajorFunction == IRP_MJ_WRITE					||  // 0x04
		iopb->MajorFunction == IRP_MJ_QUERY_INFORMATION		||  // 0x05
		iopb->MajorFunction == IRP_MJ_SET_INFORMATION			||	// 0x06
		iopb->MajorFunction == IRP_MJ_QUERY_EA					||	// 0x07
		iopb->MajorFunction == IRP_MJ_SET_EA					||	// 0x08
		iopb->MajorFunction == IRP_MJ_FLUSH_BUFFERS			||	// 0x09
		iopb->MajorFunction == IRP_MJ_QUERY_VOLUME_INFORMATION	||	// 0x0a
		iopb->MajorFunction == IRP_MJ_SET_VOLUME_INFORMATION	||	// 0x0b
		iopb->MajorFunction == IRP_MJ_DIRECTORY_CONTROL		||	// 0x0c
		iopb->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL		||	// 0x0c
		iopb->MajorFunction == IRP_MJ_LOCK_CONTROL				||	// 0x11
		iopb->MajorFunction == IRP_MJ_CLEANUP					||	// 0x12
		iopb->MajorFunction == IRP_MJ_QUERY_SECURITY			||	// 0x14
		iopb->MajorFunction == IRP_MJ_SET_SECURITY				||	// 0x15
		iopb->MajorFunction == IRP_MJ_QUERY_QUOTA				||	// 0x19
		iopb->MajorFunction == IRP_MJ_SET_QUOTA) {					// 0x1a
			
	} else if (iopb->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) {

		if (iopb->MinorFunction == IRP_MN_MOUNT_VOLUME		||
			iopb->MinorFunction == IRP_MN_VERIFY_VOLUME	||
			iopb->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM) {
		
			NDASFS_ASSERT( LFS_UNEXPECTED );
			ASSERT( Secondary_LookUpFileExtension(Secondary, fileObject) == NULL );

			PrintData( LFS_DEBUG_SECONDARY_TRACE, "Secondary_PassThrough", Secondary->LfsDeviceExt, Irp );

			Secondary_Dereference( Secondary );
			return FLT_PREOP_SUCCESS_NO_CALLBACK;
		}
	
	} else if (iopb->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL	|| 	// 0x0f
			   iopb->MajorFunction == IRP_MJ_SHUTDOWN					||  // 0x10
			   iopb->MajorFunction == IRP_MJ_CREATE_MAILSLOT			||  // 0x13
			   iopb->MajorFunction == IRP_MJ_POWER						||  // 0x16
			   iopb->MajorFunction == IRP_MJ_SYSTEM_CONTROL			||  // 0x17
			   iopb->MajorFunction == IRP_MJ_DEVICE_CHANGE) {				// 0x18
	
		NDASFS_ASSERT( LFS_REQUIRED );
		PrintData( LFS_DEBUG_SECONDARY_TRACE, "Secondary_PassThrough", Secondary->LfsDeviceExt, Irp );

		Secondary_Dereference( Secondary );

		return FLT_PREOP_SUCCESS_NO_CALLBACK;

	} else if (iopb->MajorFunction == IRP_MJ_DEVICE_CONTROL) {

		PFILE_EXTENTION	fileExt = NULL;

		fileExt = Secondary_LookUpFileExtension(Secondary, fileObject);
		
		if (fileExt == NULL || fileExt->TypeOfOpen != UserVolumeOpen) {

			Secondary_Dereference( Secondary );

			Data->IoStatus.Status = STATUS_INVALID_PARAMETER;
			Data->IoStatus.Information = 0;

			return FLT_PREOP_COMPLETE;
		}

		status = MiniSecondary_Ioctl( Secondary, Data );

		Secondary_Dereference( Secondary );

		return status;	

	} else {

		NDASFS_ASSERT( LFS_UNEXPECTED );

		Secondary_Dereference( Secondary );
		return FLT_PREOP_SUCCESS_NO_CALLBACK;
	}		

	PrintData( LFS_DEBUG_SECONDARY_TRACE, "Secondary_PassThrough", Secondary->LfsDeviceExt, Irp );
	
	if (Secondary->Thread.SessionStatus == STATUS_DISK_CORRUPT_ERROR) {

		NDASFS_ASSERT( Secondary_LookUpFileExtension(Secondary, fileObject) == NULL );

		if (iopb->MajorFunction == IRP_MJ_CLOSE) {

			if (Secondary_LookUpFileExtension(Secondary, fileObject)) {

				SecondaryFileObjectClose( Secondary, fileObject );
			}

			Data->IoStatus.Status = STATUS_SUCCESS;
			Data->IoStatus.Information = 0;

		} else if (iopb->MajorFunction == IRP_MJ_CLEANUP) {

			InterlockedDecrement( &((PLFS_FCB)iopb->TargetFileObject->FsContext)->UncleanCount );
			SetFlag( fileObject->Flags, FO_CLEANUP_COMPLETE );

			Data->IoStatus.Status = STATUS_SUCCESS;
			Data->IoStatus.Information = 0;

		} else {

			Data->IoStatus.Status = STATUS_DISK_CORRUPT_ERROR;
			Data->IoStatus.Information = 0;
		}

		Secondary_Dereference( Secondary );
		
		return FLT_PREOP_COMPLETE;
	} 
	
	if (Secondary->Thread.SessionStatus == STATUS_UNRECOGNIZED_VOLUME) {

		NDASFS_ASSERT( Secondary_LookUpFileExtension(Secondary, fileObject) == NULL );

		if (iopb->MajorFunction == IRP_MJ_CLOSE) {

			if (Secondary_LookUpFileExtension(Secondary, fileObject)) {

				SecondaryFileObjectClose( Secondary, fileObject );
			}

			Data->IoStatus.Status = STATUS_SUCCESS;
			Data->IoStatus.Information = 0;

		} else if (iopb->MajorFunction == IRP_MJ_CLEANUP) {

			InterlockedDecrement( &((PLFS_FCB)iopb->TargetFileObject->FsContext)->UncleanCount );
			SetFlag( fileObject->Flags, FO_CLEANUP_COMPLETE );

			Data->IoStatus.Status = STATUS_SUCCESS;
			Data->IoStatus.Information = 0;

		} else {

			Data->IoStatus.Status = STATUS_DISK_CORRUPT_ERROR;
			Data->IoStatus.Information = 0;
		}

		Secondary_Dereference( Secondary );

		return FLT_PREOP_COMPLETE;
	}

	while (1) {

		NDASFS_ASSERT( fastMutexSet == FALSE );
		NDASFS_ASSERT( retry == FALSE );

		ExAcquireFastMutex( &Secondary->FastMutex );

		if (FlagOn(Secondary->Flags, SECONDARY_FLAG_CLOSED)) {

			SPY_LOG_PRINT( LFS_DEBUG_SECONDARY_ERROR, 
						   ("Secondary is already closed Secondary = %p\n", Secondary) );

			ExReleaseFastMutex( &Secondary->FastMutex );

			NDASFS_ASSERT( iopb->MajorFunction == IRP_MJ_CREATE );

			if (iopb->MajorFunction == IRP_MJ_CLOSE) {

				if (Secondary_LookUpFileExtension(Secondary, fileObject)) {

					SecondaryFileObjectClose( Secondary, fileObject );
				}

				Data->IoStatus.Status = STATUS_SUCCESS;
				Data->IoStatus.Information = 0;

			} else if (iopb->MajorFunction == IRP_MJ_CLEANUP) {

				InterlockedDecrement( &((PLFS_FCB)iopb->TargetFileObject->FsContext)->UncleanCount );
				SetFlag( fileObject->Flags, FO_CLEANUP_COMPLETE );

				Data->IoStatus.Status = STATUS_SUCCESS;
				Data->IoStatus.Information = 0;

			} else {

				Data->IoStatus.Status = STATUS_TOO_LATE;
				Data->IoStatus.Information = 0;
			}

			status = FLT_PREOP_COMPLETE;
			break;
		}

		if (FlagOn(Secondary->Flags, SECONDARY_FLAG_ERROR)) {

			ExReleaseFastMutex( &Secondary->FastMutex );

			if (iopb->MajorFunction == IRP_MJ_CLOSE) {

				if (Secondary_LookUpFileExtension(Secondary, fileObject)) {

					SecondaryFileObjectClose( Secondary, fileObject );
				}

				Data->IoStatus.Status = STATUS_SUCCESS;
				Data->IoStatus.Information = 0;

			} else if (iopb->MajorFunction == IRP_MJ_CREATE) {

				Data->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
				Data->IoStatus.Information = 0;
			
			} else if (iopb->MajorFunction == IRP_MJ_CLEANUP) {

				InterlockedDecrement( &((PLFS_FCB)iopb->TargetFileObject->FsContext)->UncleanCount );
				SetFlag( fileObject->Flags, FO_CLEANUP_COMPLETE );

				Data->IoStatus.Status = STATUS_SUCCESS;
				Data->IoStatus.Information = 0;

			} else {

				Data->IoStatus.Status = STATUS_FILE_CORRUPT_ERROR;
				Data->IoStatus.Information = 0;
			} 

			status = FLT_PREOP_COMPLETE;
			break;
		}
		
		ExReleaseFastMutex( &Secondary->FastMutex );

		if (!FlagOn(Secondary->Flags, SECONDARY_FLAG_RECONNECTING)) {

			NDASFS_ASSERT( Secondary->ThreadObject );
		}

		KeEnterCriticalRegion();
		status = MiniRedirectIrp( Secondary, Data, &fastMutexSet, &retry );
		KeLeaveCriticalRegion();

		if (retry == TRUE) {

			retry = FALSE;
			continue;
		}

		if (status == STATUS_SUCCESS) {

			NDASFS_ASSERT( fastMutexSet == FALSE );

			if (Data->IoStatus.Status == STATUS_PENDING) {

				NDASFS_ASSERT( LFS_BUG );
			}

			status = FLT_PREOP_COMPLETE;
			break;	
		} 
		
		if (status == STATUS_DEVICE_REQUIRES_CLEANING) {

			PrintData( LFS_DEBUG_LFS_INFO, 
					  "STATUS_DEVICE_REQUIRES_CLEANING", 
					  CONTAINING_RECORD(Secondary, LFS_DEVICE_EXTENSION, Secondary), 
					  Irp );

			if (iopb->MajorFunction == IRP_MJ_CLEANUP) {

				InterlockedDecrement( &((PLFS_FCB)iopb->TargetFileObject->FsContext)->UncleanCount );
				SetFlag( fileObject->Flags, FO_CLEANUP_COMPLETE );

				Data->IoStatus.Status = STATUS_SUCCESS;
				Data->IoStatus.Information = 0;

			} else {
			
				Data->IoStatus.Status = STATUS_ACCESS_DENIED;
				Data->IoStatus.Information = 0;
			}

			status = FLT_PREOP_COMPLETE;
			break;
		} 
		
		if (status == STATUS_ALERTED || status == STATUS_USER_APC) {

			NDASFS_ASSERT( fastMutexSet == FALSE );
			continue;		
		} 

		NDASFS_ASSERT( status == STATUS_REMOTE_DISCONNECT || status == STATUS_IO_DEVICE_ERROR );
		NDASFS_ASSERT( fastMutexSet == TRUE );

		ExAcquireFastMutex( &Secondary->FastMutex );

		ASSERT( FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) );

		if (Secondary->LfsDeviceExt->SecondaryState == CONNECTED_TO_LOCAL_STATE		|| 
			FlagOn(Secondary->LfsDeviceExt->Flags, LFS_DEVICE_FLAG_SURPRISE_REMOVED)		||
			GlobalLfs.ShutdownOccured == TRUE) {

			SetFlag( Secondary->Flags, SECONDARY_FLAG_ERROR );
			ExReleaseFastMutex( &Secondary->FastMutex );

			KeReleaseSemaphore( &Secondary->Semaphore, IO_NO_INCREMENT, 1, FALSE );
			fastMutexSet = FALSE;

			Data->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
			Data->IoStatus.Information = 0;
	
			status = FLT_PREOP_COMPLETE;
			break;
		}

		if (FlagOn(Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

			//BOOLEAN			recoveryResult;

			ASSERT( !FlagOn(Secondary->Flags, SECONDARY_FLAG_RECONNECTING) );
			SetFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

			ExReleaseFastMutex( &Secondary->FastMutex );

			if (FlagOn(Secondary->Flags, SECONDARY_FLAG_CLOSED)) {

				ASSERT( iopb->MajorFunction == IRP_MJ_CREATE );
					
				SPY_LOG_PRINT( LFS_DEBUG_SECONDARY_ERROR, 
							   ("Secondary is already closed Secondary = %p\n", Secondary) );

				ClearFlag( Secondary->Flags, SECONDARY_FLAG_RECONNECTING );

				KeReleaseSemaphore( &Secondary->Semaphore, IO_NO_INCREMENT, 1, FALSE );

				continue;
			}

			CallRecoverySessionAsynchronously( Secondary );
			fastMutexSet = FALSE;
				
			continue;
		}

		//
		//	Recovery failed.
		//

		SetFlag( Secondary->Flags, SECONDARY_FLAG_ERROR );
		ExReleaseFastMutex( &Secondary->FastMutex );

		KeReleaseSemaphore( &Secondary->Semaphore, IO_NO_INCREMENT, 1, FALSE );
		fastMutexSet = FALSE;

		NDASFS_ASSERT( IsListEmpty(&Secondary->RequestQueue) );

		continue;
	}

	NDASFS_ASSERT( fastMutexSet == FALSE );

	Secondary_Dereference( Secondary );

	NDASFS_ASSERT( status == FLT_PREOP_COMPLETE );

	return status;
}
Пример #25
0
// fdo pnp
NTSTATUS DoFdoPnP(PDEVICE_OBJECT pDevice,PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	PFdoExt pFdoExt = static_cast<PFdoExt>(pDevice->DeviceExtension);

	// nead call next driver
	BOOLEAN bCallNext = TRUE;

	PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);

	// inc io count
	IncIoCount(pFdoExt);

	// save minor code
	UCHAR uMinorCode = pIoStack->MinorFunction;

	switch(uMinorCode)
	{
	case IRP_MN_START_DEVICE:
		{
			// send down first
			status = SendIrpToLowerDeviceSyn(pFdoExt->m_pLowerDevice,pIrp);
			if(NT_SUCCESS(status))
			{
				// set device power state
				pFdoExt->m_devPowerState = PowerDeviceD0;
				POWER_STATE state;
				state.DeviceState = PowerDeviceD0;
				PoSetPowerState(pDevice,DevicePowerState,state);

				// set device interface state
				status = IoSetDeviceInterfaceState(&pFdoExt->m_symbolicName,TRUE);

				// set device pnp state
				SetNewPnpState(pFdoExt,IRP_MN_START_DEVICE);
			}

			// complete the irp
			pIrp->IoStatus.Status = status;
			IoCompleteRequest(pIrp,IO_NO_INCREMENT);

			// do not call down the device stack
			bCallNext = FALSE;
		}
		break;

		// set pnp state directly
	case IRP_MN_QUERY_REMOVE_DEVICE:
	case IRP_MN_QUERY_STOP_DEVICE:
		SetNewPnpState(pFdoExt,uMinorCode);
		break;

		// check for current pnp state,and restore it
	case IRP_MN_CANCEL_REMOVE_DEVICE:
		if(pFdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_REMOVE_DEVICE)
			RestorePnpState(pFdoExt);

		break;

		// the same
	case IRP_MN_CANCEL_STOP_DEVICE:
		if(pFdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_STOP_DEVICE)
			RestorePnpState(pFdoExt);

		break;

		// remove
	case IRP_MN_REMOVE_DEVICE:
		{
			// normal remove
			if(pFdoExt->m_ulCurrentPnpState != IRP_MN_SURPRISE_REMOVAL)
			{
				// just stop device interface
				if(pFdoExt->m_symbolicName.Buffer)
				{
					// set device interface false
					IoSetDeviceInterfaceState(&pFdoExt->m_symbolicName,FALSE);

					RtlFreeUnicodeString(&pFdoExt->m_symbolicName);
				}
			}

			// update pnp state
			SetNewPnpState(pFdoExt,IRP_MN_REMOVE_DEVICE);

			// dec outstandingio by 2
			DecIoCount(pFdoExt);

			DecIoCount(pFdoExt);

			// wait other irps finish
			KeWaitForSingleObject(&pFdoExt->m_evRemove,Executive,KernelMode,FALSE,NULL);

			// check pdo
			ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo);

			// if the pdo is present
			if(pFdoExt->m_pEnumPdo)
			{
				PPdoExt pPdoExt = static_cast<PPdoExt>(pFdoExt->m_pEnumPdo->DeviceExtension);

				// surprise removal.update those field
				if(pPdoExt->m_ulCurrentPnpState == IRP_MN_SURPRISE_REMOVAL)
				{
					pPdoExt->m_pParentFdo = NULL;
					pPdoExt->m_bReportMissing = TRUE;
					pFdoExt->m_pEnumPdo = NULL;
				}

				// delete the pdo device
				IoDeleteDevice(pFdoExt->m_pEnumPdo);
			}

			ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);

			pIrp->IoStatus.Status = STATUS_SUCCESS;

			// call next driver,do not need to wait the finish
			IoSkipCurrentIrpStackLocation(pIrp);
			status = IoCallDriver(pFdoExt->m_pLowerDevice,pIrp);

			// first detach it from the device stack
			IoDetachDevice(pFdoExt->m_pLowerDevice);

			// then delete it,note that the device extension will become invalid,so dec need to check the minor code carefully
			IoDeleteDevice(pDevice);

			bCallNext = FALSE;
		}
		break;

		// stop
	case IRP_MN_STOP_DEVICE:
		DecIoCount(pFdoExt);

		KeWaitForSingleObject(&pFdoExt->m_evStop,Executive,KernelMode,FALSE,NULL);

		IncIoCount(pFdoExt);

		SetNewPnpState(pFdoExt,IRP_MN_STOP_DEVICE);
		break;
	
		// query bus relations
	case IRP_MN_QUERY_DEVICE_RELATIONS:
		{
			// only care bus relations
			if (BusRelations != pIoStack->Parameters.QueryDeviceRelations.Type) 
			{
				/*switch(pIoStack->Parameters.QueryDeviceRelations.Type)
				{
				case EjectionRelations:
					devDebugPrint("\tquery EjectionRelations\n");
					break;
				case PowerRelations:
					devDebugPrint("\tquery PowerRelations\n");
					break;
				case RemovalRelations:
					devDebugPrint("\tquery RemovalRelations\n");
					break;
				case TargetDeviceRelation:
					devDebugPrint("\tquery TargetDeviceRelation\n");
					break;
				case SingleBusRelations:
					devDebugPrint("\tquery SingleBusRelations\n");
					break;
				}*/
				
				break;
			}

			// old relations
			PDEVICE_RELATIONS pOldRel = static_cast<PDEVICE_RELATIONS>(ULongToPtr(pIrp->IoStatus.Information));
			ULONG ulNewCount = 0;

			ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo);

			// no pdo
			if(!pFdoExt->m_pEnumPdo)
			{
				devDebugPrint("\tBusRelations no device plugin \n");
                ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);
				break;
			}
			
			PPdoExt pPdoExt = static_cast<PPdoExt>(pFdoExt->m_pEnumPdo->DeviceExtension);
			
			// if the pdo is not present
			if(!pPdoExt->m_bPresent)
			{
				// then we report it as missing
				pPdoExt->m_bReportMissing = TRUE;
			}
			else
			{
				// report the pdo
				ObReferenceObject(pFdoExt->m_pEnumPdo);
				ulNewCount ++;
			}

			// add the old count
			if(pOldRel)
				ulNewCount += pOldRel->Count;

			// allocate paged memory
			ULONG len = sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (ulNewCount - 1);
			PDEVICE_RELATIONS pRel = static_cast<PDEVICE_RELATIONS>(ExAllocatePoolWithTag(PagedPool,len,'suBT'));

			// do not set the status,we should continue with the orignal devices that the upper devices reported
			if(!pRel)
				break;

			// copy old value
			if(pOldRel)
			{
				RtlCopyMemory(pRel,pOldRel,len - sizeof(PDEVICE_OBJECT));
				if(pPdoExt->m_bPresent)
					pRel->Objects[pOldRel->Count] = pFdoExt->m_pEnumPdo;

				// free the previous buffer
				ExFreePool(pOldRel);
			}
			else
			{
				// the device is present
				if(pPdoExt->m_bPresent)
					pRel->Objects[0] = pFdoExt->m_pEnumPdo;
			}

			pRel->Count = ulNewCount;

			pIrp->IoStatus.Information = PtrToUlong(pRel);

			devDebugPrint("\tBusRelations pdo present %d,report %d\n",pPdoExt->m_bPresent,ulNewCount);

			ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);
		}
		break;

		// surprise removal
	case IRP_MN_SURPRISE_REMOVAL:
		{
			// set pnp state
			SetNewPnpState(pFdoExt,IRP_MN_SURPRISE_REMOVAL);

			// stop the fdo
			if(pFdoExt->m_symbolicName.Buffer)
			{
				// set device interface
				IoSetDeviceInterfaceState(&pFdoExt->m_symbolicName,FALSE);

				RtlFreeUnicodeString(&pFdoExt->m_symbolicName);
			}

			// update pdo's field
			ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo);
			PPdoExt pPdoExt = static_cast<PPdoExt>(pFdoExt->m_pEnumPdo->DeviceExtension);
			pPdoExt->m_pParentFdo = NULL;
			pPdoExt->m_bReportMissing = TRUE;
			ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo);
		}
		break;

	default:
		status = pIrp->IoStatus.Status;
		break;
	}

	// nead call lower device
	if(bCallNext)
	{
		pIrp->IoStatus.Status = status;
		IoSkipCurrentIrpStackLocation(pIrp);
		status = IoCallDriver(pFdoExt->m_pLowerDevice,pIrp);
	}
	
	// specail check for remove irp
	if(uMinorCode != IRP_MN_REMOVE_DEVICE)
		DecIoCount(pFdoExt);

	return status;
}
Пример #26
0
NTSTATUS
File_UpdateEntireFileByFileObject(
	__in PFLT_CALLBACK_DATA Data,
	__in PFLT_RELATED_OBJECTS FltObjects,
	__in PFILE_OBJECT FileObject, 
	__in PSTREAM_CONTEXT pStreamCtx,
	__in PVOLUME_CONTEXT pVolCtx
	)
{
	NTSTATUS status = STATUS_SUCCESS ;
	PUCHAR Buffer = NULL ;
	LARGE_INTEGER ReadWriteOffset = {0} ;
	BOOLEAN EndOfFile = FALSE;
	ULONG uReadBytes = 0 ;
	ULONG uWriteBytes = 0 ;
	ULONG uAllocateBufferSize = 1024*64 ; 
	ULONG uReadWriteLength = 0 ;
	ULONG uOffset = 0 ;
	LARGE_INTEGER FileSize = {0} ;
	PFILE_FLAG psFileFlag = NULL ;
	KIRQL OldIrql ;

	try{

		//判断分配空间长度是否SectorSize对齐
		if ((uAllocateBufferSize % pVolCtx->SectorSize) != 0)
		{//由于SectorSize目前为512bytes,故暂时先返回失败,以后可以对AllocateBufferSize进行调整
			status = ERR_CORE_LENGTH_NOT_ALIGNED ;
			__leave ;
		}

		Buffer = FltAllocatePoolAlignedWithTag(FltObjects->Instance,PagedPool, uAllocateBufferSize, FILEFLAG_POOL_TAG);
		if (!Buffer)
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave ;
		}

             //allocate local file flag buffer
		psFileFlag = (PFILE_FLAG)ExAllocatePoolWithTag(NonPagedPool, FILE_FLAG_LENGTH, FILEFLAG_POOL_TAG) ;
		if (NULL == psFileFlag)
		{
			status = STATUS_INSUFFICIENT_RESOURCES ;
			__leave ;
		}
		RtlCopyMemory(psFileFlag, g_psFileFlag, FILE_FLAG_LENGTH) ; //实际上这里应该是当前文件自身的flag

        //set current file size into file flag buffer
        File_GetFileSize(Data, FltObjects, &FileSize) ;
		psFileFlag->FileValidLength= FileSize.QuadPart ;

		//calculate padded file size
		if (FileSize.QuadPart % SECTOR_SIZE)
		{//file size is not multiply of sector size
			FileSize.QuadPart = FileSize.QuadPart + (SECTOR_SIZE - FileSize.QuadPart % SECTOR_SIZE) + FILE_FLAG_LENGTH ;
		}
		else
		{//file size is multiply of sector size
			FileSize.QuadPart += FILE_FLAG_LENGTH ;
		}
		RtlCopyMemory(psFileFlag->FileKeyHash, pStreamCtx->szKeyHash, HASH_SIZE) ;
		

		while (TRUE)
		{
			status = File_ReadWriteFile(IRP_MJ_READ, 
										FltObjects->Instance, 
										FileObject, 
										&ReadWriteOffset,
										uAllocateBufferSize, 
										Buffer, 
										&uReadBytes,
										FLTFL_IO_OPERATION_NON_CACHED|FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET) ;
			if (!NT_SUCCESS(status))
				break;

			if (0 == uReadBytes)
				break;

			if (KeGetCurrentIrql() > PASSIVE_LEVEL)
				ExAcquireSpinLock(&pVolCtx->FsCryptSpinLock, &OldIrql);
			else
				ExAcquireFastMutex(&pVolCtx->FsCtxTableMutex) ;
			///if (data_crypt(pVolCtx->aes_ctr_ctx, Buffer, uOffset, uReadBytes))
			///{
			///	if (KeGetCurrentIrql() > PASSIVE_LEVEL)
			///		ExReleaseSpinLock(&pVolCtx->FsCryptSpinLock, OldIrql) ;
			///	else
			///		ExReleaseFastMutex(&pVolCtx->FsCtxTableMutex) ;
			///	break ;
			///}
			if (KeGetCurrentIrql() > PASSIVE_LEVEL)
				ExReleaseSpinLock(&pVolCtx->FsCryptSpinLock, OldIrql) ;
			else
				ExReleaseFastMutex(&pVolCtx->FsCtxTableMutex) ;

			if (uReadBytes < uAllocateBufferSize)
				EndOfFile = TRUE;

			status = File_ReadWriteFile(IRP_MJ_WRITE, 
										FltObjects->Instance, 
										FileObject, 
										&ReadWriteOffset,
										uReadBytes, 
										Buffer, 
										&uWriteBytes,
										FLTFL_IO_OPERATION_NON_CACHED|FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET) ;
			if (!NT_SUCCESS(status))
				break;

			if (EndOfFile)
				break;
			
			uOffset += uAllocateBufferSize ;
			ReadWriteOffset.QuadPart += uAllocateBufferSize ;
			RtlZeroMemory(Buffer, uAllocateBufferSize) ;
		}

		// write file flag
		ReadWriteOffset.QuadPart = FileSize.QuadPart - FILE_FLAG_LENGTH ;
		File_ReadWriteFile(IRP_MJ_WRITE, 
						   FltObjects->Instance, 
						   FileObject, 
						   &ReadWriteOffset, 
						   FILE_FLAG_LENGTH, 
						   psFileFlag, 
						   &uWriteBytes,
						   FLTFL_IO_OPERATION_NON_CACHED|FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET) ;
		
	}
	finally{

		if (Buffer)
		{
			FltFreePoolAlignedWithTag(FltObjects->Instance, Buffer, FILEFLAG_POOL_TAG);
			Buffer = NULL ;
		}

		if (psFileFlag)
		{
			ExFreePoolWithTag(psFileFlag, FILEFLAG_POOL_TAG) ;
			psFileFlag = NULL ;
		}
	}

	return status;
}
Пример #27
0
VOID
ExSwapinWorkerThreads (
    IN BOOLEAN AllowSwap
    )

/*++

Routine Description:

    Sets the kernel stacks of the delayed worker threads to be swappable
    or pins them into memory.

Arguments:

    AllowSwap - Supplies TRUE if worker kernel stacks should be swappable,
                FALSE if not.

Return Value:

    None.

--*/

{
    PETHREAD         Thread;
    PETHREAD         CurrentThread;
    PEPROCESS        Process;
    KAPC             Apc;
    KEVENT           SwapSetEvent;

    PAGED_CODE();

    CurrentThread = PsGetCurrentThread();

    KeInitializeEvent (&SwapSetEvent,
                       NotificationEvent,
                       FALSE);

    Process = PsInitialSystemProcess;

    //
    // Serialize callers.
    //

    ExAcquireFastMutex (&ExpWorkerSwapinMutex);

    //
    // Stop new threads from swapping.
    //

    ExpWorkersCanSwap = AllowSwap;

    //
    // Stop existing worker threads from swapping.
    //

    for (Thread = PsGetNextProcessThread (Process, NULL);
         Thread != NULL;
         Thread = PsGetNextProcessThread (Process, Thread)) {

        //
        // Skip threads that are not worker threads or worker threads that
        // were permanently marked noswap at creation time.
        //

        if (Thread->ExWorkerCanWaitUser == 0) {
            continue;
        }

        if (Thread == CurrentThread) {

            //
            // No need to use an APC on the current thread.
            //

            KeSetKernelStackSwapEnable (AllowSwap);
        }
        else {

            //
            // Queue an APC to the thread, and wait for it to fire:
            //

            KeInitializeApc (&Apc,
                             &Thread->Tcb,
                             InsertApcEnvironment,
                             ExpSetSwappingKernelApc,
                             NULL,
                             NULL,
                             KernelMode,
                             &AllowSwap);

            if (KeInsertQueueApc (&Apc, &SwapSetEvent, NULL, 3)) {

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

                KeClearEvent(&SwapSetEvent);
            }
        }
    }

    ExReleaseFastMutex (&ExpWorkerSwapinMutex);
}
Пример #28
0
PVOID
ExAllocateFromPagedLookasideList(
    IN PPAGED_LOOKASIDE_LIST Lookaside
)

/*++

Routine Description:

    This function removes (pops) the first entry from the specified
    paged lookaside list.

Arguments:

    Lookaside - Supplies a pointer to a paged lookaside list structure.

Return Value:

    If an entry is removed from the specified lookaside list, then the
    address of the entry is returned as the function value. Otherwise,
    NULL is returned.

--*/

{

    PVOID Entry;

    Lookaside->L.TotalAllocates += 1;

#if !defined(_PPC_)

    if (Isx86FeaturePresent(KF_CMPXCHG8B)) {
        if ((Entry = ExInterlockedPopEntrySList(&Lookaside->L.ListHead,
                                                NULL)) == NULL) {

            Lookaside->L.AllocateMisses += 1;
            Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
                                            Lookaside->L.Size,
                                            Lookaside->L.Tag);
        }

        return Entry;
    }

#endif

    ExAcquireFastMutex(&Lookaside->Lock);
    Entry = PopEntryList(&Lookaside->L.ListHead.Next);
    if (Entry == NULL) {
        ExReleaseFastMutex(&Lookaside->Lock);
        Lookaside->L.AllocateMisses += 1;
        Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
                                        Lookaside->L.Size,
                                        Lookaside->L.Tag);

    } else {
        Lookaside->L.ListHead.Depth -= 1;
        ExReleaseFastMutex(&Lookaside->Lock);
    }

    return Entry;
}
Пример #29
0
VOID
VolDoThreadProc (
	IN	PVOLUME_DEVICE_OBJECT	VolDo
	)
{
	BOOLEAN		volDoThreadTerminate = FALSE;


	DebugTrace( 0, Dbg2, ("VolDoThreadProc: Start VolDo = %p\n", VolDo) );
	
	VolDo_Reference( VolDo );
	
	VolDo->Thread.Flags = VOLDO_THREAD_FLAG_INITIALIZING;

	ExAcquireFastMutex( &VolDo->FastMutex );		
	ClearFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_INITIALIZING );
	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_START );
	ExReleaseFastMutex( &VolDo->FastMutex );
			
	KeSetEvent( &VolDo->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	volDoThreadTerminate = FALSE;
	
	while (volDoThreadTerminate == FALSE) {

		PKEVENT			events[2];
		LONG			eventCount;
		NTSTATUS		eventStatus;
		LARGE_INTEGER	timeOut;
		

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;
		events[eventCount++] = &VolDo->RequestEvent;

		timeOut.QuadPart = -NDNTFS_VOLDO_THREAD_FLAG_TIME_OUT;

		eventStatus = KeWaitForMultipleObjects(	eventCount,
												events,
												WaitAny,
												Executive,
												KernelMode,
												TRUE,
												&timeOut,
												NULL );


		if (eventStatus == STATUS_TIMEOUT) {

			LARGE_INTEGER	currentTime;

			KeQuerySystemTime( &currentTime );

			if (FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN) || 
				!(FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_MOUNTED) /*&& !FlagOn(LfsDeviceExt->Flags, LFS_DEVICE_STOP)*/)) {
				
				continue;
			}

			if ((VolDo->NetdiskEnableMode == NETDISK_READ_ONLY && 
				 (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || 
				 (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_PURGE_DURATION)) ||

			    (VolDo->ReceiveWriteCommand == TRUE && 
				 (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || 
				 (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_FLUSH_DURATION))) {

				if (VolDo->NetdiskEnableMode != NETDISK_READ_ONLY && 
					(currentTime.QuadPart - VolDo->CommandReceiveTime.QuadPart) <=  NDNTFS_TRY_FLUSH_DURATION /*&& 
					(currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) <= (100*NDNTFS_TRY_FLUSH_OR_PURGE_DURATION)*/) {

					continue;
				}

				do {
				
					HANDLE					eventHandle = NULL;

					HANDLE					fileHandle = NULL;
					ACCESS_MASK				desiredAccess;
					ULONG					attributes;
					OBJECT_ATTRIBUTES		objectAttributes;
					IO_STATUS_BLOCK			ioStatusBlock;
					LARGE_INTEGER			allocationSize;
					ULONG					fileAttributes;
					ULONG					shareAccess;
				    ULONG					createDisposition;
					ULONG					createOptions;
				    PVOID					eaBuffer;
					ULONG					eaLength;

					NTSTATUS				createStatus;
					NTSTATUS				fileSystemControlStatus;

					PIRP					topLevelIrp;
					PRIMARY_REQUEST_INFO	primaryRequestInfo;


					ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

					if (VolDo->NetdiskEnableMode == NETDISK_SECONDARY) {

						break;
					}

					DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, VolDo->NetdiskPartitionInformation.VolumeName = %wZ\n", 
											VolDo, &VolDo->NetdiskPartitionInformation.VolumeName) );

					desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA 
									| FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA;

					ASSERT( desiredAccess == 0x0012019F );

					attributes  = OBJ_KERNEL_HANDLE;
					attributes |= OBJ_CASE_INSENSITIVE;

					InitializeObjectAttributes( &objectAttributes,
											    &VolDo->NetdiskPartitionInformation.VolumeName,
												attributes,
												NULL,
												NULL );
		
					allocationSize.LowPart  = 0;
					allocationSize.HighPart = 0;

					fileAttributes	  = 0;		
					shareAccess		  = FILE_SHARE_READ | FILE_SHARE_WRITE;
					createDisposition = FILE_OPEN;
					createOptions     = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE;
					eaBuffer		  = NULL;
					eaLength		  = 0;

					RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) );

					createStatus = ZwCreateFile( &fileHandle,
												 desiredAccess,
												 &objectAttributes,
												 &ioStatusBlock,
												 &allocationSize,
												 fileAttributes,
												 shareAccess,
												 createDisposition,
												 createOptions,
												 eaBuffer,
												 eaLength );

					if (createStatus != STATUS_SUCCESS) 
						break;
						
					ASSERT( ioStatusBlock.Information == FILE_OPENED);
	
					createStatus = ZwCreateEvent( &eventHandle,
												  GENERIC_READ,
												  NULL,
												  SynchronizationEvent,
												  FALSE );

					if (createStatus != STATUS_SUCCESS) {

						ASSERT( NDASNTFS_UNEXPECTED );
						ZwClose( fileHandle );
						break;
					}

					primaryRequestInfo.PrimaryTag			  = 0xe2027482;
					primaryRequestInfo.PrimarySessionId		  = NDASNTFS_LOCAL_PRMARY_SESSION_ID;
					primaryRequestInfo.PrimarySession		  = NULL;
					primaryRequestInfo.NdfsWinxpRequestHeader = NULL;

					topLevelIrp = IoGetTopLevelIrp();
					ASSERT( topLevelIrp == NULL );
					IoSetTopLevelIrp( (PIRP)&primaryRequestInfo );

					RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) );

					fileSystemControlStatus = ZwFsControlFile( fileHandle,
															   NULL, //&eventHandle,
															   NULL,
															   NULL,
															   &ioStatusBlock,
															   (VolDo->NetdiskEnableMode == NETDISK_READ_ONLY) ?
																	FSCTL_NDAS_FS_PURGE : FSCTL_NDAS_FS_FLUSH,
															   NULL,
															   0,
															   NULL,
															   0 );

					DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, createStatus = %x, ioStatusBlock = %x\n", 
											VolDo, fileSystemControlStatus, ioStatusBlock.Information) );

					if (fileSystemControlStatus == STATUS_PENDING) {
			
						LARGE_INTEGER			timeOut;
			
						timeOut.QuadPart = -3*NANO100_PER_SEC;

						ASSERT( FALSE );
						//fileSystemControlStatus = ZwWaitForSingleObject( eventHandle, TRUE,NULL /*, &timeOut*/ );
					}

					IoSetTopLevelIrp( topLevelIrp );

					if (fileSystemControlStatus != STATUS_SUCCESS)
						DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, fileSystemControlStatus = %x, ioStatusBlock = %x\n", 
												VolDo, fileSystemControlStatus, ioStatusBlock.Information) );

					ZwClose( eventHandle );
					ZwClose( fileHandle );
					
					break;
				
				} while (0);

				KeQuerySystemTime( &VolDo->TryFlushOrPurgeTime );
				VolDo->ReceiveWriteCommand = FALSE;
			}

			continue;
		}
		
		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
		ASSERT( eventCount < THREAD_WAIT_OBJECTS );
		
		if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) {

			ASSERT( NDASNTFS_UNEXPECTED );
			SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_ERROR );
			volDoThreadTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			volDoThreadTerminate = TRUE;
			break;
		
		} else {

			NDAS_ASSERT( NDASNTFS_BUG );
		}
	}

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	ExAcquireFastMutex( &VolDo->FastMutex );

	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_STOPED );

	ExReleaseFastMutex( &VolDo->FastMutex );

	DebugTrace( 0, Dbg2, ("VolDoThreadProc: PsTerminateSystemThread VolDo = %p\n", VolDo) );
	
	ExAcquireFastMutex( &VolDo->FastMutex );
	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_TERMINATED );
	ExReleaseFastMutex( &VolDo->FastMutex );
	
	VolDo_Dereference( VolDo );

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
	
	PsTerminateSystemThread( STATUS_SUCCESS );
}
Пример #30
0
NTSTATUS
NTAPI
MmpPageOutPhysicalAddress(PFN_NUMBER Page)
{
    BOOLEAN ProcRef = FALSE, PageDirty;
    PFN_NUMBER SectionPage = 0;
    PMM_RMAP_ENTRY entry;
    PMM_SECTION_SEGMENT Segment = NULL;
    LARGE_INTEGER FileOffset;
    PMEMORY_AREA MemoryArea;
    PMMSUPPORT AddressSpace = NULL;
    BOOLEAN Dirty = FALSE;
    PVOID Address = NULL;
    PEPROCESS Process = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    MM_REQUIRED_RESOURCES Resources = { 0 };

    DPRINTC("Page out %x (ref ct %x)\n", Page, MmGetReferenceCountPage(Page));

    ExAcquireFastMutex(&MiGlobalPageOperation);
    if ((Segment = MmGetSectionAssociation(Page, &FileOffset)))
    {
        DPRINTC("Withdrawing page (%x) %p:%x\n",
                Page,
                Segment,
                FileOffset.LowPart);

        SectionPage = MmWithdrawSectionPage(Segment, &FileOffset, &Dirty);
        DPRINTC("SectionPage %x\n", SectionPage);

        if (SectionPage == MM_WAIT_ENTRY || SectionPage == 0)
        {
            DPRINT1("In progress page out %x\n", SectionPage);
            ExReleaseFastMutex(&MiGlobalPageOperation);
            return STATUS_UNSUCCESSFUL;
        }
        else
        {
            ASSERT(SectionPage == Page);
        }
        Resources.State = Dirty ? 1 : 0;
    }
    else
    {
        DPRINT("No segment association for %x\n", Page);
    }

    Dirty = MmIsDirtyPageRmap(Page);

    DPRINTC("Trying to unmap all instances of %x\n", Page);
    ExAcquireFastMutex(&RmapListLock);
    entry = MmGetRmapListHeadPage(Page);

    // Entry and Segment might be null here in the case that the page
    // is new and is in the process of being swapped in
    if (!entry && !Segment)
    {
        Status = STATUS_UNSUCCESSFUL;
        DPRINT1("Page %x is in transit\n", Page);
        ExReleaseFastMutex(&RmapListLock);
        goto bail;
    }

    while (entry != NULL && NT_SUCCESS(Status))
    {
        Process = entry->Process;
        Address = entry->Address;

        DPRINTC("Process %p Address %p Page %x\n", Process, Address, Page);

        if (RMAP_IS_SEGMENT(Address))
        {
            entry = entry->Next;
            continue;
        }

        if (Process && Address < MmSystemRangeStart)
        {
            /* Make sure we don't try to page out part of an exiting process */
            if (PspIsProcessExiting(Process))
            {
                DPRINT("bail\n");
                ExReleaseFastMutex(&RmapListLock);
                goto bail;
            }
            ObReferenceObject(Process);
            ProcRef = TRUE;
            AddressSpace = &Process->Vm;
        }
        else
        {
            AddressSpace = MmGetKernelAddressSpace();
        }
        ExReleaseFastMutex(&RmapListLock);

        RtlZeroMemory(&Resources, sizeof(Resources));

        if ((((ULONG_PTR)Address) & 0xFFF) != 0)
        {
            KeBugCheck(MEMORY_MANAGEMENT);
        }

        do
        {
            MmLockAddressSpace(AddressSpace);

            MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
            if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
            {
                Status = STATUS_UNSUCCESSFUL;
                MmUnlockAddressSpace(AddressSpace);
                DPRINTC("bail\n");
                goto bail;
            }

            DPRINTC("Type %x (%p -> %p)\n",
                    MemoryArea->Type,
                    MemoryArea->StartingAddress,
                    MemoryArea->EndingAddress);

            Resources.DoAcquisition = NULL;
            Resources.Page[0] = Page;

            ASSERT(KeGetCurrentIrql() <= APC_LEVEL);

            DPRINT("%p:%p, page %x %x\n",
                   Process,
                   Address,
                   Page,
                   Resources.Page[0]);

            PageDirty = FALSE;

            Status = MmPageOutCacheSection(AddressSpace,
                                           MemoryArea,
                                           Address,
                                           &PageDirty,
                                           &Resources);

            Dirty |= PageDirty;
            DPRINT("%x\n", Status);

            ASSERT(KeGetCurrentIrql() <= APC_LEVEL);

            MmUnlockAddressSpace(AddressSpace);

            if (Status == STATUS_SUCCESS + 1)
            {
                // Wait page ... the other guy has it, so we'll just fail for now
                DPRINT1("Wait entry ... can't continue\n");
                Status = STATUS_UNSUCCESSFUL;
                goto bail;
            }
            else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
            {
                DPRINTC("DoAcquisition %p\n", Resources.DoAcquisition);

                Status = Resources.DoAcquisition(AddressSpace,
                                                 MemoryArea,
                                                 &Resources);

                DPRINTC("Status %x\n", Status);
                if (!NT_SUCCESS(Status))
                {
                    DPRINT1("bail\n");
                    goto bail;
                }
                else
                {
                    Status = STATUS_MM_RESTART_OPERATION;
                }
            }
        }
        while (Status == STATUS_MM_RESTART_OPERATION);

        if (ProcRef)
        {
            ObDereferenceObject(Process);
            ProcRef = FALSE;
        }

        ExAcquireFastMutex(&RmapListLock);
        ASSERT(!MM_IS_WAIT_PTE(MmGetPfnForProcess(Process, Address)));
        entry = MmGetRmapListHeadPage(Page);

        DPRINTC("Entry %p\n", entry);
    }

    ExReleaseFastMutex(&RmapListLock);

bail:
    DPRINTC("BAIL %x\n", Status);

    if (Segment)
    {
        ULONG RefCount;

        DPRINTC("About to finalize section page %x (%p:%x) Status %x %s\n",
                Page,
                Segment,
                FileOffset.LowPart,
                Status,
                Dirty ? "dirty" : "clean");

        if (!NT_SUCCESS(Status) ||
            !NT_SUCCESS(Status = MmFinalizeSectionPageOut(Segment,
                                                          &FileOffset,
                                                          Page,
                                                          Dirty)))
        {
            DPRINTC("Failed to page out %x, replacing %x at %x in segment %x\n",
                    SectionPage,
                    FileOffset.LowPart,
                    Segment);

            MmLockSectionSegment(Segment);

            MmSetPageEntrySectionSegment(Segment,
                                         &FileOffset,
                                         Dirty ? MAKE_PFN_SSE(Page) : DIRTY_SSE(MAKE_PFN_SSE(Page)));

            MmUnlockSectionSegment(Segment);
        }

        /* Alas, we had the last reference */
        if ((RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
            MmFinalizeSegment(Segment);
    }

    if (ProcRef)
    {
        DPRINTC("Dereferencing process...\n");
        ObDereferenceObject(Process);
    }

    ExReleaseFastMutex(&MiGlobalPageOperation);

    DPRINTC("%s %x %x\n",
            NT_SUCCESS(Status) ? "Evicted" : "Spared",
            Page,
            Status);

    return NT_SUCCESS(Status) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
}