我正在为Windows编写一个微筛选器驱动程序。我可以通过我的GetProcessFileName
函数获取进程映像名称,该函数使用ZwQueryInformationProcess
获取进程映像文件名并返回具有如下值的 PUNICODESTRING :
DeviceHarddiskVolume2Program FilesCommon FilesACD SystemsPicaViewACDSeePicaView.exe
但我想从这个 PUNICODESTRING 中提取三个变量的音量和父目录。例如
PUNICODESTRING volume;
PUNICODESTRING parentdir;
PUNICODESTRING processname;
怎么能做到这一点,所以我的变量将是:
volume ---> DeviceHarddiskVolume2
parentdir ---> Program FilesCommon FilesACD SystemsPicaView
processname ---> ACDSeePicaView.exe
使用FltParseFileName
函数 https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/fltkernel/nf-fltkernel-fltparsefilename
FltParse文件名解析扩展名、流和最终组件 从文件名字符串。
NTSTATUS FLTAPI FltParseFileName(
[in] PCUNICODE_STRING FileName,
[in, out] PUNICODE_STRING Extension,
[in, out] PUNICODE_STRING Stream,
[in, out] PUNICODE_STRING FinalComponent
);
该函数采用UNICODE_STRING结构指针,并返回文件扩展名、流和最终组件。
\设备\硬盘卷2\程序文件\通用文件\ACD 系统\PicaView\ACDSeePicaView.exe
扩展名:"exe">
最终组件:"ACDSeePicaView">
您可以通过第三个反斜杠之前的 get 字符串和父目录来获取卷名,并通过从字符串中减去卷和最终组件 + 扩展名来获取父目录。
这是一个从文件路径字符串中提取卷名的函数
NTSTATUS GetVolumeNameFromFileName(PUNICODE_STRING FileName, PUNICODE_STRING VolumeName) {
NTSTATUS status = STATUS_UNSUCCESSFUL;
PWCHAR fileName = ExAllocatePool2(POOL_FLAG_PAGED, FileName->Length + sizeof(WCHAR), 100);
if (fileName == NULL) {
KdPrint(("GetVolumeNameFromFileName -> Not enough memory to allocate for the file name.rn"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(fileName, FileName->Buffer, FileName->Length);
WCHAR* p;
//Search the third backslash in the file name string
int pos = 0;
int slashIndex = -1;
p = wcschr(fileName, L'\');
while (p != NULL && pos < 3) {
if (pos == 2) {
slashIndex = p - fileName;
}
else {
p = wcschr(p + 1, L'\');
}
pos += 1;
}
ExFreePoolWithTag(fileName, 100);
if (slashIndex == -1) {
KdPrint(("GetVolumeNameFromFileName -> Failed to get the directory separator index.rn"));
return STATUS_UNSUCCESSFUL;
}
UNICODE_STRING volumeName = { 0 };
volumeName.Length = 0;
volumeName.MaximumLength = (slashIndex + 1) * sizeof(WCHAR);
volumeName.Buffer = ExAllocatePool2(POOL_FLAG_PAGED, volumeName.MaximumLength, 101);
status = RtlUnicodeStringCchCopyN(&volumeName, FileName, slashIndex);
if (NT_SUCCESS(status)) {
*VolumeName = volumeName;
}
else {
KdPrint(("GetVolumeNameFromFileName -> RtlUnicodeStringCchCopyN function failed (%08x).rn", status));
}
return status;
}