阅读:7361回复:11
100分请教IoCreateSymbolicLink和DefineDosDevice的区别
是这样的,我在修改filedisk的源码,希望通过一个Pnp事件(如插上一个USB设备)来通知filedisk设备加载文件,我在USB设备驱动中向filedisk发出了IOCTL_FILE_DISK_OPEN_FILE命令,并在filedisk的IOCTL_FILE_DISK_OPEN_FILE的处理函数末尾用IoCreateSymbolicLink连接上一个盘符(如z:),这些都成功了。
但是我的电脑面板上却没有Z盘的图标,而且用cd z:\系统会显示“此卷不包含可识别的文件系统。请确定所有请求的文件系统驱动程序已加载,且此卷未损坏。“的错误信息。 如果用控制台发消息给filedisk的话却可以出现盘的图标,debug表明definedosdevice函数调用后就出现了图标,不知道那位可以解释一下 |
|
沙发#
发布于:2004-04-03 18:46
NTSTATUS
FileDiskOpenFile ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION device_extension; POPEN_FILE_INFORMATION open_file_information; UNICODE_STRING ufile_name; UNICODE_STRING symLinkName; UNICODE_STRING deviceName; NTSTATUS status; OBJECT_ATTRIBUTES object_attributes; OBJECT_ATTRIBUTES oa; FILE_END_OF_FILE_INFORMATION file_eof; FILE_BASIC_INFORMATION file_basic; FILE_STANDARD_INFORMATION file_standard; FILE_ALIGNMENT_INFORMATION file_alignment; PAGED_CODE(); ASSERT(DeviceObject != NULL); ASSERT(Irp != NULL); DebugPrintMsg("in FilediskOpenFile\n"); device_extension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; open_file_information = (POPEN_FILE_INFORMATION) Irp->AssociatedIrp.SystemBuffer; if (DeviceObject->DeviceType != FILE_DEVICE_CD_ROM) { device_extension->read_only = open_file_information->ReadOnly; } device_extension->file_name.Length = open_file_information->FileNameLength; device_extension->file_name.MaximumLength = open_file_information->FileNameLength; device_extension->file_name.Buffer = ExAllocatePool(NonPagedPool, open_file_information->FileNameLength); RtlCopyMemory( device_extension->key, open_file_information->Key, KEY_WORD_LENGTH ); device_extension->dosname = open_file_information->DOSNAME; RtlCopyMemory( device_extension->file_name.Buffer, open_file_information->FileName, open_file_information->FileNameLength ); DebugPrint("filename:%s",device_extension->file_name.Buffer); status = RtlAnsiStringToUnicodeString( &ufile_name, &device_extension->file_name, TRUE ); if (!NT_SUCCESS(status)) { ExFreePool(device_extension->file_name.Buffer); Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; return status; } InitializeObjectAttributes( &object_attributes, &ufile_name, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = ZwCreateFile( &device_extension->file_handle, device_extension->read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, &object_attributes, &Irp->IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, device_extension->read_only ? FILE_SHARE_READ : 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_NO_INTERMEDIATE_BUFFERING | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NO_SUCH_FILE) { if (device_extension->read_only || open_file_information->FileSize.QuadPart == 0) { ExFreePool(device_extension->file_name.Buffer); RtlFreeUnicodeString(&ufile_name); Irp->IoStatus.Status = STATUS_NO_SUCH_FILE; Irp->IoStatus.Information = 0; return STATUS_NO_SUCH_FILE; } else { status = ZwCreateFile( &device_extension->file_handle, GENERIC_READ | GENERIC_WRITE, &object_attributes, &Irp->IoStatus, &open_file_information->FileSize, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_NO_INTERMEDIATE_BUFFERING | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if (!NT_SUCCESS(status)) { ExFreePool(device_extension->file_name.Buffer); RtlFreeUnicodeString(&ufile_name); return status; } if (Irp->IoStatus.Information == FILE_CREATED) { file_eof.EndOfFile.QuadPart = open_file_information->FileSize.QuadPart; status = ZwSetInformationFile( device_extension->file_handle, &Irp->IoStatus, &file_eof, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation ); if (!NT_SUCCESS(status)) { ExFreePool(device_extension->file_name.Buffer); RtlFreeUnicodeString(&ufile_name); ZwClose(device_extension->file_handle); return status; } } } } else if (!NT_SUCCESS(status)) { ExFreePool(device_extension->file_name.Buffer); RtlFreeUnicodeString(&ufile_name); return status; } RtlFreeUnicodeString(&ufile_name); status = ZwQueryInformationFile( device_extension->file_handle, &Irp->IoStatus, &file_basic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation ); if (!NT_SUCCESS(status)) { ExFreePool(device_extension->file_name.Buffer); ZwClose(device_extension->file_handle); return status; } // // The NT cache manager can deadlock if a filesystem that is using the cache // manager is used in a virtual disk that stores its file on a filesystem // that is also using the cache manager, this is why we open the file with // FILE_NO_INTERMEDIATE_BUFFERING above, however if the file is compressed // or encrypted NT will not honor this request and cache it anyway since it // need to store the decompressed/unencrypted data somewhere, therefor we put // an extra check here and don't alow disk images to be compressed/encrypted. // if (file_basic.FileAttributes & (FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED)) { ExFreePool(device_extension->file_name.Buffer); ZwClose(device_extension->file_handle); Irp->IoStatus.Status = STATUS_ACCESS_DENIED; Irp->IoStatus.Information = 0; return STATUS_ACCESS_DENIED; } status = ZwQueryInformationFile( device_extension->file_handle, &Irp->IoStatus, &file_standard, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation ); if (!NT_SUCCESS(status)) { ExFreePool(device_extension->file_name.Buffer); ZwClose(device_extension->file_handle); return status; } device_extension->file_size.QuadPart = file_standard.EndOfFile.QuadPart; status = ZwQueryInformationFile( device_extension->file_handle, &Irp->IoStatus, &file_alignment, sizeof(FILE_ALIGNMENT_INFORMATION), FileAlignmentInformation ); if (!NT_SUCCESS(status)) { ExFreePool(device_extension->file_name.Buffer); ZwClose(device_extension->file_handle); return status; } DeviceObject->AlignmentRequirement = file_alignment.AlignmentRequirement; if (device_extension->read_only) { DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; } else { DeviceObject->Characteristics &= ~FILE_READ_ONLY_DEVICE; } device_extension->media_in_device = TRUE; DebugPrintMsg("before set link\n"); RtlInitUnicodeString(&deviceName,L"\\Device\\FileDisk\\FileDisk0"); RtlInitUnicodeString(&symLinkName,L"\\??\\Z:"); status = IoCreateSymbolicLink(&symLinkName, &deviceName); if( !NT_SUCCESS( status ) ){ ExFreePool(device_extension->file_name.Buffer); ZwClose(device_extension->file_handle); DebugPrintMsg(" set link error2 "); return status; } Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; DebugPrintMsg("Out FilediskOpenFile\n"); return STATUS_SUCCESS; } |
|
板凳#
发布于:2004-04-04 11:35
use winobj tool to see if symbolic link(z:) exists.
|
|
地板#
发布于:2004-04-04 18:49
不是这个问题,Z:已生成,我用softice的tool看了一下
|
|
地下室#
发布于:2004-04-04 18:57
用definedosdevice时检测出系统回向我的驱动发出六条ioctl指令以获取磁盘信息,随即我的电脑的面板上就出现了磁盘图标,但是ioCreateSymbolicLink调用时系统就没有发出这些指令。
|
|
5楼#
发布于:2004-04-04 19:41
据我的判断你用的应该是WindowsXP系统。在XP下MS-DOS Device Names(如盘符)分为Global与Local两种类型,在用户登录的时候系统自动将Global MS-DOS Device Names拷贝到用户的Local MS-DOS Device Names,然后用户自己建立的MS-DOS Device Names只对当前用户产生作用,系统中其他用户并不能看到此MS-DOS Device Names,同时Global MS-DOS Device Names的改变只有在用户下次登录时才会体现出来。因此想要使盘符的变化立即对当前用户生效,MS-DOS Device Names应该在用户的Local空间中建立,就是在当前登录用户的上下文环境中建立而不应该在系统的上下文环境中建立。详见DDK文档。
|
|
6楼#
发布于:2004-04-05 14:17
问题如你所说,我换个账号重新登陆就可出现盘符了,呵呵,真想请你吃饭。。。
我查了一下,如果用gloabe的话,只要symboliclink时用\\dosdevices\\gloabe\\z:就行了,如果用local的话,需要一个win32程序发出的ioctl请求中symboliclink即可,但我用的是驱动调驱动,就不知道怎么办了。 你有这方面经验么,能不能详细讲一下,谢谢:) |
|
7楼#
发布于:2004-04-05 14:30
已经给了20分了,剩下80分怎么给?
|
|
8楼#
发布于:2004-04-05 17:56
可以再开几个帖子给分 :P :D
|
|
9楼#
发布于:2004-04-05 18:18
呵呵,还想问一下MS-DOS Device Names怎么在用户的Local空间中建立
|
|
10楼#
发布于:2005-01-25 07:30
Who knows how to work this on Terminal Server/Client with definedosdevice? I want to create a Global Dos Device on TS, but can not see it from TS client, only can see on Local, "Global\Z:", doesn't help.
|
|
11楼#
发布于:2009-09-16 14:30
可以同时在内核态和用户态都创建同样的一个符号链接
经过测试 最好是先在用户态调用definedosdevice创建一个符号链接,之后在内核态调用IoCreateSymboliclink再创建同样的符号链接,且在内核态创建时不需要知道创建的结果。 原理如下: 1、如果当前的环境是local system context ,那么definedosdevice创建的符号链接应该是全局的,同时操作系统会通过某种机制保证在用户登录够此全局的符号链接复制到用的session空间。此时如果在内核太重新创建符号链接(全局的),会创建失败,因为此时全局的符号链接已经存在。这样就保证了在全局的和用户session空间的都有一个同样的符号链接。 2、如果当前环境是用户登录之后的环境,那么definedosdevice创建的符号链接是当前用户session空间的,全局的肯定不可见。此时调用内核去创建全局的符号链接,则会创建成功。这样也保证了全局和当前用户session空间都存在一个同样的符号链接。这样即使切换用户,这个符号链接也是有效的 |
|
|