符号 ??HelloDDK -》\.
??HelloDDK ->\.HelloDDK -> C语言字符串 \\.\HelloDDK
HANDLE hDevice = CreateFile("\\.\HelloDDK", GENERIC_READ | GENERIC_WRITE, 0, // share mode none NULL, // no security OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); // no template if (hDevice == INVALID_HANDLE_VALUE) { printf("Failed to obtain file handle to device: " "%s with Win32 error code: %d ", "MyWDMDevice", GetLastError() ); return 1; } CloseHandle(hDevice);//触发MJ_CLEANUP MJ_CLOSE设备对象一共有3中读写方式:
1)缓冲区方式读写
//创建设备 status = IoCreateDevice( pDriverObject, sizeof(DEVICE_EXTENSION), &(UNICODE_STRING)devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj ); if (!NT_SUCCESS(status)) return status; pDevObj->Flags |= DO_BUFFERED_IO;
用程序提供缓冲区的数据复制到内核模式下的中,无论操作系统怎么切换,内核模式地址都不会改变
缺点: 影响了运行效率
下面为 利用缓冲区 方式读设备:(写入数据
pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKRead;
IRP_MJ_READ 的派遣函数主要任务是把任务断的数据复制到AssociatedIrp.SystemBuffer
NTSTATUS HelloDDKRead(IN PDEV0CE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("Enter HelloDDKRead ")); //对一般IRP的简单操作,后面会介绍对IRP更复杂的操作 NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); ULONG ulReadLength = stack->Parameters.Read.Length; // 完成IRP //设置IRP完成状态 pIrp->IoStatus.Status = status; //设置IRP操作了多少字节 pIrp->IoStatus.Information = ulReadLength; // bytes xfered memset(pIrp->AssociatedIrp.SystemBuffer,0xAA,ulReadLength); //处理IRP IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("Leave HelloDDKRead ")); return status; }
下面为 程序 读取
HANDLE hDevice = CreateFile("\\.\HelloDDK", GENERIC_READ | GENERIC_WRITE, 0, // share mode none NULL, // no security OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); // no template if (hDevice == INVALID_HANDLE_VALUE) { printf("Failed to obtain file handle to device: " "%s with Win32 error code: %d ", "MyWDMDevice", GetLastError() ); return 1; } UCHAR buffer[10]; ULONG ulRead; BOOL bRet = ReadFile(hDevice,buffer,10,&ulRead,NULL); if (bRet) { printf("Read %d bytes:",ulRead); for (int i=0;i<(int)ulRead;i++) { printf("%02X ",buffer[i]); } printf(" "); } CloseHandle(hDevice); return 0;
下面是程序写入设备 WriteFile 内部产生 IRP_MJ_WRITE 类型的IRP
派遣函数需要将传送进来的数据保存起来,以便读取该设备的时候读取
NTSTATUS HelloDDKWrite(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("Enter HelloDDKWrite ")); //对一般IRP的简单操作,后面会介绍对IRP更复杂的操作 NTSTATUS status = STATUS_SUCCESS; PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp); ULONG ulWriteLength = stack->Parameters.Write.Length; ULONG ulWriteOffset = (ULONG)stack->Parameters.Write.ByteOffset.QuadPart; if (ulWriteOffset + ulWriteLength > 1024) { status = STATUS_FILE_INVALID; ulWriteOffset = 0; } else { memcpy(pDevExt->buffer+ulWriteOffset, pIrp->AssociatedIrp.SystemBuffer, ulWriteLength); status = STATUS_SUCCESS; if (ulWriteLength + ulWriteOffset > pDevExt->File_length) { pDevExt->File_length = ulWriteLength + ulWriteOffset; } } pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = ulWriteLength; //处理IRP IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("Leave HelloDDKWrite ")); return status; }