Example #1
0
NTSTATUS DPBitmapInit(
	DP_BITMAP **     bitmap,
	unsigned long       sectorSize,
	unsigned long       byteSize,
	unsigned long       regionSize,
	unsigned long       regionNumber
	)
{
	int i = 0;
	DP_BITMAP * myBitmap = NULL;
	NTSTATUS status = STATUS_SUCCESS;

	//检查参数,以免使用了错误的参数导致发生处零错等错误
	if (NULL == bitmap || 0 == sectorSize ||
		0 == byteSize || 0 == regionSize  || 0 == regionNumber)
	{
		return STATUS_UNSUCCESSFUL;
	}
	__try
	{
		//分配一个bitmap结构,这是无论如何都要分配的,这个结构相当于一个bitmap的handle	
		if (NULL == (myBitmap = (DP_BITMAP*)DPBitmapAlloc(0, sizeof(DP_BITMAP))))
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}
		//清空结构
		memset(myBitmap, 0, sizeof(DP_BITMAP));
		//根据参数对结构中的成员进行赋值
		myBitmap->sectorSize = sectorSize;
		myBitmap->byteSize = byteSize;
		myBitmap->regionSize = regionSize;
		myBitmap->regionNumber = regionNumber;
		myBitmap->regionReferSize = sectorSize * byteSize * regionSize;
		myBitmap->bitmapReferSize = (__int64)sectorSize * (__int64)byteSize * (__int64)regionSize * (__int64)regionNumber;
		//分配出regionNumber那么多个指向region的指针,这是一个指针数组
		if (NULL == (myBitmap->Bitmap = (tBitmap **)DPBitmapAlloc(0, sizeof(tBitmap*) * regionNumber)))
		{
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}
		//清空指针数组
		memset(myBitmap->Bitmap, 0, sizeof(tBitmap*) * regionNumber);
		* bitmap = myBitmap;
		status = STATUS_SUCCESS;
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		status = STATUS_UNSUCCESSFUL;
	}
	if (!NT_SUCCESS(status))
	{
		if (NULL != myBitmap)
		{
			DPBitmapFree(myBitmap);
		}
		* bitmap = NULL;
	}
	return status;
}
Example #2
0
NTSTATUS	
DPDispatchPnp(
	IN	PDEVICE_OBJECT	DeviceObject,
	IN	PIRP			Irp
	)
{
	//用来指向过滤设备的设备扩展的指针
	PDP_FILTER_DEV_EXTENSION	DevExt = DeviceObject->DeviceExtension;
	//返回值
	NTSTATUS ntStatus = STATUS_SUCCESS;
	//用来指向irp stack的指针
	PIO_STACK_LOCATION  irpsp = IoGetCurrentIrpStackLocation(Irp);

	switch(irpsp->MinorFunction) 
	{
	case IRP_MN_REMOVE_DEVICE:
		//如果是PnP manager发过来的移除设备的irp,将进入这里
		{
			//这里主要做一些清理工作
			if (DevExt->ThreadTermFlag != TRUE && NULL != DevExt->ThreadHandle)
			{
				//如果线程还在运行的话需要停止它,这里通过设置线程停止运行的标志并且发送事件信息,让线程自己终止运行
				DevExt->ThreadTermFlag = TRUE;
				KeSetEvent(
					&DevExt->ReqEvent,
					(KPRIORITY) 0,
					FALSE
					);
				//等待线程结束
				KeWaitForSingleObject(
					DevExt->ThreadHandle,
					Executive,
					KernelMode,
					FALSE,
					NULL
					);
				//解除引用线程对象
				ObDereferenceObject(DevExt->ThreadHandle);
			}
	 		if (NULL != DevExt->Bitmap)
	 		{
				//如果还有位图,就释放
	 			DPBitmapFree(DevExt->Bitmap);
	 		}
			if (NULL != DevExt->LowerDevObj)
			{
				//如果存在着下层设备,就先去掉挂接
				IoDetachDevice(DevExt->LowerDevObj);
			}
	 		if (NULL != DevExt->FltDevObj)
	 		{
				//如果存在过滤设备,就要删除它
	 			IoDeleteDevice(DevExt->FltDevObj);
	 		}
			break;
		}
	//这个是PnP 管理器用来询问设备能否支持特殊文件的irp,作为卷的过滤驱动,我们必须处理
	case IRP_MN_DEVICE_USAGE_NOTIFICATION:
		{
			BOOLEAN setPagable;
			//如果是询问是否支持休眠文件和dump文件,则直接下发给下层设备去处理
			if (irpsp->Parameters.UsageNotification.Type != DeviceUsageTypePaging) 
			{
				ntStatus = DPSendToNextDriver(
					DevExt->LowerDevObj,
					Irp);
				return ntStatus; 
			}
			//这里等一下分页计数事件
			ntStatus = KeWaitForSingleObject(
				&DevExt->PagingPathCountEvent,
				Executive, 
				KernelMode,
				FALSE, 
				NULL);

			//setPagable初始化为假,是没有设置过DO_POWER_PAGABLE的意思
			setPagable = FALSE;
			if (!irpsp->Parameters.UsageNotification.InPath &&
				DevExt->PagingPathCount == 1 ) 
			{
				//如果是PnP manager通知我们将要删去分页文件,且我们目前只剩下最后一个分页文件的时候会进入这里
				if (DeviceObject->Flags & DO_POWER_INRUSH)
				{} 
				else 
				{
					//到这里说明没有分页文件在这个设备上了,需要设置DO_POWER_PAGABLE这一位了
					DeviceObject->Flags |= DO_POWER_PAGABLE;
					setPagable = TRUE;
				}
			}
			//到这里肯定是关于分页文件的是否可建立查询,或者是删除的通知,我们交给下层设备去做。这里需要用同步的方式给下层设备,也就是说要等待下层设备的返回
			ntStatus = DPForwardIrpSync(DevExt->LowerDevObj,Irp);

			if (NT_SUCCESS(ntStatus)) 
			{
				//如果发给下层设备的请求成功了,说明下层设备支持这个操作,会执行到这里
				//在成功的条件下我们来改变我们自己的计数值,这样就能记录我们现在这个设备上到底有多少个分页文件
				IoAdjustPagingPathCount(
					&DevExt->PagingPathCount,
					irpsp->Parameters.UsageNotification.InPath);
				if (irpsp->Parameters.UsageNotification.InPath) 
				{
					if (DevExt->PagingPathCount == 1) 
					{
						//如果这个请求是一个建立分页文件的查询请求,并且下层设备支持这个请求,而且这是第一个在这个设备上的分页文件,那么我们需要清除DO_POWER_PAGABLE位
						DeviceObject->Flags &= ~DO_POWER_PAGABLE;
					}
				}
			}
			else 
			{
				//到这里说明给下层设备发请求失败了,下层设备不支持这个请求,这时候我们需要把之前做过的操作还原
				if (setPagable == TRUE) 
				{
					//根据setPagable变量的值来判断我们之前是否做过对DO_POWER_PAGABLE的设置,如果有的话就清楚这个设置
					DeviceObject->Flags &= ~DO_POWER_PAGABLE;
					setPagable = FALSE;
				}
			}
			//设置分页计数事件
			KeSetEvent(
				&DevExt->PagingPathCountEvent,
				IO_NO_INCREMENT, 
				FALSE
				);
			//到这里我们就可以完成这个irp请求了
			IoCompleteRequest(Irp, IO_NO_INCREMENT);
			return ntStatus;
		}		
	default:
		break;
	}
	return DPSendToNextDriver(
		DevExt->LowerDevObj,
		Irp);

}
Example #3
-1
NTSTATUS
DPVolumeOnLineCompleteRoutine(
	IN PDEVICE_OBJECT  DeviceObject,
	IN PIRP  Irp,
	IN PVOLUME_ONLINE_CONTEXT  Context
	)
{
	//返回值
	NTSTATUS ntStatus = STATUS_SUCCESS;
	//这个卷设备的dos名字,也就是C,D等
	UNICODE_STRING		DosName = { 0 };

	//在这里Context是不可能为空的,为空就是出错了
	ASSERT(Context!=NULL);
	//下面调用我们自己的VolumeOnline处理
	//获取这个卷的dos名字
	ntStatus = IoVolumeDeviceToDosName(Context->DevExt->PhyDevObj, &DosName);
	if (!NT_SUCCESS(ntStatus))
		goto ERROUT;
	//将dos名字变成大写形式
	Context->DevExt->VolumeLetter = DosName.Buffer[0];
	if (Context->DevExt->VolumeLetter > L'Z')
		Context->DevExt->VolumeLetter -= (L'a' - L'A');
	//我们只保护“D”盘
	if (Context->DevExt->VolumeLetter == L'D')
	{
		//获取这个卷的基本信息
		ntStatus = DPQueryVolumeInformation(
			Context->DevExt->PhyDevObj,
			&(Context->DevExt->TotalSizeInByte),
			&(Context->DevExt->ClusterSizeInByte),
			&(Context->DevExt->SectorSizeInByte));
		if (!NT_SUCCESS(ntStatus))
		{
			goto ERROUT;
		}
		//建立这个卷对应的位图
		ntStatus = DPBitmapInit(
			&Context->DevExt->Bitmap,
			Context->DevExt->SectorSizeInByte,
			8,
			25600,
			(DWORD)(Context->DevExt->TotalSizeInByte.QuadPart / 
			(LONGLONG)(25600 * 8 * Context->DevExt->SectorSizeInByte)) + 1);
		if (!NT_SUCCESS(ntStatus))
			goto ERROUT;
		//对全局量赋值,说明我们找到需要保护的那个设备了
		gProtectDevExt = Context->DevExt;
	}
	
ERROUT:
	if (!NT_SUCCESS(ntStatus))
	{
		if (NULL != Context->DevExt->Bitmap)
		{
			DPBitmapFree(Context->DevExt->Bitmap);
		}
		if (NULL != Context->DevExt->TempFile)
		{
			ZwClose(Context->DevExt->TempFile);
		}
	}
	if (NULL != DosName.Buffer)
	{
		ExFreePool(DosName.Buffer);
	}
	//设置等待同步事件,这样可以让我们等待的DeviceIoControl处理过程继续运行
	KeSetEvent(
		Context->Event,
		0,
		FALSE);
	return STATUS_SUCCESS;
}