FLT_CREATEFILE_TARGET_ECP_CONTEXT 結構 (fltkernel.h)
FLT_CREATEFILE_TARGET_ECP_CONTEXT 結構是一個額外的 create 參數, (ECP) 用來將目標資訊傳回給 FltCreateFileEx2 的呼叫端。
語法
typedef struct _FLT_CREATEFILE_TARGET_ECP_CONTEXT {
PFLT_INSTANCE Instance;
PFLT_VOLUME Volume;
PFLT_FILE_NAME_INFORMATION FileNameInformation;
FLT_CREATEFILE_TARGET_FLAGS Flags;
} FLT_CREATEFILE_TARGET_ECP_CONTEXT, *PFLT_CREATEFILE_TARGET_ECP_CONTEXT;
成員
Instance
附加至調整目標的篩選實例。
Volume
調整的目標磁碟區。
FileNameInformation
調整目標的檔案資訊。
Flags
控制重新分析作業的旗標。 此值可以是 0 或下列值。
值 | 意義 |
---|---|
|
當找不到具有源文件信息的目標時,要求 FltCreateFileEx2 嘗試重新剖析作業。 |
備註
當 FltCreateFileEx2 的呼叫端想要啟用磁碟區目標的重新分析時 ,FLT_CREATEFILE_TARGET_ECP_CONTEXT可以 包含在 DriverContext 參數中的 ECP 清單中作為 ECP 清單。 如果此 ECP 存在, FltCreateFileEx2 將會調整建立作業的目標裝置,並嘗試尋找適合指定檔案資訊的已篩選磁碟區實例。 如果篩選管理員在目標磁碟區上找不到呼叫端的對應實例,它會為新目標設定FLT_CREATEFILE_TARGET_ECP_CONTEXT的 Volume 和 FileNameInformation 成員。 接著,呼叫端可以使用這項資訊來決定如何繼續。
如果 FltCreateFileEx2 的呼叫端想要處理重新分析作業本身,則會從 Flags 成員清除FLTTCFL_AUTO_REPARSE旗標。 在此情況下, FltCreateFileEx2 會將初始目標調整資訊放在 ECP 中,然後傳回,結束檔案建立嘗試。
如果在已認可的 ECP 中設定 Instance、 Volume 或 FileNameInformation 中的值,則會參考這些值。 FltCreateFileEx2 的呼叫端負責呼叫 Instance 和 Volume 的 FltObjectDereference,以及針對 FileNameInformation 呼叫 FltReleaseFileNameInformation。
下列範例例程示範迷你篩選如何呼叫 FltCreateFileEx2 搭配 FLT_CREATEFILE_TARGET_ECP_CONTEXT ,以在需要尋找檔案目標時處理重新分析至不同的磁碟區。
NTSTATUS
CrossVolumeCreate(
_In_ PUNICODE_STRING FileName,
_In_ PFLT_FILTER Filter,
_In_ PFLT_INSTANCE Instance,
_Inout_ PIO_STATUS_BLOCK IoStatus,
_Out_ PHANDLE Handle,
_Outptr_ PFILE_OBJECT *FileObject
)
/*++
Routine Description:
Issues a targeted create and handles cross volume reparse.
Arguments:
FileName - The name of the file to open
Filter – The filter issuing the create
Instance - The filter instance for the targeted create
IoStatus - Receives the operation status
Handle - Receives the file handle
FileObject - Receives the file object
Return Value:
status of the operation
--*/
{
PFLT_CREATEFILE_TARGET_ECP_CONTEXT ecpContext;
PECP_LIST ecpList;
PFLT_FILE_NAME_INFORMATION fileNameInformation;
IO_DRIVER_CREATE_CONTEXT myCreateContext;
OBJECT_ATTRIBUTES objAttr;
NTSTATUS status;
ecpContext = NULL;
ecpList = NULL;
fileNameInformation = NULL;
status = STATUS_SUCCESS;
InitializeObjectAttributes( &objAttr,
FileName,
OBJ_KERNEL_HANDLE,
NULL,
NULL );
//
// First we optimistically send a targeted create that is not
// setup to handle cross-volume reparse.
//
status = FltCreateFileEx2( Filter,
Instance,
Handle,
FileObject,
FILE_READ_DATA|FILE_WRITE_DATA,
&objAttr,
IoStatus,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0,
IO_IGNORE_SHARE_ACCESS_CHECK,
NULL );
if (!NT_SUCCESS(status)) {
if ((status != STATUS_INVALID_DEVICE_OBJECT_PARAMETER) &&
(status != STATUS_MOUNT_POINT_NOT_RESOLVED)) {
goto CrossVolumeCreateExit;
}
} else {
//
// The create succeeded. There must not have been a cross-volume
// reparse.
//
goto CrossVolumeCreateExit;
}
//
// The create failed traversing a cross-volume link.
// Issue another create with a targeting ECP so that
// we can handle cross-volume reparse.
//
status = FltAllocateExtraCreateParameterList( Filter,
0,
&ecpList );
if (!NT_SUCCESS( status )) {
goto CrossVolumeCreateExit;
}
status = FltAllocateExtraCreateParameter( Filter,
&GUID_ECP_FLT_CREATEFILE_TARGET,
sizeof(FLT_CREATEFILE_TARGET_ECP_CONTEXT),
0,
NULL,
POOL_TAG,
&ecpContext );
if (!NT_SUCCESS( status )) {
goto CrossVolumeCreateExit;
}
//
// Initialize the ECP with the FLTTCFL_AUTO_REPARSE flag which
// tells filter manager to handle the cross-volume reparse
// internally when possible (when it can find our instance
// on the target volume). If this flag is not set, the filter will
// be responsible for calling FltCreateFileEx2 with appropriate
// Instance parameter.
//
ecpContext->Flags = FLTTCFL_AUTO_REPARSE;
ecpContext->Instance = NULL;
ecpContext->Volume = NULL;
ecpContext->FileNameInformation = NULL;
status = FltInsertExtraCreateParameter( Filter,
ecpList,
ecpContext );
if (!NT_SUCCESS( status )) {
goto CrossVolumeCreateExit;
}
IoInitializeDriverCreateContext( &myCreateContext );
myCreateContext.ExtraCreateParameter = ecpList;
InitializeObjectAttributes( &objAttr,
FileName,
OBJ_KERNEL_HANDLE,
NULL,
NULL );
status = FltCreateFileEx2( Filter,
Instance,
Handle,
FileObject,
FILE_READ_DATA|FILE_WRITE_DATA,
&objAttr,
IoStatus,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0,
IO_IGNORE_SHARE_ACCESS_CHECK,
&myCreateContext );
if (!NT_SUCCESS(status)) {
if ((status != STATUS_INVALID_DEVICE_OBJECT_PARAMETER) &&
(status != STATUS_MOUNT_POINT_NOT_RESOLVED)) {
goto CrossVolumeCreateExit;
}
} else {
goto CrossVolumeCreateExit;
}
//
// Filter manager should have acknowledged the ECP. If it
// is not acknowledged, it does not contain any cross-volume
// targeting information.
//
if (!FltIsEcpAcknowledged( Filter, ecpContext)) {
goto CrossVolumeCreateExit;
}
//
// Filter manager could not automatically handle the
// cross-volume traversal. We choose to send the create
// to the top of the stack on the target volume indicated
// in the targeting ECP.
//
//
// The ECP may contain pointers to referenced objects. We
// need to deal with those references before reusing the
// ECP.
//
if (ecpContext->Volume != NULL) {
FltObjectDereference( ecpContext->Volume );
ecpContext->Volume = NULL;
}
//
// Note: since we flagged the ECP to automatically handle
// cross-volume reparse, the create should have failed after
// we traversed a mountpoint only if our filter did not have
// an instance on the target volume. In that case we would
// expect the Instance field in the ECP to be NULL. We still
// demonstrate derefing the instance for the general case.
//
if (ecpContext->Instance != NULL) {
FltObjectDereference( ecpContext->Instance );
ecpContext->Instance = NULL;
}
fileNameInformation = ecpContext->FileNameInformation;
ecpContext->FileNameInformation = NULL;
//
// Tell filter manager to not handle the cross-volume
// reparse itself. Presumably a filter would do this if it
// did not want the create automatically targeted at its
// instance on another volume.
//
ecpContext->Flags = 0;
//
// Reinitialize the targeting ECP to it can be reused.
//
FltPrepareToReuseEcp( Filter, ecpContext );
IoInitializeDriverCreateContext( &myCreateContext );
myCreateContext.ExtraCreateParameter = ecpList;
InitializeObjectAttributes( &objAttr,
&fileNameInformation->Name,
OBJ_KERNEL_HANDLE,
NULL,
NULL );
status = FltCreateFileEx2( Filter,
NULL,
Handle,
FileObject,
FILE_READ_DATA|FILE_WRITE_DATA,
&objAttr,
IoStatus,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN_IF,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0,
IO_IGNORE_SHARE_ACCESS_CHECK,
&myCreateContext );
if (!NT_SUCCESS(status)) {
if ((status != STATUS_INVALID_DEVICE_OBJECT_PARAMETER) &&
(status != STATUS_MOUNT_POINT_NOT_RESOLVED)) {
goto CrossVolumeCreateExit;
}
//
// We hit another cross-volume link. For the purposes of
// this example we are just giving up. An actual filter
// would determine the next target instance based on the
// information provided in the targeting ECP. Some of the
// possibilities are:
// 1) If the Instance field in the ECP is available, target
// the create to this instance.
// 2) If the Instance field is NULL, attempt to attach
// an instance based on the Volume parameter in the ECP
// and then target that new instance.
// 3) Use the FileNameInformation provided in the ECP and a
// NULL instance to target the top of the other
// volume's stack.
//
} else {
goto CrossVolumeCreateExit;
}
CrossVolumeCreateExit:
if (ecpContext != NULL &&
FltIsEcpAcknowledged( Filter, ecpContext)) {
FltRemoveExtraCreateParameter( Filter,
ecpList,
&GUID_ECP_FLT_CREATEFILE_TARGET,
&ecpContext,
NULL );
if (ecpContext->Instance != NULL) {
FltObjectDereference( ecpContext->Instance );
}
if (ecpContext->Volume != NULL) {
FltObjectDereference( ecpContext->Volume );
}
if (ecpContext->FileNameInformation != NULL) {
FltReleaseFileNameInformation( ecpContext->FileNameInformation );
}
FltFreeExtraCreateParameter( Filter, ecpContext );
}
if (ecpList != NULL) {
FltFreeExtraCreateParameterList( Filter, ecpList );
}
if (fileNameInformation != NULL) {
FltReleaseFileNameInformation( fileNameInformation );
}
return status;
}
規格需求
需求 | 值 |
---|---|
最低支援的用戶端 | 從 Windows 8 開始,即可使用此結構。 |
標頭 | fltkernel.h (包含 FltKernel.h) |