阅读:2034回复:4
[Sfilter]在SfCreate()函数一开始得到文件名的方法(含长短名转换)
编译环境:ifs2003
目标系统:windowsXP + sp2 基本是按照楚狂人的教程来的,长短名转换确实挺麻烦,已通过测试。 在驱网看了很多好文章,心底有很多谢意,也许这个东西能对别人有用。 FYI: //get the name with FILE_OBJECT's FileName and RelatedObject fields void SfGetFileNameFromFileObject( IN PSFILTER_DEVICE_EXTENSION devExt, IN PFILE_OBJECT FileObject, OUT ULONG* FileNameLength, OUT PWCHAR buffer ) { POBJECT_NAME_INFORMATION nameInfo = NULL; ULONG returnLength; ULONG index; NTSTATUS status; ULONG i; BOOLEAN firstPassed; HANDLE hDir = NULL; PWCHAR s2li = NULL; PWCHAR start; PWCHAR wc; WCHAR longName[MAXPATHLEN]; ULONG longNameIndex; UNICODE_STRING usDirName; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK statusBlock; ULONG dirInfoLength; PVOID dirInfo; PFILE_BOTH_DIR_INFORMATION dirEntryInfo; //for winXP; PWCHAR wci; PWCHAR wcj; ULONG j; BOOLEAN differ; HANDLE hEvent; //1) add the drive letter which I get it in SfFsControlMountVolume() buffer[0] = devExt->DriveLetter; buffer[1] = L':'; index = 2; returnLength = 0; if(FileObject->RelatedFileObject != NULL) { nameInfo = ExAllocatePoolWithTag( PagedPool, sizeof(OBJECT_NAME_INFORMATION) + MAXPATHLEN * sizeof(WCHAR), CJTAG); status = ObQueryNameString( FileObject->RelatedFileObject, nameInfo, sizeof(OBJECT_NAME_INFORMATION) + MAXPATHLEN * sizeof(WCHAR), &returnLength); if(!NT_SUCCESS(status)) { ExFreePool(nameInfo); return; } //2)add the directory's path if the file is queried by relative //the path gotten with ObQueryNameString is like: //"\Device\HarddiskVolume1\WINDOWS" KdPrint(("_CJDN: %wZ\n", nameInfo->Name)); firstPassed = FALSE; for(i=1; i<nameInfo->Name.Length; i++) { if(nameInfo->Name.Buffer == L'\\') { if(firstPassed) break; else firstPassed = TRUE; } } RtlCopyMemory(buffer + index, nameInfo->Name.Buffer + i, nameInfo->Name.Length - i * sizeof(WCHAR)); index += nameInfo->Name.Length / sizeof(WCHAR) - i; } if(FileObject->FileName.Length == 0) { if(nameInfo) ExFreePool(nameInfo); return; } RtlCopyMemory(&buffer[index], FileObject->FileName.Buffer, FileObject->FileName.Length); index += FileObject->FileName.Length / sizeof(WCHAR); buffer[index] = L'\0'; //substitute short names if exist with their relative long names. //buffer now is like L"C:\\PROGRA~1" but the ZwCreateFile() need //file name like L"\\Device\\HarddiskVolume1\PROGRA~1". RtlCopyMemory(longName, devExt->DeviceName.Buffer, devExt->DeviceName.Length); longNameIndex = devExt->DeviceName.Length / sizeof(WCHAR); start = buffer + 2; while((s2li = wcschr(start, L'~')) != NULL) { for(wc=s2li; (*wc)!=L'\\'; wc--) //the previous L'\\' ; RtlCopyMemory(&longName[longNameIndex], start, (wc + 1 - start) * sizeof(WCHAR)); longNameIndex += wc + 1 - start; for(wc=s2li; (*wc)!=L'\\' && (*wc)!=L'\0'; wc++) //the next L'\\' or end ; if(*wc == L'\0') break; longName[longNameIndex] = L'\0';//compose a temporary directory file path RtlInitUnicodeString(&usDirName, longName); InitializeObjectAttributes(&objectAttributes, &usDirName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwCreateFile(&hDir, FILE_READ_DATA | SYNCHRONIZE, &objectAttributes, &statusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if(!NT_SUCCESS(status)) { if(nameInfo) ExFreePool(nameInfo); KdPrint(("_cj ZwCreateFile() @ SfGetFileNameFromFileObject() failed, status: 0x%x\n", status)); return; } dirInfoLength = 4048;//one page size dirInfo = ExAllocatePoolWithTag(NonPagedPool, dirInfoLength, CJTAG); ZwCreateEvent(&hEvent, GENERIC_ALL, NULL, NotificationEvent, FALSE); status = ZwQueryDirectoryFile(hDir, hEvent, NULL, NULL, &statusBlock, dirInfo, dirInfoLength, FileBothDirectoryInformation, FALSE, NULL, TRUE); if(STATUS_PENDING == status) { ZwWaitForSingleObject(hEvent, TRUE, NULL); } else if(!NT_SUCCESS(status)) { ExFreePool(dirInfo); ZwClose(hDir); if(nameInfo) ExFreePool(nameInfo); KdPrint(("_CJ ZwWaitForSingleObject() @ SfGetFileNameFromFileObject() failed, status: 0x%x\n", status)); return; } dirEntryInfo = (PFILE_BOTH_DIR_INFORMATION)dirInfo; while(1)//compare the directory's entries one by one to find the one I want { //judge whether this entry is which I need. //start --- wc is like: L"PROGRA~1\\", while start is L'P', and wc is L'\\' if(dirEntryInfo->ShortNameLength / 2 == (wc - start -1)) { differ = FALSE; wci = start + 1; wcj = dirEntryInfo->ShortName; for(; wci < wc; wci++, wcj++) { if(*wci != *wcj) { differ = TRUE; break; } } if(differ == FALSE) //no difference found, so I get the appropriate one { for(j=0; j<dirEntryInfo->FileNameLength/2; j++) { longName[longNameIndex] = dirEntryInfo->FileName[j]; longNameIndex++; } break;// break while(1) } } if(dirEntryInfo->NextEntryOffset == 0) {//can't find one, so this is a long name, such as "abc~def.txt" for(wci = start; wci < wc; wci++) { longName[longNameIndex] = *wci; longNameIndex++; } break; } else dirEntryInfo = (PFILE_BOTH_DIR_INFORMATION)((char*)dirEntryInfo + dirEntryInfo->NextEntryOffset); } ExFreePool(dirInfo); ZwClose(hDir); start = wc; } //the remainder doesn't have L'~', so I just make a copy. RtlCopyMemory(&longName[longNameIndex], start, (buffer + index - start) * sizeof(WCHAR)); longNameIndex += buffer + index - start; //finally, I copy the result to my output buffer RtlCopyMemory(buffer + 2, longName + devExt->DeviceName.Length / sizeof(WCHAR), longNameIndex * sizeof(WCHAR) - devExt->DeviceName.Length); *FileNameLength = 2 * sizeof(WCHAR) + (longNameIndex * sizeof(WCHAR) - devExt->DeviceName.Length); if(nameInfo) ExFreePool(nameInfo); } |
|
沙发#
发布于:2008-05-01 21:01
学习了,谢谢
|
|
板凳#
发布于:2008-05-03 11:20
这样处理得不错.
|
|
|
地板#
发布于:2008-05-05 16:10
也学习了,谢谢,楼主好人啊
|
|
|
地下室#
发布于:2008-05-06 09:55
这个要放在哪个地方啊,我怎么实现不了这个功能啊???
|
|
|