Introduction

Welcome to CBFS Filter, an all-in-one solution for filesystem, registry, and process manager request filtering. Advanced filter rules ensure that your application is notified only of the operations that you care about, and intelligent access rules enable you to enforce access restrictions with no additional effort. CBFS Filter's robust and performant event-driven API will help you monitor, intercept, handle, block, or otherwise react to various system requests, all without writing a single line of driver code.

Included Libraries

The .NET Edition includes several libraries (.dll files) which are supported in different environments. The following libraries are present in the lib directory after installation:

  • lib\callback.CBFSFilter.dll is designed for use in .NET Framework 4.0 and up. This is the default library which maintains a familiar API in line with previous versions of the product.

  • lib\net6.0\callback.CBFSFilter.dll is designed for use in .NET 6 and up. The .NET 6 library maintains the same API as the default library and can be used in projects that are based on .NET 6 and later.

  • lib\netstandard2.0\callback.CBFSFilter.dll is designed for use in .NET Standard 2.0 and up. The .NET Standard library maintains the same API as the default library and can be used in projects that are based on .NET Core and .NET 5 and later.

  • lib\net20\callback.CBFSFilter.dll is designed for use in .NET Framework 2.0 and up. This library targets .NET Framework 2.0 and is maintained for legacy projects.

Included Components

CBFilterThe CBFilter component allows applications to intercept and control filesystem requests.
CBMonitorThe CBMonitor component allows applications to monitor filesystem requests.
CBProcessThe CBProcess component enables applications to intercept process manager requests.
CBRegistryThe CBRegistry component allows applications to intercept and control registry requests.

Additional Information

You will always find the latest information about CBFS Filter at our web site: www.callback.com. We offer free, fully-functional 30-day trials for all of our products, and our technical support staff are happy to answer any questions you may have during your evaluation.

Please direct all technical questions to support@callback.com. To help support technicians assist you as quickly as possible, please provide an detailed and accurate description of your problem, the results you expected, and the results that you received while using our product. For questions about licensing and pricing, and all other general inquiries, please contact sales@callback.com.

Thank You!

Thank you for choosing CBFS Filter for your development needs. We realize that you have a choice among development tools, and that by choosing us you are counting on us to be a key component in your business. We work around the clock to provide you with ongoing enhancements, support, and innovative products; and we will always do our best to exceed your expectations!

Deployment

The topics in this section provide information regarding the deployment of applications built with CBFS Filter. The information in these topics should be reviewed carefully when designing a deployment strategy, because CBFS Filter's kernel mode drivers and other supplementary DLLs must be distributed along with the application for it to function correctly.

Topics

Driver Installation

At a high level, CBFS Filter consists of component-specific kernel mode drivers and user mode library libraries which work together in tandem to provide each component's functionality. Therefore, it is necessary to install a component's kernel mode driver when deploying an application built with its user mode library.

The functionality needed to install the component drivers is included in each one's user mode library, as well as in the standalone installer DLLs provided for each one. The drivers directory, located within the product's installation directory, contains the following files for each component*:

{ComponentName}.cab Contains the component's drivers and the supplementary installation/uninstallation files.
installer/{ComponentName}Inst.h A header file for the installer DLL. The installer DLL may be used on the target system to install (or uninstall) the items within {ComponentName}.cab.
installer/x64/{ComponentName}Inst.dll The C/C++ installer DLL for the x64 (AMD64) processor architecture.
installer/x86/{ComponentName}Inst.dll The C/C++ installer DLL for 32-bit x86 processor architecture.
installer/ARM/{ComponentName}Inst.dll The C/C++ installer DLL for 32-bit ARM processor architecture.
installer/ARM64/{ComponentName}Inst.dll The C/C++ installer DLL for 64-bit ARM processor architecture.
*Note: The CBMonitor component uses the same driver as the CBFilter component. Note: When the user-mode library is installed or updated on end-user systems, it is required to ensure that the kernel-mode drivers already present in the system are updated to match the version of the installed user-mode library.

NuGet Notes

If CBFS Filter is installed using NuGet, the drivers directory described above will be located within NuGet's global-packages directory at the following path (assuming NuGet's global-packages directory has not been changed): %USERPROFILE%\.nuget\packages\callback.cbfsfilter\22.0.xxxx\contentFiles\any\any\drivers.

Installation and Uninstallation via User Mode Library Methods

The component includes the following methods to install and uninstall the required files; please refer to their documentation for more information:

All of the links in this topic point to the CBFilter's copy of these methods, but they are available in all components.

Important: Uninstall must only be used when completely removing the driver. When updating the driver, this method must not be used as it may cause the OS to incorrectly remove the driver on reboot. Please refer to the "Updating the Driver" section, below, for more information.

Installation and Uninstallation via Installer DLL Functions

The installer DLL is a lightweight, stand-alone library that contains only the functionality required for installing and uninstalling the required files. It is available in both 32-bit and 64-bit versions (each of which is capable of installing both 32-bit and 64-bit drivers and helper DLLs); and may be used as desired in installation scripts, setup applications, or any other executable capable of loading dynamically-linked libraries (DLLs).

The functions exposed by the installer DLL mirror the component methods listed above. Each function is available in two forms: those with an *A suffix, which can be used with ANSI/UTF8 strings; and those with a *W suffix, which can be used with Unicode (UTF16) strings.

Updating the Driver

To update the driver, call the Install method. The new version of the driver will replace the older version. Please do not call the Uninstall method when updating the driver.

Uninstalling the Driver

To uninstall the driver completely, call the Uninstall method. If the driver cannot be immediately uninstalled, it will be marked for removal and uninstalled on the next reboot.

Use caution when calling Uninstall ; if it gets called and the driver cannot be uninstalled immediately, and then Install is subsequently called to install a new version, then upon reboot, the OS will end up uninstalling the newly-installed driver.

Important: The driver should only be uninstalled when the intent is to completely remove it from the system. Do not uninstall the driver to update it.

Reboot Requirements

Depending on the current state of the system, as well as the options chosen when installing or uninstalling the driver, the OS may need to reboot to complete the operation.

Always check the return value of the Install and Uninstall methods/functions; it will indicate whether a reboot is required .

Additional Notes

The OS treats major versions of the driver as separate products; they can operate in parallel and do not share any resources. Old major versions may optionally be removed from the system when calling Install by passing the appropriate value for its Flags parameter.

For each major version of the product, only one copy of the driver can be installed at any time. When the driver is being installed, its version is checked, and one of the following three things occurs:

  • If no driver with the same major version is currently installed, then the install procedure installs the driver as a new product.
  • If a driver with the same major version and an older minor version is currently installed, then the install procedure updates the existing driver with the new one.
  • If a driver with the same major version and a newer minor version is currently installed, then the install procedure leaves the existing driver unchanged.

When deploying files to a target system, the CAB file must remain present on the system. This file is required for uninstallation of the driver at a later time.

The product's installation code maintains a ProductGUID-based record of driver installations in the Windows Registry, creating a separate registry entry for each different ProductGUID. When the driver is "uninstalled", the corresponding registry entry is removed. The driver is only removed from the system if there are no entries left in the registry that reference the driver.

Windows 7 and Windows 2008 Server R2

Kernel-mode drivers are signed using the SHA2 algorithm. The original releases of Windows 7 and Windows 2008 Server R2 didn't support SHA2. To be able to load the newest versions of the drivers, the system needs to have certain updates installed. The updates are KB976932 (Service Pack 1 of the mentioned systems) and KB4474419 (Security Update).

Required Permissions

By default, Windows only allows installation and uninstallation of the CBFS Filter system files (kernel mode drivers and helper DLLs) to be performed from a user account which is a member of the Administrators group.

On systems where UAC is enabled, the process responsible for installing or uninstalling the system files must run with elevated permissions. Detection of current privileges and elevation of permissions is not within the scope of the component itself.

Some examples of obtaining the required permissions for driver installation and uninstallation are below.

  • Starting the application which uses the component with the "Run as administrator" option.
  • Modifying the Load and unload device drivers setting in the Local Security Policy under the User Rights Assignment section.
  • Including a manifest alongside the application indicating the requirement for elevated permissions. For instance, if a file MyApp.exe.manifest with the content below exists next to the application MyApp.exe, it will prompt for elevated permissions when started (if required).

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="ExeName" type="win32"/> <description>elevate execution level</description> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges> <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo> </assembly>

User Mode Library

Note: : The user-mode library must be deployed to end-user systems along with the kernel-mode drivers; the version of the kernel-mode drivers on the end-user systems must be equal to or newer than the version of the user-mode library. Thus, when the user-mode library is installed or updated on end-user systems, it is required to ensure that the kernel-mode drivers already present in the system are updated to match the version of the installed user-mode library.

The user-mode library comes in two pieces, both of which must be deployed along with the application:

  1. A .NET assembly (managed), named callback.cbfsfilter.dll (or callback.cbfsfilter.NetStd.dll, for .NET Standard).
  2. A native dynamic library (unmanaged), named cbfsfilter22.dll, available for both 32-bit (x86) and 64-bit (x64, ARM64) processor architectures.

When deploying the application, copy both the .NET assembly and the native library to the target system and place them next to the application's .exe file .

The .NET assembly may alternatively be deployed to the Global Assembly Cache (GAC).

Alternatively, the native dynamic library may be placed into one of directories, the paths to which are contained in the PATH environment variable, such as C:\Windows\System32 (or C:\Windows\SysWOW64 when deploying a 32-bit application on a 64-bit Windows system).

NuGet Notes

After the NuGet package is added to a project, both the managed .NET assembly and the unmanaged native library will be copied to the project's output directory anytime the project is built. However, the exact files copied to the output directory for the native library will vary based on the project type:

  • For .NET Core projects, a runtimes directory will be created in the output directory (if it does not already exist), and versions of the native library for each supported runtime identifer (RID) (e.g., win-x64) will be placed in the appropriate subdirectories. When the .NET Core application is distributed, the entire runtimes directory should be deployed alongside it.
  • For other types of projects (.NET Framework, UWP), only the native library version specific to the currently selected platform target (e.g., x64) will be copied to the output directory.
    • For .NET Framework projects specifically, please note that the project's platform target (Project > Properties > Build Tab > Platform target) must be set to a real architecture. If it is set to "Any CPU", no native library will be copied to the output directory.

The native library may alternatively be installed to the Windows system directory. This approach allows deploying both the 32-bit and 64-bit versions of the native library simultaneously, because each gets placed into the system directory that corresponds to the appropriate processor architecture.

Remember to deploy the drivers too, as they are an integral part of CBFS Filter.

General Information

The topics in this section provide general information about various aspects of the product's functionality.

Topics

Thread Safety of the API

The properties and methods provided by CBFS Filter's APIs fall into one of the following categories when it comes to thread safety:

  • Properties and methods that are intended to be accessed from event handlers (i.e., those documented as such) are thread-safe, since event handlers always execute in the context of worker threads.
  • Methods related to installation, uninstallation, and status retrieval are not thread-safe, since they are expected to be used during the application installation process. (Methods in this category are those which are documented as being "available in both the component API and the Installer DLL".)
  • Any helper methods documented in the component's API (i.e., those used to convert error codes, or provide similar supplementary functionality) don't use any explicit thread synchronization, but also don't access any other component properties or methods, and thus are inherently thread-safe.
  • All other properties and methods are not thread-safe, so applications must employ proper thread synchronization techniques when using them on multiple threads (including, but not limited to, during event handlers).

CBFilter/CBMonitor Topics

The topics in this section provide additional information specific to the CBFilter and CBMonitor components.

Topics

File Masks

File masks are "templates" against which file and directory names are matched. A file mask may optionally begin with a path, either with or without a volume name (see the next section); and both the filename part and the path part may contain single-character wildcards (?) or multicharacter wildcards (*). Following are a few examples of file masks:

  • 20??_Budget.xls
  • *.doc
  • *\Pictures\20??\*.jpg
  • \temp\*.tmp
  • C:\Reports\*

In general, file masks like C:\Reports\* will not match the C:\Reports\ directory itself, so any filter rule using this mask will therefore not match operations that target C:\Reports\ directly (such as an operation that enumerates its files and subdirectories). This behavior applies for all rules except reparse rules; a reparse rule with a source mask like C:\Reports\* will match any operation that targets the C:\Reports\ directory or any of its descendants.

Volume Names in Paths

If a file mask begins with a path, that path may optionally include a volume name. This allows applications to monitor only the volumes they are interested in. The following kinds of volume names are acceptable:

  • A volume GUID, formatted like Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\ (note the trailing backslash). A mask may start with the \\?\ prefix, such as "\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}".
  • A hidden volume mounting point, formatted like \\.\mounting_point_name\.
  • A DOS name, formatted like C:\.
  • A network resource, formatted like \\server_name\share_name\ (please refer to the Monitoring Network Resources topic for more information).
  • A volume NT-native name, formatted like \Device\HarddiskVolumeX\, where X is the number of the volume.

Note: To successfully add a rule with a file mask that includes a volume name, the specified volume must already be present on the system. Applications that wish to add rules for volumes that are not currently present can do one of the following things:

  1. Add rules without volume names and selectively skip volumes as desired by setting the BeforeFilterAttachToVolume event's SkipVolume parameter to true.
  2. Add and remove volume-specific rules "on-demand" using the AfterFilterAttachToVolume and AfterFilterDetachFromVolume events.
(The aforementioned events are available in both CBFilter and CBMonitor.)

Mask Modifiers

Inverted Masks

An inverted mask starts with two pipe characters ("||"), such as ||file_mask. It inverts (negates) the result of matching the name to the mask. This syntax is an alternative to using passthrough rules. It can be used to slightly speed up operations: an inverted mask requires one rule, whereas the use of a passthrough rules introduces a secondary bypass rule to match.

Matching of Alternate Data Streams' Names

An alternate data stream (ADS) is a secondary file stream with its own name that follows the name of the file. An ADS full name looks like \path\to\filename.ext:streamname:$streamtype where the "streamname" part can be empty. Thus, to track events that happen specifically on ADS, you need to write the mask in the way that the ADS name matches it. A simple mask to track operations on all file's ADS is filename.ext:*. More complex use of wildcards in such a mask is possible as well.

Exclusion of Alternate Data Streams

Most "simple" masks match both the main name of the file and all of file's alternate data streams (named streams). To track operations that occur with a file but not its ADS, append ":|" to the filename in the mask (e.g., filename.ext:|).

Note: Such a mask covers operations on the specific ADS names that denote the main file or directory's content, that is, "::$DATA" (main data stream of a file), "::$INDEX_ALLOCATION", and ":$I30:$INDEX_ALLOCATION" (both identify a directory's content stream). If you want to exclude operations on these streams, use passthrough rules.

Per-Process Masks

Masks used by standard filter rules and access rules can be restricted so that they only match operations made by a specific process (or, made by all processes except a specific process). To do this, construct a mask in one of the following forms:

  • process_name.exe|file_mask: Only matches operations requested by process_name.exe.
  • ~process_name.exe|file_mask: Only matches operations not requested by process_name.exe.
  • process_id|file_mask: Only matches operations requested by the process whose Id is process_id.
  • ~process_id|file_mask: Only matches operations not requested by the process whose Id is process_id.

In all cases, file_mask can be any valid file mask as described above. The process_name.exe portion must be a valid process executable filename, and may optionally begin with a path. Wildcards are supported in any part of the process_name.exe portion. The process_id portion must be a numeric process Id (PID). When adding a PID-based rule, you need to be aware of the PID Reuse behavior of Windows.

Contexts

It is often necessary for an application to associate certain information with a given file/directory, file handle, or enumeration operation. To assist developers in doing so in a convenient and performant manner, the CBFilter component provides context parameters in a number of events.

A context carries an application-defined value that identifies or points to some application-defined data, and each file/directory, file handle, and enumeration operation has a separate context associated with it. The CBFilter component treats context values as opaque; it stores the context values passed to it by the application and ensures that the correct values are exposed again whenever some event fires for a particular file, handle, or enumeration; but otherwise, it does not attempt to use said values in any way.

Note: Contexts are not available in the CBMonitor component.

Context Lifetimes

Contexts in CBFilter can be grouped into a few categories, each of which is subject to a different lifetime:

  • File contexts and directory contexts, which are associated with an open file or directory.
  • Handle contexts, which are associated with a specific open file or directory handle.
  • Enumeration contexts, which are associated with an ongoing enumeration.

File/directory contexts are created the first time a file or directory is opened, and they live until the last handle to that file or directory is closed. Handle contexts, in contrast, are created every time a file or directory is opened, and they live only until the associated file handle is closed. For example, consider the following sequence of operations:

Operation on File X Context Creations/Deletions Active Contexts
1. Opened by process A File context FX and handle context HXA created FX, HXA
2. Opened by process B Handle context HXB created FX, HXA, HXB
3. Closed by process B Handle context HXB deleted FX, HXA
4. Opened by process C Handle context HXC created FX, HXA, HXC
5. Closed by process A Handle context HXA deleted FX, HXC
6. Closed by process C File context FX and handle context HXC deleted

File/directory contexts are available in all Control Events corresponding to operations performed on some open file or directory, and handle contexts have similar availability. Enumeration contexts are created anytime a new enumeration operation begins and live until the enumeration operation ends.

All contexts, when created, are created before their corresponding "first event" fires (e.g., AfterOpenFile, AfterEnumerateDirectory). When deleted, all contexts are deleted after their corresponding "last event" fires (e.g., AfterCloseFile, AfterCloseEnumeration). If, however, a context's "first event" fails, whether as expected (e.g., due to Security Checks) or otherwise (see Error Reporting and Handling), then that context's value is immediately discarded because its corresponding "last event" will not ever fire. (Contexts are not available in the BeforeOpenFile or BeforeCreateFile events because it is unknown whether such requests will succeed.)

Note: The components offer a special event, CleanupContext, which is the ultimate last event for the open file lifecycle. This event lets you dispose of the data, associated with file and handle contexts. It is recommended that contexts are deleted not in a AfterCloseFile event, but in CleanupContext. This will guarantee that there is no race condition between file closing and reopening, in which case such race condition could lead to an invalid context value coming into play.

Context Use Cases

Contexts are most helpful when used to store information associated with a file/directory or file handle. Typically, contexts are initialized during their corresponding "first event", and then are used in subsequent events to speed up those operations.

Event contexts are used to pass information between event handlers of Before* events and the related handlers of the corresponding After* event fired during handling of the same OS request.

Applications are free to obtain and store whatever information they wish using contexts, as long as their event handlers comply with the restrictions described by the Avoiding Deadlocks and Recursive Calls topics.

Note: Although contexts usually come into play when the file is opened, the complex architecture of Windows filesystem filter stack makes it possible that some event, related to the opened file, fires ahead of the "first event" (i.e., before AfterCreateFile/AfterOpenFile/AfterEnumerateDirectory).

Using Contexts

In .NET, context parameters are IntPtr-typed. You can store either an Int64 value or a reference to the object in those parameters. Storing Int64 values is used to keep keys of dictionary records, so that the stored values act as "handles" to the real data in the dictionary.

To store an integer value, use the IntPtr(Int64) constructor. To retrieve the stored value, use the IntPtr.ToInt64 method.

To store a reference to an object in a context, create a GCHandle instance using said object (so that it will not be garbage collected), and then use it to obtain an IntPtr: Stream stream; // The object whose reference will be stored in the context. Context = GCHandle.ToIntPtr(GCHandle.Alloc(stream));

Then, to access the object in a later event using the IntPtr stored in the context, do the following: // Guard against empty context. Stream stream = (Context != IntPtr.Zero) ? (Stream) GCHandle.FromIntPtr(Context).Target : null;

Finally, before a Context is discarded, be sure to free the GCHandle instance so that the referenced object can be garbage collected, if needed. // Guard against empty context. if (Context != IntPtr.Zero) GCHandle.FromIntPtr(Context).Free();

This scheme also can be used to store primitives (via "boxing") and other value types (nonobjects).

Avoiding Deadlocks

As the Cached and Non-Cached Requests topic describes, it is common for the filesystem requests intercepted by a CBFilter/CBMonitor-based application to have been sent by the system's cache manager rather than by an actual process. Consequently, it is critical to keep the following restrictions in mind when implementing the application's event handlers:

  • Event handlers must not perform any operations, explicitly or implicitly, against files opened in buffered mode. Any file accessed from an event handler must be opened using the Windows API's FILE_FLAG_NO_BUFFERING flag.
  • Event handlers must not perform any asynchronous procedure calls (APCs).
  • User interface operations must be strongly restricted.
  • Plus, all CBFilter/CBMonitor-specific restrictions discussed in the Recursive Calls topic.

Events handlers that violate any of the restrictions described here will cause a system-wide deadlock.

Security Checks

The CBFilter component offers flexible security handling. During Control Events, applications can use information obtained from security-related methods to determine whether a request should be allowed as-is, modified before continuing, or denied immediately.

CBFilter provides a number of methods that applications can use to implement security checks. The most notable of these methods are GetOriginatorProcessName and GetOriginatorProcessId, which return the name and process Id (PID) of the process that initiated the request; and GetOriginatorToken, which returns the system-defined security token of the process that initiated the request.

The latter is particularly useful when used with various methods in the Windows API, such as the GetTokenInformation function, which can be used to obtain various pieces of information about the object the token is associated with.

Effective security enforcement does not require that all event handlers perform security checks. Applications are technically free to deny almost any file-related event because of a failed security check. It is not, however, meaningful to perform security checks in all event handlers in the first place, and unnecessary security checks will decrease an application's overall performance.

For example, it makes sense to validate access rights in the BeforeCreateFile, AfterCreateFile, BeforeOpenFile, and AfterOpenFile event handlers, but not in the AfterReadFile or BeforeWriteFile event handlers. If an application denies a file create/open request made by some process, then that process will not be able to make a subsequent read/write request. Therefore, applications can safely assume that all read/write requests come from processes whose access rights they have already verified. Similar logic can be applied for directories and directory enumerations.

Note: This is not an exhaustive set of use-cases; each application's needs will differ.

As stated earlier, applications are free to allow, modify, or deny any request based on security checks. However, they must not "selectively alter" filesystem information based on these checks; it is "all or nothing". Following are some examples to clarify implementation:

  • A filesystem object cannot appear to exist to process A, but appear nonexistent to process B.
  • A filesystem object cannot be reported as a file to process A, but as a directory to process B.
  • A filesystem object's metadata, absent of actual changes, must be consistent between requests (e.g., if a file's size is reported as 1 KB to process A, then it must also be reported as 1 KB to process B).
  • A file's contents, absent of actual changes, also must be consistent between requests (e.g., for a file whose size is reported as 1 KB, exactly 1024 bytes must be returned when the file is read, and those 1024 bytes must be exactly the same, including ordering, regardless of which process is doing the reading).

File Create/Open Events

The CBFilter component provides three pairs of events related to creating and opening files:

Note: The Notification Events are also available in CBMonitor; please refer to the Event Types topic for more information.)

Files can be created or deleted at any time, so there is no way for the OS to know with complete certainty whether a particular file exists until an interested process actually attempts to access it. This is true even if the process checks whether the file exists beforehand, because that file could then be created/deleted in the time between when the check occurred and when the create/open call occurs.

For this reason, the same Windows API function, CreateFile, is used for both creating and opening files. Processes that call this function use its CreationDisposition parameter to specify what the OS and filesystem should do if the file exists/does not exist. The one and only CreationDisposition option that results in a "create file" request is CREATE_NEW; all other options result in an "open file" request, and the filesystem then uses the CreationDisposition for guidance.

Because the component's only source of information is the requests themselves, they also have no way of knowing whether a particular file exists (or not) at any given time. Thus, they simply act in the following manner:

  • If the request's CreationDisposition is CREATE_NEW, then the *CreateFile events are used.
  • If the request's CreationDisposition is FILE_SUPERSEDE (an NT-native flag used in the kernel), then the *OpenFile events are used, followed by the corresponding *CreateFile events.
  • In all other cases, the *OpenFile events are used.

Cached and Non-Cached Requests

Windows has an extremely robust file caching system that it makes extensive use of to provide optimal file I/O performance at all times. To accomplish this, file read/write requests are routed to the cache manager by default, and the cache manager attempts to service said requests with as few actual filesystem calls as possible. These behaviors result in a file I/O model that has three separate "paths" for file data to flow over:

  1. From an application (or system component) to the system file cache.
  2. From the system file cache to the filesystem.
  3. From an application to the filesystem (bypassing the system file cache).

By default, the CBFilter and CBMonitor components track file read/write requests only on paths (2) and (3); such operations are referred to as noncached requests (or, noncached operations). To include requests on path (1) (referred to as cached requests/operations), the ProcessCachedIORequests property must be enabled. This property is disabled by default, because in most cases, it is not necessary to intercept cached requests.

To distinguish between cached and noncached file read/write requests, applications can check the Direction parameter provided in the following events:

Note: All API members discussed in this topic are available in both CBFilter and CBMonitor, except for the Control Events, which are available only in CBFilter.)

Monitoring Network Resources

In certain cases, it may be desirable for a CBFilter/CBMonitor-based application to be able to track filesystem operations performed on a remote system, such as a file server. It is important to understand the limitations of Windows' filesystem filtering mechanisms to maintain reasonable expectations when developing for such use-cases.

The CBFS Filter system drivers must be installed on a machine for an application built with CBFilter or CBMonitor to be able to track filesystem requests on it; and, similarly, the CBFilter and CBMonitor components can only track filesystem requests that are made against a local filesystem.

For example, imagine an environment with a file server S, and two client machines C1 and C2. If C1 and C2 have both mounted the filesystem shared by S as a network drive, then two options are available for tracking all requests directed at that filesystem:

  1. Install the application on S and track filesystem operations on the shared drive.
  2. Install the application on both C1 and C2 and track filesystem operations on the mounted network drive.
In the latter case, it is necessary to install the application on both client machines because the requests that originate on C1 cannot be seen on C2, and vice versa.

Request Modification

Modification of file read/write requests will only work correctly for local filesystems due to how Windows actually transfers the data internally. Attempting to modify the file data carried by a read/write request made against a locally mounted network drive will always fail.

CBRegistry Topics

The topics in this section provide additional information specific to the CBRegistry component.

Topics

Registry Key Masks

Registry key masks are "templates" against which registry key names are matched. A registry key mask may begin with a "registry key path" or may simply be a standalone key name; and both the key name part and the path part may contain single-character wildcards (?) or multicharacter wildcards (*). Following are a few examples of registry key masks:

  • \REGISTRY\MACHINE\Software\*
  • HKEY_LOCAL_MACHINE\Software\*
  • *Microsoft*

Note: Some registry keys are reparse points, and the driver cannot match masks that contain the names of such reparse points. For example, "HKEY_LOCAL_MACHINE\System\CurrentControlSet" is a reparse point; thus, the rule to track operations on its subkeys must refer to targets and not to the reparse point. As a result, the following sample rule will work: "HKEY_LOCAL_MACHINE\System\*ControlSet*\Enum" (here, asterisks are wildcard marks to let the rule cover various "ControlSetNN" keys).

Contexts

It is often necessary for an application to associate certain information with a given registry key. To assist developers in doing so in a convenient and performant manner, the CBRegistry component provides context parameters in a number of events.

A context carries an application-defined value that identifies or points to some application-defined data, and a registry key has a separate context associated with it. The CBRegistry component treats context values as opaque. It stores the context values passed to it by the application and ensures that the correct values are exposed again whenever some event fires for a particular registry key; but otherwise, it does not attempt to use said values in any way.

Context Lifetimes

Key contexts in CBRegistry are available in all events that correspond to registry key operations. They are created before the BeforeCreateKey or BeforeOpenKey event fires, and they are deleted after the AfterCloseKey event fires (or, more accurately, after the CleanupKeyContext event fires).

Context Use Cases

Key contexts are most helpful when used to store information associated with a registry key that can be used to speed up later events. For example, the only time the CBRegistry component exposes the name of a registry key is during the BeforeCreateKey and BeforeOpenKey events. Applications that wish to use the key name in later events can store it in the key context and then access it in the desired events later. A similar strategy can also be applied for events related to registry key values.

More generally, applications are free to obtain and store whatever information they wish using contexts, as long as their event handlers comply with the restrictions described by the Recursive Calls topic.

Using Contexts

In .NET, context parameters are IntPtr-typed. You can store either an Int64 value or a reference to the object in those parameters. Storing Int64 values is used to keep keys of dictionary records, so that the stored values act as "handles" to the real data in the dictionary.

To store an integer value, use the IntPtr(Int64) constructor. To retrieve the stored value, use the IntPtr.ToInt64 method.

To store a reference to an object in a context, create a GCHandle instance using said object (so that it will not be garbage collected), and then use it to obtain an IntPtr: Stream stream; // The object whose reference will be stored in the context. Context = GCHandle.ToIntPtr(GCHandle.Alloc(stream));

Then, to access the object in a later event using the IntPtr stored in the context, do the following: // Guard against empty context. Stream stream = (Context != IntPtr.Zero) ? (Stream) GCHandle.FromIntPtr(Context).Target : null;

Finally, before a Context is discarded, be sure to free the GCHandle instance so that the referenced object can be garbage collected, if needed. // Guard against empty context. if (Context != IntPtr.Zero) GCHandle.FromIntPtr(Context).Free();

This scheme also can be used to store primitives (via "boxing") and other value types (nonobjects).

Security Checks

The CBRegistry component offers flexible security handling. During events, applications can use information obtained from security-related methods to determine whether a request should be allowed as-is, modified before continuing, or denied immediately.

CBRegistry provides three security-related methods that applications can use to help implement security checks. They are GetOriginatorProcessName and GetOriginatorProcessId, which return the name and process Id (PID) of the process that initiated the request; and GetOriginatorToken, which returns the system-defined security token of the process that initiated the request.

The latter is particularly useful when used with various methods in the Windows API, such as the GetTokenInformation function, which can be used to obtain various pieces of information about the object the token is associated with.

Driver Altitudes

A key benefit of filter drivers in general is that any number of them can be active at the same time. To keep things organized, Windows maintains a separate stack of filter drivers for each applicable system component (filesystem, registry, and process manager) and ensures that each stack is sorted consistently based on the drivers' altitudes.

These altitudes, which are expressed in a string notation as numbers with an optional fractional part (e.g., "12345.768"), essentially define each driver's absolute position in the stack. Drivers with higher altitudes are attached toward the top of the stack, closer to user mode, whereas drivers with lower altitudes are attached toward the bottom of the stack, closer to the applicable system component. Please refer to Microsoft's Load Order Groups and Altitudes for Minifilter Drivers article for more information about altitudes (much of the content is specific to filesystem filter drivers, but the general concepts apply to all filter drivers).

When an operation is requested, that request "enters" the top of the filter driver stack and moves downward, toward the applicable system component. Once the request has been handled (either by the system component or by one of the filter drivers in the stack), a response travels back up the stack. So the process of choosing a suitable altitude depends primarily on the intended functionality of the filter application being developed. That said, some factors are specific to each type of filter driver; please refer to the sections below for more information.

Filesystem Minifilter Drivers

Of the three kinds of filter drivers mentioned above, filesystem filter drivers are by far the most complex, which is why much of Microsoft's altitude documentation is presented from a filesystem-centric context. To prevent collisions, Microsoft also manages all filesystem minifilter altitude assignments.

When developing an application that uses CBFilter and/or CBMonitor, an altitude must be requested from Microsoft. Use the instructions described in their Minifilter Altitude Request article; and be sure to specify "FileSystem" (or "Both") for the "Filter type:" field when composing the request.

Once Microsoft has assigned an altitude for the application, it should be specified using the Altitude property or the Altitude parameter of the Install method, which are available in both CBFilter and CBMonitor.

Registry Filter Drivers

Registry filter drivers are not required to have an altitude (in which case they will be attached near the top of the driver stack), but it is recommended that one be requested anyway. Please refer to Microsoft's Supporting Layered Registry Filtering Drivers article for more information.

Although not explicitly stated in the aforementioned article, registry filter driver altitudes can be requested from Microsoft in the same manner as they are for filesystem minifilter driver altitudes. Use the instructions described in their Minifilter Altitude Request article; and be sure to specify "Registry" (or "Both") for the "Filter type:" field when composing the request.

Once Microsoft has assigned an altitude for the application, it should be specified using CBRegistry's Altitude property.

Process Manager Filter Drivers

Microsoft is fairly vague about altitudes for process manager filter drivers; there is essentially no information about them beyond confirmation of their existence, as the documentation for the OB_CALLBACK_REGISTRATION structure shows. Notably, it is unclear whether there is a standard way to request an altitude for a process manager filter driver as there is for the other two kinds of filter drivers.

With that in mind, applications are free to set CBProcess's Altitude property as desired. CBProcess also provides an extra property, StrictAltitude, which specifies how the component should behave if the chosen altitude is already in use.

Event Handling

The topics in this section provide information about event handling.

Topics

Event Types

The events provided by the CBFS Filter components generally fall into two categories: Control Events, which are synchronous; and Notification Events, which are asynchronous.

Control Events allow an application to control the execution of an operation. They are fired before a request reaches the applicable system component. For certain operations, they also are fired after the request is handled (i.e., as its response comes back).

Control Events have names like BeforeOperation and AfterOperation (except for CBProcess, whose events do not have a prefix). In the CBProces component all events are Control Events that occur before the operation is completed.

Notification Events, which have names like NotifyOperation, inform an application that an operation has been performed. They are fired as a response comes back (specifically, after the applicable AfterOperation event fires, if such an event exists).

To get a better idea of the general event flow for an operation, please refer to this diagram:

  1. A process sends a request, causing the corresponding BeforeOperation event to fire synchronously. The BeforeOperation events allow an application to do the following things:
    • Allow the request to continue, potentially after modifying its parameters/data.
    • Handle the request itself.
    • Deny the request entirely.
    • Store information about the request in the event's contexts, so that it can be used later during the AfterOperation event.
  2. Once the request gets to the applicable system component, the requested operation will occur, and a response will be sent back to the process, causing the corresponding AfterOperation event to fire synchronously. The AfterOperation events allow applications to do the following things:
    • Perform an action based on whether the operation succeeded or failed.
    • Modify the response (if the operation supports doing so).
    • Do something earlier with the information stored in the event's contexts during the BeforeOperation event.
  3. The response continues onward toward the process, causing the corresponding NotifyOperation event to fire asynchronously. The NotifyOperation events cannot be used to modify responses, nor do they include event contexts; they are best-suited for doing things like audit logging and change journaling.
    • More specifically, notification events are queued for delivery, and fired on a "best-effort" basis.
    • The notification event queue's size is not artificially limited; it will continue to grow (if necessary) so long as the system has sufficient resources available.

Note: The system can have multiple filter drivers loaded simultaneously, and any filter driver that a request or response "reaches" can do any of the things described above. Please refer to the Driver Altitudes topic for more information.

Each of the CBFS Filter components provide a different set of events for each operation, so the event flow for a particular operation may be simpler than the one shown here depending on which component is being used. Following is a quick summary of which events each component offers:

For more information about how to use event contexts in CBFilter, please refer to this topic; and for more information about how to use them in CBRegistry, please refer to this topic.

Buffer Parameters

Some events include one or more parameters intended for use as a binary data buffer. Depending on the event, these parameters may contain data when the event is fired, or it may be expected that the application populates them with the desired amount of data during the event handler. Some events combine both paradigms and then expect the application to modify the data already present when the event is fired.

The documentation for such events will describe which of these cases applies to each buffer parameter. In all cases, buffer parameters point to a preallocated block of unmanaged memory, the size of which is specified by the parameter immediately following the buffer parameter. In cases in which data are to be written, be sure to write it directly to the pointed-to memory, do not change the value of the buffer parameter itself.

Buffer parameters are always of the IntPtr type; use the .NET Marshal.Copy() method to read and write data from and to the unmanaged memory region. When targeting newer .NET versions, such as .NET Standard 2.1 and later, applications can use the Span<T> and ReadOnlySpan<T> classes to access and modify the unmanaged memory region without extra data copying.

Recursive Calls

To ensure stable operation, it is critical that applications avoid recursive access to the system component associated with each component. Essentially, this means that event handlers must comply with the following restrictions, which vary by component:

  • CBFilter and CBMonitor: Event handlers must not attempt to perform any operations that involve the file or directory for which the event was fired.
  • CBProcess: Event handlers must not perform any operations that cause a process or thread to be created or terminated.
  • CBRegistry: Event handlers must not perform any operations that cause registry access (either directly or indirectly).

    Note: Many system operations in Windows will perform registry access as part of their normal execution, and this side-effect is rarely documented (if ever).

Event handlers that violate any of these restrictions are likely to cause a system deadlock.

Additional information about third-party filters: Even when a file or registry operation seems to be generally safe, some third-party filter drivers may be not prepared for such recursive operations and will deadlock. Such filters must be dealt with on a case-by-case basis (usually by disabling them).

Threading and Concurrency

Through the use of multithreading, CBFS Filter provides powerful concurrency features to help applications maximize their performance. Each component provides the following API members to allow applications to specify the extent to which events should be fired concurrently:

  • The SerializeEvents property controls whether events should be serialized on a single worker thread or fired in parallel on several. By default, this property is disabled and events are allowed to fire in parallel.
  • The MinWorkerThreadCount and MaxWorkerThreadCount configuration settings control the minimum and maximum number of worker threads the components can use for firing events. By default, both are set to 0, which indicates that a component's system driver should automatically choose appropriate values based on how many CPU cores the system has.

Note: Even when configured for minimal concurrency, the components always fire events in the context of a worker thread, not in the thread the component was originally created on. Therefore, applications must be sure to synchronize operations between event handlers and other threads as necessary (including, but not limited to, calls to the component instance, unless a method is explicitly documented as callable within events).

Timeouts

(This topic references methods of the CBFilter component; the same methods exist in CBProcess and CBRegistry components as well.)

Because the CBFS Filter components' Control Events are tied directly to the underlying operations' requests and responses, it is critical that their event handlers complete quickly to prevent the system from being blocked. To help prevent such blocking, the components' system drivers can enforce event timeouts.

To enable event timeouts, pass a nonzero value for the Timeout parameter when calling the StartFilter method. Passing 0 will disable event timeouts, in which case, events may take as long as necessary to execute.

When timeout enforcement is in effect, and an event executes long enough for its timeout to expire, the driver either "releases" the underlying request (passing it onward unchanged), or cancels it by reporting an error; whichever is most appropriate for the event in question. The tardy event still runs to completion, but any results it returns once finished are ignored because the underlying request has already passed through the filter driver.

If an event handler knows it will require additional time to complete an operation, it can call the ResetTimeout method before the current timeout expires to restart its timeout timer.

Applications should always strive to ensure that all event handlers complete quickly, even if request timeouts are disabled. Do not perform time-consuming work within event handlers; offload such work to background threads.

Note: This information is less relevant for Notification Events, which, because they fire asynchronously, cannot block the system. The CBMonitor component, therefore, does not expose a Timeout parameter in StartFilter, or a method for resetting event timeouts; it operates without event timeout enforcement.

File and Registry Filter Rules

In their default state, the CBFS Filter components ignore all operations; applications must explicitly specify which operations they are interested in by adding one or more filter rules. This "opt-in" approach prevents applications from being overwhelmed by the constant flood of operations occurring on a system at all times.

At a high level, there are two basic categories of filter rules: standard filter rules, which the components use to determine which operations they should (or should not) fire events for; and special filter rules, which alter or augment the component's behavior in a variety of ways. The following sections discuss each category of filter rules in more detail, and provide component-specific information, where applicable.

Standard Filter Rules

Standard filter rules are typically an integral part of a CBFS Filter-based application's design. Thousands of operations may be occurring on a system at any given moment, and rarely are applications interested in more than a small subset of them. To start receiving events for those "interesting" operations, applications must add one or more standard filter rules so that the CBFS Filter driver knows which operations it needs to monitor.

For the CBFilter, CBMonitor, and CBRegistry components, standard filter rules always contain two key pieces of information:

  1. A mask that determines which files or registry keys the filter matches (or "covers"). The CBFilter and CBMonitor components use File Masks, while the CBRegistry component uses Registry Key Masks.
    • For CBFilter and CBMonitor, standard filter rules can also include additional qualifiers like file size and attributes, but the mask always takes precedence.
  2. A set of flags that specifies what kinds of filesystem/registry operations the component should fire events for.

Together, this pair of parameters gives applications great flexibility, allowing them to create filter rules that are as broad or as narrow in scope as desired. For example, one application might wish to monitor any and all operations performed on files or registry keys whose name contains a specific word, whereas another application might only care about read operations performed on audio files in a specific directory, or on values of a specific registry key.

The CBFilter, CBMonitor, and CBRegistry components provide the following methods for managing standard filter rules:

For the CBProcess component, whose design is far less complex than the other component's design, standard filter rules are much simpler. Applications specify which processes they wish to monitor and ignore by name and/or PID using the following methods:

For all components, standard filter rules are deactivated and deleted when the application exits.

Special Filter Rules

In addition to standard filter rules, the CBFilter, CBMonitor, and CBRegistry components also support special filter rules. Unlike standard filter rules, special filter rules determine when a component should do something other than fire its events. There are multiple types of special filter rules, each of which alters (or augments) a component's behavior in a different way.

The following table provides links to topics with more information about each type of special filter rule, as well as information about which types are supported by each component.

Note: The CBProcess component does not support any special filter rules.

Rulesets

All rules, regardless of their type, are stored in some sort of ruleset; and within a ruleset, rules are uniquely identified by their masks. Adding multiple rules with the same mask to a particular ruleset will result in a single aggregate rule. Knowledge of this behavior is helpful for understanding how to use the methods that add and delete rules.

The number of rulesets each component has depends on its complexity. The most complex component, CBFilter, has four rulesets:

  • One for standard filter rules and access rules (please refer to the Access Rules topic for more information on how this works).
  • One for default rules.
  • One for passthrough rules.
  • One for reparse rules.

Access Rules

Access rules are a type of special filter rule supported by the CBFilter and CBRegistry components. Access rules instruct the component's system driver to automatically process certain requests automatically in a certain manner, without involving the component itself.

Like standard filter rules, access rules use either a file mask or a registry key mask to determine which operations should be handled automatically. For CBFilter, access rules also can include additional qualifiers, such as file size and attributes; however, as with standard filter rules, the mask always takes precedence.

By adding a matching access rule, applications can effectively make one or more files or registry keys read-only, write-only, inaccessible, or protected from deletion. Because the desired access restrictions are enforced by the component's system driver, the application will not have to handle any events, which increases their overall performance and efficiency (especially if the application's sole purpose is access control).

If file creation and opening is covered by one or several rules in a way that both access flags and callback or notify flags should be in effect, access flags are ignored to let the process receive events for operations, specified using those callback and notify flags.

The methods that the CBFilter and CBRegistry components provide for managing standard filter rules also are used to manage access rules:

Access rules are stored in the same ruleset as the standard filter rules. As the File and Registry Filter Rules topic describes, each rule in a ruleset must have a unique mask; therefore, access rules and standard filter rules with the same mask are aggregated into a single rule. Knowledge of this behavior is helpful for understanding how these methods work.

Access rules are deactivated and deleted when the application exits. For use cases in which this is undesirable, applications may wish to use default rules instead; they provide the same functionality, but are managed by the component's system driver, and thus are enforced any time it is loaded, regardless of whether the application itself is open.

Default Rules

Default rules are a type of special filter rule supported by the CBFilter and CBRegistry components. Default rules work the same way that access rules do, with one notable exception: they are managed by a component's system driver rather than by the component itself. As a result, they become active as soon as the component's system driver loads at boot time, and then they continue to be enforced at all times, regardless of whether the application that originally added them is open.

Note: Default rules have lower priority that all other filter rules. This means that if or when the application opens and begins to add other kinds of filter rules, any rules that "overlap" a default rule (i.e., those whose masks match one or more of the files or registry keys covered by a default rule) will take precedence, overriding the applicable default rule. When such a rule is removed (either directly or because of the application closing), the default rule that it was overriding will become active again.

The CBFilter and CBRegistry components provide the following methods for managing default rules:

The component's system driver stores information about default rules in the registry under the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services key, which has restricted accessibility. Applications must therefore be running with Administrator or System Service rights (or their equivalent) to successfully add or remove default rules. (Running the application from an account that belongs to the administrator's group is not sufficient.)

Note: Default rules only work when a component's system driver is loaded. This means that default rules will not be available, for example, if the system boots in safe mode. Please refer to the Loading Drivers in Safe Mode topic for more information.

Passthrough Rules

Passthrough rules are a type of special filter rule supported by the CBFilter, CBMonitor, and CBRegistry components. Passthrough rules instruct the component's system driver to explicitly exclude certain requests from processing, thus counteracting any standard filter rules or access rules that they otherwise would match.

Like standard filter rules, passthrough rules use either a file mask or a registry key mask to determine which files/directories or registry keys match. For CBFilter and CBMonitor, passthrough rules can also include additional qualifiers like file size and attributes; however, as with standard filter rules, the mask always takes precedence.

When adding a passthrough rule, applications can specify one or both of the following things:

  • Which specific filesystem/registry operations the component should not fire events for (to counteract standard filter rules).
  • Which specific access restrictions the component's system driver should not apply (to counteract access rules).

The CBFilter, CBMonitor, and CBRegistry components provide the following methods for managing passthrough rules:

Passthrough rules are deactivated and deleted when the application exits.

Reparse Rules

Reparse rules are a type of special filter rule supported by the CBFilter component. Reparse rules are used to redirect file or directory access to another location based on two file masks: a source mask used for matching (in the same way as described for standard filter rules); and a destination mask to specify the location to redirect to.

For each wildcard (* or ?) present in the source mask, there must be a corresponding wildcard (of the same type) in the destination mask; and the wildcards in the destination mask must appear in the same order as they do in the source mask. For example, if the source mask is 20??_Budget.*, then 20??_Budget_Report.* would be a legal destination mask; however, 20??_Budget_Report.xls would not be a legal destination mask, nor would 20*_Budget_Report.*.

To use reparse rules effectively, it is important to understand two things about how they behave:

  1. Reparse rules have priority over all other types of rules. So, if a file or directory matches a reparse rule, then it will always be redirected, even if it matches other types of rules as well.
  2. The rule-matching procedure "restarts" every time a redirection occurs. So, if the newly redirected file or directory matches another reparse rule, then it is redirected again (and the matching procedure restarts again); otherwise, the matching procedure proceeds to consider other types of rules, as usual.

The second behavior is especially notable because it means that multiple reparse rules can "chain" together and be applied in succession. This is a powerful feature, but it must be used carefully; if a cycle of reparse rules is allowed to form, triggering it will send the system driver into an infinite loop, causing a system-wide deadlock.

The CBFilter component provides the following methods for managing reparse rules:

Reparse rules are managed by the component's system driver rather than by the component. As a result, they will remain active until they are explicitly removed or the system reboots (whichever occurs first), regardless of whether the application that originally added them remains open.

Applications that require more advanced redirection logic can add a standard filter rule that includes the FS_CE_REPARSE_FILENAME control event flag, and then can use the ReparseFileName event to implement it.

Note: Neither this event, nor the ReparseWithTag event, are directly related to the reparse rules.

Network Filter Rules

In their default state, the CBFS Filter components ignore all operations; applications must explicitly specify which operations they are interested in by adding one or more filter rules. This "opt-in" approach prevents applications from being overwhelmed by the constant flood of operations occurring on a system at all times.

The CBNETWORKcomponent provides the following methods for managing standard filter rules:

  • AddFilterRule
  • DeleteFilterRule
  • DeleteAllFilterRules

Filter rules are deactivated and deleted when the application exits.

Passthrough Rules

Loading Drivers in Safe Mode

When booting in Safe Mode, Windows loads only a limited set of drivers. If circumstances require that one or more of the CBFS Filter drivers be loaded in Safe Mode, this can be accomplished by adding the filenames of the applicable drivers to the following registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot.

Warning: Attempting to load the CBFS Filter drivers in Safe Mode can render the system unbootable if the driver fails or (for the CBFilter and CBRegistry components' drivers in particular) if the Default Rules added using the CBFilter or CBRegistry component prevent the system from accessing any of the files or registry keys it needs to boot.

PID Reuse

When using various rules that are based on process IDs (PID), you need to be aware that Windows tends to reuse PID numbers. Once the process with a certain PID is finished in any way, Windows can re-use this PID for another process being started. And it does reuse PIDs quite frequently for the purpose of keeping PID numbers low.

Such reuse can cause unexpected and sometimes unpleasant consequence for your application. To counteract it, you can take one or both actions:

  1. Open a handle to the process with the needed PID and not close it as long as your rule exists. Windows documentation states that as long as there exists an open handle to a process, its PID is not reused.
  2. Track completion of the process with the given PID (either by monitoring the state of the process by its handle or using CBProcess component of the CBFS Filter product) and once the process is finished, delete the corresponding rule.

Error Reporting and Handling

Error Codes

The CBFS Filter communicates errors using the Win32 error codes defined in WinError.h, which is part of the Windows Platform SDK. The CBFS Filter system drivers, however, use NT native error codes, which do not have one-to-one mappings with Win32 error codes. The component includes logic for converting between the two as necessary, and that logic can be updated if any codes are not covered.

Additionally, CBFS Filter uses use certain error codes in a special manner. For more information about such error codes, please refer to the Error Codes page (available for each component).

Reporting Errors to the Component from Event Handlers

If an event has a ResultCode parameter, an event handler can use it to return the result code of the operation to the component. The ResultCode parameter is set to 0 by default, which indicates the operation was successful.

If an unhandled exception occurs in the event handler, it will be caught by the component, which will fire the OnError event.

In some events, the OS does not expect the error code to be returned and either the component or the OS ignores the returned error code. Please refer to the description of a particular event for more information.

How to Handle Errors Reported by the Component

If an error occurs, the component will throw an exception. The Code property of the exception object will contain an error code, and the Message property will contain an error message (if available).

Extended Logging in Windows

Some component methods in CBFS Filter are capable of writing extended information about reported errors to the Windows event logs, which can be viewed using the system's eventvwr.exe tool. The user mode part of the component writes to the "Windows Logs \ Application" folder, while the kernel mode part writes to the "Windows Logs \ System" folder.

The information written in the extended logs is meaningful to the Callback Technologies development team, but not to end-users, so extended logging is disabled by default. If issues occur during the installation of the CBFS Filter system drivers, or while using the component, please do the following:

  1. Enable extended logging (see below).
  2. Replicate the issue.
  3. Using Event Viewer (eventvwr.exe), export the event log entries from the locations mentioned above in native format (please restrict the scope of the export to just those entries related to CBFS Filter).
  4. Submit an issue report that includes the exported file.

There are two ways to toggle extended logging for a component:

  1. By toggling the component's LoggingEnabled configuration setting (available in all components).
  2. By adding a DWORD-typed value named Enabled to the HKEY_LOCAL_MACHINE\SOFTWARE\Callback Technologies\{ComponentName}\EventLog registry key and setting it to 0 (disabled) or 1 (enabled).
    • Replace the {ComponentName} part of the registry key path with the name of the applicable component (use CBFilter for both CBFilter and CBMonitor).
    • If this registry key, one of its parents, or the actual value does not exist, please create it manually.

    Note: If your code runs in emulated mode (x86 mode on x64 or ARM64 architecture), you need to add the value to the HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Callback Technologies\{ComponentName}\EventLog registry key in addition to the "main" registry key.

The system must be rebooted anytime extended logging is enabled or disabled to make the changes take effect.

Troubleshooting

CBFS Filter is a complex product that operates in both user mode and kernel mode simultaneously; so when a serious issue occurs, it's critical that we are able to obtain sufficient information about the circumstances of the failure.

In order to help us assist you in a more expedient manner, please collect the information described in the instructions below when reporting a serious issue (i.e., one that causes the system to crash or hang). Our development team cannot effectively diagnose such issues without this information.

Also, please note that these sorts of issues commonly involve environmental differences and other factors that are either unforeseen or otherwise out of our control. It is also not unheard-of for a crash to appear attributable to one thing while in fact being caused by something completely different. Rest assured that we are committed to assisting you as best we can, and we thank you ahead-of-time for your patience and understanding throughout the support process.

System Crashes (BSODs)

If you encounter a consistently-reproducible system crash (BSOD) that you suspect may be due to CBFS Filter, please obtain a crash dump and include it when reporting the issue to us. Our development team is unable to diagnose system crashes without the information these dumps contain.

Ensure that your system is set up to generate crash dumps, and to not restart automatically after a crash, by following the steps found in Microsoft's Enabling a Kernel-Mode Dump File article. The options available in the memory dump dropdown vary depending on your version of Windows; please choose the first one from the following list that is present in yours:

  • Complete
  • Full
  • Automatic
  • Kernel

Once your system is set up to generate crash dumps, perform the same action that caused the BSOD originally to trigger the crash again. When it occurs, be sure to copy the information on the BSOD screen exactly so that it can be included in your submission (a picture of the screen in which all of the information is legible is also acceptable). Here are some examples of the specific information we're looking for:

Recent versions of Windows:

What failed: cbfs***22.sys Stop Code: FILE_SYSTEM

Older versions of Windows:

STOP: 0x00000022 (0x00240076, 0xF7A07AA8, 0xF7A077A8, 0xF7800C82) cbfs***22.sys - Address F7800C82 base at F77CD000, DateStamp 447d6975

After you've copied this information, reboot and check that the memory dump file was created at %SYSTEMROOT%\MEMORY.DMP (typically this is C:\Windows\MEMORY.DMP; if you changed the dump file location in the crash dump settings, check the location you specified instead). It will be a very large file that is too big to attach to an email, so please upload it to a file sharing site of your choice and generate a sharing link that our development team can use to download it.

Finally, submit a support issue to us that includes the link to your dump file, all of the information from the BSOD screen (if you took a picture, attach it or provide another sharing link), a description of how the BSOD was triggered, and any other information that you feel is relevant.

System Hangs

If you encounter a consistently-reproducible system hang that you suspect may be due to CBFS Filter, you'll need to collect the same information as described above. But in order to obtain a crash dump, you'll first need to configure your system so that you can trigger a crash from the keyboard once it hangs. To make this possible, follow these steps (adapted from Microsoft's Forcing a System Crash from the Keyboard article):

  1. First, using the instructions provided in the section above, configure your system to generate crash dumps, and to not restart automatically after a crash.
  2. Next, you must enable keyboard-initiated crashes in the registry by creating a new value named CrashOnCtrlScroll, and setting it equal to a REG_DWORD value of 0x01, in all of the following registry keys:
    • HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\i8042prt\Parameters
    • HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\kbdhid\Parameters
    • HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\hyperkbd\Parameters
  3. Finally, you must restart the system in order for these settings to take effect.

After these steps are complete, you'll be able to trigger a keyboard-initiated crash by using the following hotkey sequence: hold down the Right CTRL key, and press the SCROLL LOCK key twice.

At this point, you can perform the same action that caused the system to hang originally to trigger the hang again. Once the system hangs, use the hotkey sequence to force it to crash, and then follow the rest of the instructions from the section above to collect and submit the necessary information.

Method Never Returns

If your application makes a call to some CBFS Filter method and that method never returns, there's a high chance that the driver deadlock has occurred. This can be caused by various factors; to determine the reason and possible solutions, we need a memory dump, as described above. If your system remains functional, you may also use easier ways to initiate a crash:

  1. Use the NotMyFault tool by SysInternals to initiate a system crash. This is the preferred way because it generates Complete memory dumps. This tool has a self-explanatory GUI.
  2. Use the LiveKD tool by SysInternals to create a live memory dump without crashing a system. The disadvantage of this method is that it creates Kernel dumps that are missing user-mode information. To use LiveKD on 32-bit systems, use this command: "livekd.exe -ml -o memory.dmp". On 64-bit systems, the command line would be "livekd64.exe -ml -k .\kd64.exe -o memory.dmp".

Application Crashes

Sometimes, an application crashes while the OS continues to operate, and the name of one of the modules of CBFS Filter is present in the crash information. A crashing application can be the one that uses CBFS Filter or some third-party process. If the crash occurs repeatedly, it is possible to make use of a User-Mode Crash Dump to locate or narrow down the source of the crash. Generation of crash dumps is disabled by default. Before you reproduce the crash, you need to Enable Collecting User-Mode Crash Dumps.

After you enable the crash dump, you don't need to reboot, you can proceed to reproduction of the crash immediately. After the crash re-occurs, you can pick the dump file from its location. The default locations of user-mode dump files are:

  • For regular applications: %LOCALAPPDATA%\CrashDumps
  • For System services: %WINDIR%\System32\Config\SystemProfile
  • For Network and Local services: %WINDIR%\ServiceProfiles
If you changed the dump file location in the crash dump settings in the Registry, check the location you specified instead.

A crash dump can be a large file (depending on the settings) that is too big to attach to an email, so please upload it to a file sharing site of your choice and generate a sharing link that our development team can use to download it.

Finally, submit a support issue to us that includes the link to your dump file, a description of how the BSOD or a manual crash was triggered, and any other information that you feel is relevant.

Constants

All constants are accessible through the callback.CBFSFilter.Constants class.

Access Restriction Flags

ACCESS_NONE 0x00 No access restrictions.

ACCESS_READ_ONLY 0x01 Read-only access; writing and deleting are prohibited.

ACCESS_WRITE_ONLY 0x02 Write-only access; reading and deleting are prohibited.

ACCESS_DELETE_PROTECT 0x04 Deleting and renaming are prohibited.

ACCESS_EXECUTE_PROTECT 0x08 Execution is prohibited.

ACCESS_NO_CHANGE_DAC 0x10 Change of security attributes is prohibited.

ACCESS_NO_CHANGE_OWNER 0x20 Change of owner is prohibited.

ACCESS_RENAME_PROTECT 0x40 Renaming is prohibited.

ACCESS_DELETE_ONLY_PROTECT 0x80 Deleting is prohibited (renaming is not affected).

ACCESS_REMOTE_ACCESS_PROTECT 0x100 Access from other systems is prohibited.

ACCESS_DENY_ALL 0x200 All access is denied.

ACCESS_ALL_FLAGS -1 Used to denote all currently set access restriction flags.

Filesystem Control Event Flags

FS_CE_NONE 0 Don't fire for any filesystem operations.

Control Events will not fire for any filesystem operations.

FS_CE_BEFORE_CREATE 0x000000000001L Fire before file creation operations.

The BeforeCreateFile event will fire anytime the OS attempts to create a file or directory. In some cases, this event can cause the BeforeOpenFile event to fire; refer to the File Create/Open Events topic for more information.

FS_CE_AFTER_CREATE 0x000000000002L Fire after file creation operations.

The AfterCreateFile event will fire after a file or directory creation request has been processed, before the response is returned. In some cases, this event can cause the AfterOpenFile event to fire; refer to the File Create/Open Events topic for more information.

FS_CE_BEFORE_OPEN 0x000000000004L Fire before file open operations.

The BeforeOpenFile event will fire anytime the OS attempts to open a file or directory. In some cases, this event can cause the BeforeCreateFile event to fire; refer to the File Create/Open Events topic for more information.

FS_CE_AFTER_OPEN 0x000000000008L Fire after file open operations.

The AfterOpenFile event will fire after a file or directory open request has been processed, before the response is returned. In some cases, this event can cause the AfterCreateFile event to fire; refer to the File Create/Open Events topic for more information.

FS_CE_BEFORE_READ 0x000000000010L Fire before read operations.

The BeforeReadFile event will fire anytime the OS attempts to read data from a file.

FS_CE_AFTER_READ 0x000000000020L Fire after read operations.

The AfterReadFile event will fire after a read request has been processed, before the response is returned.

FS_CE_BEFORE_WRITE 0x000000000040L Fire before write operations.

The BeforeWriteFile event will fire anytime the OS attempts to write data to a file.

FS_CE_AFTER_WRITE 0x000000000080L Fire after write operations.

The AfterReadFile event will fire after a write request has been processed, before the response is returned.

FS_CE_BEFORE_LOCK_CONTROL 0x000000000100L Fire before lock and unlock operations.

The BeforeLock, BeforeUnlockAll, BeforeUnlockAllByKey, and BeforeUnlockSingle events will fire, as applicable, before the OS attempts to lock or unlock a range of bytes in a file.

FS_CE_AFTER_LOCK_CONTROL 0x000000000200L Fire before and after lock and unlock operations.

The AfterLock, AfterUnlockAll, AfterUnlockAllByKey, and AfterUnlockSingle, events will fire, as applicable, after a lock or unlock request has been processed, before the response is returned.

FS_CE_BEFORE_CLEANUP 0x000000000400L Fire before file handle cleanup operations.

The BeforeCleanupFile event will fire anytime a process closes a file or directory handle.

FS_CE_AFTER_CLEANUP 0x000000000800L Fire after file handle cleanup operations.

The AfterCleanupFile event will fire after a file handle cleanup request has been processed, before the response is returned.

FS_CE_BEFORE_CLOSE 0x000000001000L Fire before file close operations.

The BeforeCloseFile event will fire anytime the OS closes a file or directory. Also, the AfterCloseEnumeration event will fire anytime the OS closes a directory enumeration (which typically occurs immediately before the directory is closed).

FS_CE_AFTER_CLOSE 0x000000002000L Fire after file close operations.

The AfterCloseFile event will fire after a file/directory close request has been processed, before the response is returned.

FS_CE_BEFORE_CAN_DELETE 0x000000004000L Fire before 'can be deleted' operations.

The BeforeCanFileBeDeleted event will fire anytime the OS checks whether a file or directory can be deleted.

FS_CE_AFTER_CAN_DELETE 0x000000008000L Fire after 'can be deleted' operations.

The AfterCanFileBeDeleted event will fire after a can be deleted request has been processed, before the response is returned.

FS_CE_BEFORE_DELETE 0x000000010000L Fire before delete operations

The BeforeDeleteFile event will fire anytime the OS attempts to delete a file or directory.

FS_CE_AFTER_DELETE 0x000000020000L Fire after delete operations.

The AfterDeleteFile event will fire after a delete request has been processed, before the response is returned.

FS_CE_BEFORE_RENAME 0x000000040000L Fire before rename/move operations.

The BeforeRenameOrMoveFile event will fire anytime the OS attempts to rename or move a file or directory.

FS_CE_AFTER_RENAME 0x000000080000L Fire after rename/move operations.

The AfterRenameOrMoveFile event will fire after a rename or move request has been processed, before the response is returned.

FS_CE_BEFORE_GET_SECURITY 0x000000100000L Fire before get security operations.

The BeforeGetFileSecurity event will fire before the OS queries the security attributes of a file or directory.

FS_CE_AFTER_GET_SECURITY 0x000000200000L Fire after get security operations.

The AfterGetFileSecurity events will fire after a get security operation has been processed, before the response is returned.

FS_CE_BEFORE_ENUMERATE_DIRECTORY 0x000000400000L Fire before directory enumeration operations.

The BeforeEnumerateDirectory event will fire anytime the OS needs to read information about directory entries.

FS_CE_AFTER_ENUMERATE_DIRECTORY 0x000000800000L Fire after directory enumeration operations.

The AfterEnumerateDirectory event will fire after information about a directory entry has been retrieved during directory enumeration, before the response is returned.

FS_CE_BEFORE_QUERY_FILE_INFO 0x000001000000L Fire before 'query file information' operations.

The BeforeQueryFileInfo event will fire anytime the OS needs to retrieve information about a file or directory.

FS_CE_AFTER_QUERY_FILE_INFO 0x000002000000L Fire after 'query file information' operations.

The AfterQueryFileInfo event will fire after a file or directory information query request has been processed, before the response is returned.

FS_CE_AFTER_GET_SIZES 0x000008000000L Fire after get size operations.

The AfterGetFileSizes event will fire after a file's size information is retrieved, before the response is returned.

FS_CE_BEFORE_SET_SECURITY 0x000010000000L Fire before set security operations.

The BeforeSetFileSecurity event will fire anytime the OS needs to change the security attributes of a file or directory.

FS_CE_AFTER_SET_SECURITY 0x000020000000L Fire after set security operations.

The AfterSetFileSecurity event will fire after a security attribute change request has been processed, before the response is returned.

FS_CE_BEFORE_SET_ATTRIBUTES 0x000040000000L Fire before file attribute update operations.

The BeforeSetFileAttributes event will fire anytime the OS attempts to change the attributes of a file or directory.

FS_CE_AFTER_SET_ATTRIBUTES 0x000080000000L Fire after file attribute update operations.

The AfterSetFileAttributes event will fire after a file attribute change request has been processed, before the response is returned.

FS_CE_BEFORE_SET_SIZES 0x000100000000L Fire before file resize operations.

The BeforeSetFileSize event will fire anytime the OS attempts to resize a file, and the BeforeSetAllocationSize event will fire anytime the OS attempts to change a file's allocation size.

FS_CE_AFTER_SET_SIZES 0x000200000000L Fire after file resize operations.

The AfterSetFileSize event will fire after a file resize request has been processed, and the AfterSetAllocationSize event will fire after a file allocation size change request has been processed, before the response is returned.

FS_CE_BEFORE_CREATE_HARD_LINK 0x000400000000L Fire before hard link creation operations.

The BeforeCreateHardLink event will fire anytime the OS attempts to create a hard link.

FS_CE_AFTER_CREATE_HARD_LINK 0x000800000000L Fire after hard link creation operations.

The AfterCreateHardLink events will fire after a hard link creation request has been processed, before the response is returned.

FS_CE_BEFORE_FSCTL 0x001000000000L Fire before FSCTL operations.

The BeforeFsctl event will fire anytime an IRP_MJ_FILE_SYSTEM_CONTROL request occurs.

FS_CE_AFTER_FSCTL 0x002000000000L Fire after FSCTL operations.

The AfterFsctl event will fire after an IRP_MJ_FILE_SYSTEM_CONTROL request has been processed, before the response is returned.

FS_CE_BEFORE_IOCTL 0x004000000000L Fire before IOCTL operations.

The BeforeIoctl event will fire anytime an IRP_MJ_DEVICE_CONTROL request occurs.

FS_CE_AFTER_IOCTL 0x008000000000L Fire after IOCTL operations.

The AfterIoctl event will fire after an IRP_MJ_DEVICE_CONTROL request has been processed, before the response is returned.

FS_CE_BEFORE_SET_FILE_INFO 0x010000000000L Fire before 'set file information' operations.

The BeforeSetFileInfo event will fire anytime the OS needs to change information about a file or directory.

FS_CE_AFTER_SET_FILE_INFO 0x020000000000L Fire after 'set file information' operations.

The AfterSetFileInfo event will fire after a file or directory information change request has been processed, before the response is returned.

FS_CE_BEFORE_SET_EA 0x040000000000L Fire before Set Extended Attributes operations.

The BeforeSetEa event will fire anytime the OS needs to set extended attributes of a file.

FS_CE_AFTER_SET_EA 0x080000000000L Fire after Set Extended Attributes operations.

The AfterSetEa event will fire after the OS request to set extended attributes of a file has been processed, before the response is returned.

FS_CE_BEFORE_QUERY_EA 0x100000000000L Fire before Query Extended Attributes operations.

The BeforeQueryEa event will fire anytime the OS needs to retrieve extended attributes of a file.

FS_CE_AFTER_QUERY_EA 0x200000000000L Fire after Query Extended Attributes operations.

The AfterQueryEa event will fire after the OS request to retrieve extended attributes of a file has been processed, before the response is returned.

FS_CE_BEFORE_GET_REPARSE_POINT 0x400000000000L Fire before Get Reparse Point operations.

The BeforeGetReparsePoint event will fire anytime the OS needs to read a reparse point of a file or directory.

FS_CE_AFTER_GET_REPARSE_POINT 0x800000000000L Fire after Get Reparse Point operations.

The AfterGetReparsePoint event will fire after the OS request to read a reparse point of a file or directory has been processed, before the response is returned.

FS_CE_BEFORE_SET_REPARSE_POINT 0x1000000000000L Fire before Set Reparse Point operations.

The BeforeSetReparsePoint event will fire anytime the OS needs to set or update a reparse point for a file or directory.

FS_CE_AFTER_SET_REPARSE_POINT 0x2000000000000L Fire after Set Reparse Point operations.

The AfterSetReparsePoint event will fire after the OS request to set or update a reparse point for a file or directory has been processed, before the response is returned.

FS_CE_BEFORE_DELETE_REPARSE_POINT 0x4000000000000L Fire before Delete Reparse Point operations.

The BeforeDeleteReparsePoint event will fire anytime the OS needs to remove reparse point information from a file or directory.

FS_CE_AFTER_DELETE_REPARSE_POINT 0x8000000000000L Fire after Delete Reparse Point operations.

The AfterDeleteReparsePoint event will fire after the OS request to remove reparse point information from a file or directory has been processed, before the response is returned.

FS_CE_REPARSE_FILENAME 0x40000000000000L Fire before various operations for the purpose of file redirection.

The ReparseFileName event will fire before any operation that includes a file or directory name, giving the application a chance to redirect it. This event is typically used when an application requires more advanced redirection logic than Reparse Rules can provide; please refer to that topic for more information.

FS_CE_REPARSE_TAG 0x80000000000000L Fire for reparse operations.

The ReparseWithTag event will fire anytime a file/directory open operation returns a STATUS_REPARSE result, allowing the application to handle the reparse point. Please refer to Microsoft's Reparse Points article for more information.

FS_CE_ALL -1 Fire for all filesystem operations.

Control Events will fire for all filesystem operations that the component tracks.

Filesystem Notification Event Flags

FS_NE_NONE 0 Don't fire for any filesystem operations.

Notification Events will not fire for any filesystem operations.

FS_NE_CREATE 0x00000001L Fire for file creation operations.

The NotifyCreateFile event will fire anytime the OS creates a file or directory. In some cases, this event can cause the NotifyOpenFile event to fire; refer to the File Create/Open Events topic for more information.

FS_NE_OPEN 0x00000002L Fire for file open operations.

The NotifyOpenFile event will fire anytime the OS opens a file or directory. In some cases, this event can cause the NotifyCreateFile event to fire; refer to the File Create/Open Events topic for more information.

FS_NE_READ 0x00000004L Fire for read operations.

The NotifyReadFile event will fire anytime the OS reads data from a file.

FS_NE_WRITE 0x00000008L Fire for write operations.

The NotifyWriteFile event will fire anytime the OS writes data to a file.

FS_NE_LOCK_CONTROL 0x00000010L Fire for lock and unlock operations.

The NotifyLock, NotifyUnlockAll, NotifyUnlockAllByKey, and NotifyUnlockSingle events will fire, as applicable, anytime the OS locks or unlocks a range of bytes in a file.

FS_NE_CLEANUP 0x00000020L Fire for file handle cleanup operations.

The NotifyCleanupFile event will fire anytime a process closes a file or directory handle.

FS_NE_CLOSE 0x00000040L Fire for file close operations.

The NotifyCloseFile event will fire anytime the OS closes a file or directory.

FS_NE_CAN_DELETE 0x00000080L Fire for 'can be deleted' operations.

The NotifyCanFileBeDeleted event will fire anytime the OS checks whether or not a file or directory can be deleted.

FS_NE_DELETE 0x00000100L Fire for delete operations.

The NotifyDeleteFile event will fire anytime the OS deletes a file or directory.

FS_NE_RENAME 0x00000200L Fire for rename/move operations.

The NotifyRenameOrMoveFile event will fire anytime the OS renames or moves a file or directory.

FS_NE_GET_SECURITY 0x00000400L Fire for get security operations.

The NotifyGetFileSecurity event will fire anytime the OS queries the security attributes of a file or directory.

FS_NE_ENUMERATE_DIRECTORY 0x00000800L Fire for directory enumeration operations.

The NotifyEnumerateDirectory event will fire anytime the OS retrieves a directory entry during directory enumeration.

FS_NE_QUERY_FILE_INFO 0x00001000L Fire for QueryFileInformation operations.

The NotifyQueryFileInfo event will fire anytime the OS retrieves information about a file or directory.

FS_NE_GET_SIZES 0x00002000L Fire for get size operations.

The NotifyGetFileSizes event will fire anytime the OS retrieves a file's size information.

FS_NE_SET_SECURITY 0x00004000L Fire for set security operations.

The NotifySetFileSecurity event will fire anytime the OS changes the security attributes of a file or directory.

FS_NE_SET_ATTRIBUTES 0x00008000L Fire for file attribute update operations.

The NotifySetFileAttributes event will fire anytime the OS changes the attributes of a file or directory.

FS_NE_SET_SIZES 0x00010000L Fire for file resize operations.

The NotifySetFileSize event will fire anytime the OS resizes a file, and the NotifySetAllocationSize event will fire anytime the OS changes a file's allocation size.

FS_NE_CREATE_HARD_LINK 0x00020000L Fire for hard link creation operations.

The NotifyCreateHardLink event will fire anytime the OS creates a hard link.

FS_NE_FSCTL 0x00040000L Fire for FSCTL operations.

The NotifyFsctl event will fire anytime an IRP_MJ_FILE_SYSTEM_CONTROL operation occurs.

FS_NE_IOCTL 0x00080000L Fire for IOCTL operations.

The NotifyIoctl event will fire anytime an IRP_MJ_DEVICE_CONTROL operation occurs.

FS_NE_SET_FILE_INFO 0x00100000L Fire for SetFileInformation operations.

The NotifySetFileInfo event will fire anytime the OS changes information about a file or directory.

FS_NE_SET_EA 0x00200000L Fire for Set Extended Attributes operations.

The NotifySetEa event will fire anytime the OS sets extended attributes of a file.

FS_NE_QUERY_EA 0x00400000L Fire for Query Extended Attributes operations.

The NotifyQueryEa event will fire anytime the OS retrieves extended attributes of a file.

FS_NE_GET_REPARSE_POINT 0x00800000L Fire for Get Reparse Point operations.

The NotifyGetReparsePoint event will fire anytime the OS reads reparse point information of a file or directory.

FS_NE_SET_REPARSE_POINT 0x01000000L Fire for Set Reparse Point operations.

The NotifySetReparsePoint event will fire anytime the OS sets or updates reparse point information for a file or directory.

FS_NE_DELETE_REPARSE_POINT 0x02000000L Fire for Delete Reparse Point operations.

The NotifyDeleteReparsePoint event will fire anytime the OS deletes reparse point information from a file or directory.

FS_NE_ALL -1 Fire for all filesystem operations.

Notification Events will fire for all filesystem operations that the component tracks.

Directory Enumeration flags

FS_ENUM_RESTART_SCAN 1 The requestor specified that directory enumeration must be restarted.

FS_ENUM_RETURN_SINGLE_ENTRY 2 One entry should be returned.

FS_ENUM_INDEX_SPECIFIED 4 The requestor specified the index to start enumeration from.

Filesystem Reparse Flags

FS_REPARSE_CHANGE_PATH 0 Perform redirection by modifying the path directly using the CBFilter system driver.

FS_REPARSE_USE_REPARSE_POINT 1 Perform redirection by having the CBFilter system driver emulate real reparse point behavior.

This option will cause the driver to report that a file or directory's parent directory is a reparse point of the SYMLINK variety. Redirection performed in this manner is more consistent with Windows' behavior; however, some software may fail to correctly handle paths that cross such symbolic links.

Filesystem Request Directions

FS_REQUEST_DIR_USER_NONCACHED 0 Operations performed in the user mode application <--> filesystem direction.
FS_REQUEST_DIR_USER_CACHED 1 Operations performed in the user mode application <--> system cache direction.
FS_REQUEST_DIR_SYSTEM_NONCACHED 2 Operations performed in the system cache <--> filesystem direction.
FS_REQUEST_DIR_SYSTEM_CACHED 3 Operations performed in the system component <--> system cache direction.

Filesystem Volume Mount Events

FS_MOUNT_IGNORE 0 Don't fire any events when volumes are mounted or unmounted.

FS_MOUNT_NOTIFY 64 Fire Notification Events when volumes are mounted or unmounted.

The NotifyFilterAttachToVolume and NotifyFilterDetachFromVolume events will fire, asynchronously, as necessary.

FS_MOUNT_CONTROL 128 Fire Control Events when volumes are mounted or unmounted.

The BeforeFilterAttachToVolume, AfterFilterAttachToVolume, and AfterFilterDetachFromVolume events will fire, synchronously, as necessary.

FS_MOUNT_BOTH 192 Fire all events when volumes are mounted or unmounted.

File Flushing Behavior Flags

FS_FLUSH_FILES_ON_OPEN 1 Whether memory-mapped file data should be flushed to disk before files are opened.

This flag indicates that the component's system driver should flush any cached and memory-mapped file data, leftover from the last time a file was opened, before opening it again. Doing so ensures that file data are read directly from the disk rather than from the old memory mapping.

Applications that modify file data as it is being read may need to set this flag to function correctly. For example, applications that provide on-the-fly encryption should set this flag to ensure that file data are always read from the disk (and thus have a chance to get decrypted) when a file is opened.

Applications that do not modify file data as it is being read should leave this flag unset to maintain optimal performance when opening files.

FS_FLUSH_FILES_ON_CLOSE 2 Whether file buffers must be flushed when files are closed.

This flag indicates that the component's system driver should flush and clear the buffers of files that are opened for writing (and have had data written to them) when they are closed.

Applications that modify file data as it is being written may need to set this flag to function correctly. For example, applications that provide on-the-fly encryption should set this flag to ensure that all file data are flushed to the disk (and thus has a chance to get encrypted) when a file is closed.

Applications that do not modify file data as it is being written can unset this flag.

After a file is flushed, all in-memory buffers and memory mappings are cleared to avoid leakage of unprotected information.

FS_CLOSE_FILES_ON_STOPFILTER 4 Whether files opened for writing must be closed when the application stops filtering.

This flag indicates that the component's system driver should close files that are opened for writing (and have had data written to them) when the application calls StopFilter.

Applications that modify file data as it is being written (e.g., on-the-fly encryption) may need to set this flag to prevent further operations against the file data from being performed. Applications that do not modify file data as it is being written can leave this flag unset.

Note: If memory mappings of some file exist, these mappings will remain active; only the open handles to such files are closed.

When the file is closed, all in-memory buffers and memory mappings are cleared to avoid leakage of unprotected information. Applications can control whether file data are flushed before files are closed using the FS_FLUSH_FILES_ON_STOPFILTER flag; any data that are not flushed get discarded.

FS_FLUSH_FILES_ON_STOPFILTER 8 Whether file buffers must be flushed when the application stops filtering.

This flag indicates that the component's system driver should flush and clear the buffers of files that are opened for writing (and have had data written to them) when the application calls StopFilter.

Applications that modify file data as it is being written (e.g., on-the-fly encryption) may need to set this flag to ensure that no unprotected data are kept in memory, but rather has a chance to be encrypted and written out to disk. Applications that do not modify file data as it is being written can leave this flag unset.

If the application will not be able to perform on-the-fly data modification at the moment when StopFilter is called (e.g., because a cryptographic hardware module is unplugged), then this flag should be unset before calling StopFilter.

After a file is flushed, all in-memory buffers and memory mappings are cleared to avoid leakage of unprotected information.

FS_CLOSE_FILES_ON_CRASH 16 Whether files opened for writing must be closed if the application terminates unexpectedly.

This flag indicates that the component's system driver should close files that are opened for writing (and have had data written to them) if the driver detects that the application has terminated.

Applications that modify file data as it is being written (e.g., on-the-fly encryption) may need to set this flag to prevent further operations against the file data from being performed. Applications that do not modify file data as it is being written can leave this flag unset.

Note: If memory mappings of some file exist, these mappings will remain active; only the open handles to such files are closed.

When the file is closed, all in-memory buffers and memory mappings are cleared to avoid leakage of unprotected information.

FS_FLUSH_FILES_ON_CRASH 32 Whether file buffers must be flushed if the application terminates unexpectedly.

This flag indicates that the component's system driver should flush and clear the buffers of files that are opened for writing (and have had data written to them) if the driver detects that the application has terminated.

Applications that do not modify data as it is being written may set this flag if necessary. Applications that modify data as it is being written (e.g., on-the-fly encryption) should not set this flag, because such flushing could cause unprotected data to be written out to disk.

FS_SUPPORT_FILE_ENCRYPTION 31 Combination of flags suitable for on-the-fly file encryption applications.

This option includes the following flags: FS_FLUSH_FILES_ON_OPEN, FS_FLUSH_FILES_ON_CLOSE, FS_CLOSE_FILES_ON_STOPFILTER, FS_FLUSH_FILES_ON_STOPFILTER, and FS_CLOSE_FILES_ON_CRASH flags.

Delete request types

DEL_REQ_OPEN_FLAG 0x1 The file or directory is opened with the FILE_FLAG_DELETE_ON_CLOSE flag

DEL_REQ_SET_DISPOSITION 0x2 The system has sent the IRP_MJ_SET_INFORMATION request with SetFileDisposition structure as a parameter.

This request usually is sent using the NtSetInformationFile() Windows native API function.

Process Event Flags

PROC_EVT_NONE 0 Don't fire for any process operations.

Events will not fire for any process operations.

PROC_EVT_PROCESS_CREATION 1 Fire during process creation operations.

The ProcessCreation event will fire anytime the OS attempts to create a process.

PROC_EVT_PROCESS_TERMINATION 2 Fire during process closing/termination.

The ProcessTermination event will fire when a process is being terminated.

PROC_EVT_PROCESS_HANDLE_OPERATION 4 Fire during process handle creation or duplication.

The ProcessHandleOperation event will fire when a process handle is being created or duplicated.

PROC_EVT_THREAD_CREATION 8 Fire during thread creation operations.

The ThreadCreation event will fire when a thread is being created, before it is started.

PROC_EVT_THREAD_TERMINATION 0x10 Fire during thread termination operations.

The ThreadTermination event will fire when a thread is being terminated.

PROC_EVT_THREAD_HANDLE_OPERATION 0x20 Fire during thread handle creation or duplication.

The ThreadHandleOperation event will fire when a thread handle is being created or duplicated.

PROC_EVT_ALL -1 Fire for all process and thread operations.

Events will fire for all thread operations.

Registry Control Event Flags

REG_CE_NONE 0 Don't fire for any registry operations.

Control Events will not fire for any registry operations.

REG_CE_BEFORE_CREATE_KEY 0x00000001L Fire before registry key creation operations.

The BeforeCreateKey event will fire anytime the OS attempts to create a registry key.

REG_CE_AFTER_CREATE_KEY 0x00000002L Fire after registry key creation operations.

The AfterCreateKey event will fire after a registry key creation request has been processed, before the response is returned.

REG_CE_BEFORE_OPEN_KEY 0x00000004L Fire before registry key open operations.

The BeforeOpenKey event will fire anytime the OS attempts to open a registry key.

REG_CE_AFTER_OPEN_KEY 0x00000008L Fire after registry key open operations.

The AfterOpenKey event will fire after a registry key open request has been processed, before the response is returned.

REG_CE_BEFORE_CLOSE_KEY 0x00000010L Fire before registry key close operations.

The BeforeCloseKey event will fire anytime the OS closes a registry key.

REG_CE_AFTER_CLOSE_KEY 0x00000020L Fire after registry key close operations.

The AfterCloseKey event will fire after a registry key close request has been processed, before the response is returned.

REG_CE_BEFORE_DELETE_KEY 0x00000040L Fire before registry key delete operations.

The BeforeDeleteKey event will fire anytime the OS attempts to delete a registry key.

REG_CE_AFTER_DELETE_KEY 0x00000080L Fire after registry key delete operations.

The AfterDeleteKey event will fire after a registry key delete request has been processed, before the response is returned.

REG_CE_BEFORE_RENAME_KEY 0x00000100L Fire before registry key rename operations.

The BeforeRenameKey event will fire anytime the OS attempts to rename a registry key.

REG_CE_AFTER_RENAME_KEY 0x00000200L Fire after registry key rename operations.

The AfterRenameKey event will fire after a registry key rename request has been processed, before the response is returned.

REG_CE_BEFORE_ENUM_KEY 0x00000400L Fire before subkey enumeration operations.

The BeforeEnumerateKey event will fire anytime the OS attempts to enumerate a registry key's subkeys.

REG_CE_AFTER_ENUM_KEY 0x00000800L Fire after subkey enumeration operations.

The AfterEnumerateKey event will fire after a subkey enumeration request has been processed, before the response is returned.

REG_CE_BEFORE_QUERY_KEY 0x00001000L Fire before registry key metadata retrieval operations.

The BeforeQueryKey event will fire anytime the OS attempts to retrieve a registry key's metadata.

REG_CE_AFTER_QUERY_KEY 0x00002000L Fire after registry key metadata retrieval operations.

The AfterQueryKey event will fire after a registry key metadata retrieval request has been processed, before the response is returned.

REG_CE_BEFORE_SET_KEY 0x00004000L Fire before registry key metadata update operations.

The BeforeSetKey event will fire anytime the OS attempts to update a registry key's metadata.

REG_CE_AFTER_SET_KEY 0x00008000L Fire after registry key metadata update operations.

The AfterSetKey event will fire after a registry key metadata update request has been processed, before the response is returned.

REG_CE_BEFORE_DELETE_VALUE 0x00010000L Fire before registry value delete operations.

The BeforeDeleteValue event will fire anytime the OS attempts to delete a registry value.

REG_CE_AFTER_DELETE_VALUE 0x00020000L Fire after registry value delete operations.

The AfterDeleteValue event will fire after a registry value delete request has been processed, before the response is returned.

REG_CE_BEFORE_ENUM_VALUE 0x00040000L Fire before value enumeration operations.

The BeforeEnumerateValue event will fire anytime the OS attempts to enumerate a registry key's values.

REG_CE_AFTER_ENUM_VALUE 0x00080000L Fire after value enumeration operations.

The AfterEnumerateValue event will fire after a value enumeration request has been processed, before the response is returned.

REG_CE_BEFORE_QUERY_VALUE 0x00100000L Fire before registry value query operations.

The BeforeQueryValue event will fire anytime the OS attempts to query a registry value.

REG_CE_AFTER_QUERY_VALUE 0x00200000L Fire after registry value query operations.

The AfterQueryValue event will fire after a registry value query request has been processed, before the response is returned.

REG_CE_BEFORE_SET_VALUE 0x00400000L Fire before registry value set/update operations.

The BeforeSetValue event will fire anytime the OS attempts to set or update a registry value.

REG_CE_AFTER_SET_VALUE 0x00800000L Fire after registry value set/update operations.

The AfterSetValue event will fire after a registry value set or update request has been processed, before the response is returned.

REG_CE_BEFORE_GET_KEY_SECURITY 0x001000000L Fire before get registry key security operations.

The BeforeGetKeySecurity event will fire before the OS queries the security attributes of a registry key.

REG_CE_AFTER_GET_KEY_SECURITY 0x002000000L Fire after registry value query operations.

The AfterGetKeySecurity event will fire after a get security operation has been processed, before the response is returned.

REG_CE_BEFORE_SET_KEY_SECURITY 0x004000000L Fire before registry value set/update operations.

The BeforeSetValue event will fire anytime the OS needs to change the security attributes of a registry key.

REG_CE_AFTER_SET_KEY_SECURITY 0x008000000L Fire after registry value set/update operations.

The AfterSetValue event will fire after a security attributes change request has been processed, before the response is returned.

REG_CE_ALL -1 Fire for all registry operations.

Control Events will fire for all registry operations.

Registry Key Fields

REG_KEYFIELD_LASTWRITETIME 1 A registry key's last write time.

REG_KEYFIELD_NAME 2 A registry key's name.

REG_KEYFIELD_MAXNAMELENGTH 4 A registry key's longest subkey name.

REG_KEYFIELD_CLASSNAME 8 A registry key's class name.

REG_KEYFIELD_MAXCLASSNAMELENGTH 16 A registry key's longest subkey class name.

REG_KEYFIELD_SUBKEYS 32 The number of subkeys a registry key has.

REG_KEYFIELD_VALUES 64 The number of values a registry key has.

REG_KEYFIELD_MAXVALUENAMELENGTH 128 A registry key's longest value name.

REG_KEYFIELD_MAXVALUEDATASIZE 256 A registry key's largest value data size.

REG_KEYFIELD_VIRTUALIZATIONINFO 512 A registry key's virtualization information.

Registry Value Fields

REG_VALUEFIELD_TYPE 1 A registry value's type.

REG_VALUEFIELD_NAME 2 A registry value's name.

REG_VALUEFIELD_DATA 4 A registry value's data.

Registry Value Types

REG_VALUETYPE_SZ 1 A unicode string.

REG_VALUETYPE_EXPAND_SZ 2 A unicode string that contains environmental variable references.

REG_VALUETYPE_BINARY 3 Binary data.

REG_VALUETYPE_DWORD 4 A 32-bit number.

REG_VALUETYPE_MULTI_SZ 7 Multiple unicode strings.

REG_VALUETYPE_QWORD 11 A 64-bit number.

File Encryption Modes

FILEENC_EM_UNDEFINED -1 No encryption information specified.

When an event is fired, this value may be present in the Encryption parameter; it indicates that an event handler must set Encryption to an actual value as well as change the Password parameter. This value will be present when the PassRulePasswords configuration setting is disabled.

FILEENC_EM_NONE 0x0 Encryption is not applied.

When adding encryption rules with the AddFilterRule method, this value indicates that the encryption should not be applied to the matching files.

When an event is fired, this value indicates that the file is not encrypted.

FILEENC_EM_DEFAULT 0x1 Use default encryption (FILEENC_EM_AES256_PBKDF2_HMAC_SHA256).

When adding encryption rules with the AddFilterRule method, the value indicates that the default encryption, defined by the DefaultEncryption property, should be used.

FILEENC_EM_AES256_PBKDF2_HMAC_SHA256 0x2 Use AES256 encryption with PBKDF2 key derivation based on a HMAC_SHA256 key hash.

Install Flags

INSTALL_REMOVE_OLD_VERSIONS 0x00000001 Uninstall drivers from previous component versions (e.g., 2017).

INSTALL_KEEP_START_TYPE 0x00000002 Keep the driver's current start type setting in the registry.

If this flag is not set (default), the installation logic will reset the driver's start type setting in the Windows registry to the default value. Setting this flag causes the installation logic to preserve the current value, which may be necessary if the user (or the application) set it previously.

INSTALL_REQUESTS_VIA_DRIVER_STACK 0x00000004 Whether internal requests to the filesystem are sent directly to the filesystem driver or through the stack of filesystem filter drivers.

This flag is applicable only for CBFilter and CBMonitor.

After installation, the effects of this flag can be changed using the SendRequestsViaDriverStack configuration setting.

INSTALL_ALWAYS_PREPARE_FILES 0x00010000 Whether the driver should keep track of information for files that are already open when (i.e., were opened before) the component is initialized.

This flag is applicable only for CBFilter and CBMonitor.

If this flag is set, the driver will prepare information about each file as it is opened, regardless of whether a CBFilter/CBMonitor-based application is actually running at the time. This information then allows applications to receive events for any files that are already open when the CBFilter/CBMonitor component is initialized.

Note: These preparations will slow down all file open operations; do not enable this feature unless it is actually necessary.

After installation, the effects of this flag can be changed using the AlwaysPrepareFiles configuration setting.

INSTALL_FORCE_APP_PERMISSION_CHECK 0x00020000 Whether the driver should require the controller process to have elevated or system privileges.

This flag is not applicable for CBProcess.

If this flag is set, the driver will verify that the controller process is a system service (or is executing with elevated privileges) anytime a file is opened. If the controller process does not meet these requirements, the file will be skipped (i.e., not filtered in any way).

Note: This additional verification will slow down all file open operations.

After installation, the effects of this flag can be changed using the ForceAppPermissionCheck configuration setting.

INSTALL_FORCE_SECURITY_CHECKS 0x00040000 Whether the driver should prevent the controller process from filtering files that it would not normally have access to.

This flag is not applicable for CBProcess.

If this flag is set, the driver will check the security permissions of the controller process anytime a file is opened to verify that the process has access to the file. If the controller process does not have access to the file, the file will be skipped (i.e., not filtered in any way). For example, if this flag is set and the controller process is running with limited privileges, then the driver will not allow it to filter files that require greater privileges to access.

Note: This additional verification will slow down all file open operations.

After installation, the effects of this flag can be changed using the ForceSecurityChecks configuration setting.

Uninstall Version Flags

UNINSTALL_VERSION_PREVIOUS 0x00000001 Uninstall modules from previous product versions.

UNINSTALL_VERSION_CURRENT 0x00000002 Uninstall modules from the current product version.

UNINSTALL_VERSION_ALL 0x00000003 Uninstall modules from all product versions.

Module Status Flags

MODULE_STATUS_NOT_PRESENT 0x00000000 The specified module is not present on the system.

MODULE_STATUS_STOPPED 0x00000001 The specified module is in the Stopped state.

MODULE_STATUS_RUNNING 0x00000004 The specified module is loaded and running.

File Attributes

FILE_SYS_ATTR_READ_ONLY 0x00000001 The file is read-only.

Applications can read the file, but cannot write to it or delete it. This attribute is not honored on directories.

FILE_SYS_ATTR_HIDDEN 0x00000002 The file or directory is hidden.

The file is not included in an ordinary directory listing.

FILE_SYS_ATTR_SYSTEM 0x00000004 A file or directory that the operating system uses a part of, or uses exclusively.

FILE_SYS_ATTR_DIRECTORY 0x00000010 The entry is a directory.

FILE_SYS_ATTR_ARCHIVE 0x00000020 The entry is an archive file or directory.

Applications typically use this attribute to mark files for backup or removal.

FILE_SYS_ATTR_NORMAL 0x00000080 A file doesn't have other attributes set.

This attribute is valid only when used alone.

FILE_SYS_ATTR_TEMPORARY 0x00000100 A file that is being used for temporary storage.

File systems avoid writing data back to mass storage if sufficient cache memory is available, because typically, an application deletes a temporary file after the handle is closed. In that scenario, the system can entirely avoid writing the data. Otherwise, the data are written after the handle is closed.

FILE_SYS_ATTR_SPARSE_FILE 0x00000200 A file that is a sparse file.

FILE_SYS_ATTR_REPARSE_POINT 0x00000400 A file that is a reparse point or a symbolic link.

FILE_SYS_ATTR_COMPRESSED 0x00000800 A file or directory that is compressed.

For a file, all of the data in the file are compressed. For a directory, compression is the default for newly created files and subdirectories. A filesystem implementation can make use of this attribute by setting the SupportCompressedAttribute property to true and then properly handling the GetFileInfo, EnumerateDirectory, and SetFileAttributes events.

FILE_SYS_ATTR_OFFLINE 0x00001000 The data of a file are not available immediately.

This attribute indicates that the file data are physically moved to offline storage.

FILE_SYS_ATTR_NOT_CONTENT_INDEXED 0x00002000 The file or directory is not to be indexed by the content indexing service.

FILE_SYS_ATTR_ENCRYPTED 0x00004000 A file or directory that is encrypted.

For a file, all data streams in the file are encrypted. For a directory, encryption is the default for newly created files and subdirectories.

Note: This flag is used by NTFS and the OS sends undocumented requests to the filesystem based on this flag. The flag should not be used for files in custom filesystem implementations.

FILE_SYS_ATTR_VIRTUAL 0x00010000 Reserved.

Note: This flag is reserved by the OS and should not be used for files in custom filesystem implementations.

FILE_SYS_ATTR_RECALL_ON_OPEN 0x00040000 The file or directory has no physical representation on the local system; the item is virtual.

Opening the item will be more expensive than normal (e.g., it will cause at least some of it to be fetched from a remote store). This flag is reported by filesystems during directory enumerations.

File Desired Access Flags

DESIRED_ACCESS_FILE_LIST_DIRECTORY 0x00000001 For a directory, the right to list the contents of the directory.

DESIRED_ACCESS_FILE_READ_DATA 0x00000001 For a file object, the right to read the corresponding file data.

For a directory object, the right to read the corresponding directory data.

DESIRED_ACCESS_FILE_ADD_FILE 0x00000002 For a directory, the right to create a file in the directory.

DESIRED_ACCESS_FILE_WRITE_DATA 0x00000002 For a file object, the right to write data to the file.

For a directory object, the right to create a file in the directory

DESIRED_ACCESS_FILE_ADD_SUBDIRECTORY 0x00000004 For a directory, the right to create a subdirectory.

DESIRED_ACCESS_FILE_APPEND_DATA 0x00000004 For a file object, the right to append data to the file.

(For local files, write operations will not overwrite existing data if this flag is specified without FILE_WRITE_DATA.) For a directory object, the right to create a subdirectory (FILE_ADD_SUBDIRECTORY).

DESIRED_ACCESS_FILE_READ_EA 0x00000008 The right to read extended file attributes.

DESIRED_ACCESS_FILE_WRITE_EA 0x00000010 The right to write extended file attributes.

DESIRED_ACCESS_FILE_EXECUTE 0x00000020 For a native code file, the right to execute the file.

This access right given to scripts may cause the script to be executable, depending on the script interpreter.

DESIRED_ACCESS_FILE_DELETE_CHILD 0x00000040 For a directory, the right to delete a directory and all the files it contains, including read-only files.

DESIRED_ACCESS_FILE_READ_ATTRIBUTES 0x00000080 The right to read file attributes.

DESIRED_ACCESS_FILE_WRITE_ATTRIBUTES 0x00000100 The right to write file attributes.

DESIRED_ACCESS_READ_CONTROL 0x00020000 The right to read the information in the file or directory object's security descriptor.

This does not include the information in the SACL.

DESIRED_ACCESS_STANDARD_RIGHTS_READ 0x00020000 Includes READ_CONTROL, which is the right to read the information in the file or directory object's security descriptor.

This does not include the information in the SACL.

DESIRED_ACCESS_STANDARD_RIGHTS_WRITE 0x00020000 Same as STANDARD_RIGHTS_READ

DESIRED_ACCESS_STANDARD_RIGHTS_EXECUTE 0x00020000 Same as STANDARD_RIGHTS_READ

DESIRED_ACCESS_SYNCHRONIZE 0x00100000 The right to use the object for synchronization.

This enables a thread to wait until the object is in the signaled state. Some object types do not support this access right.

DESIRED_ACCESS_FILE_ALL_ACCESS 0x001F01FF All possible access rights for a file.

DESIRED_ACCESS_FILE_GENERIC_READ 0x00120089 A combinarion of flags that allow reading of the file.

Note: Don't match received values against this flag. Instead, use flags that specify the rights that you want to verify or add/remove.

DESIRED_ACCESS_FILE_GENERIC_WRITE 0x00120116 A combinarion of flags that allow modifications to the file.

Note: Don't match received values against this flag. Instead, use flags that specify the rights that you want to verify or add/remove.

DESIRED_ACCESS_FILE_GENERIC_EXECUTE 0x001200A0 A combinarion of flags that allow execution of the file.

Note: Don't match received values against this flag. Instead, use flags that specify the rights that you want to verify or add/remove.

Creation Disposition flags

FILE_DISPOSITION_CREATE_NEW 0x00000001 Creates a new file, only if it does not already exist.

If the specified file exists, the operation fails with an "already exists" error.

FILE_DISPOSITION_CREATE_ALWAYS 0x00000002 Creates a new file, always.

If the specified file exists and is writable, the system overwrites the file. If the specified file does not exist and is a valid path, a new file is created.

FILE_DISPOSITION_OPEN_EXISTING 0x00000003 Opens a file, only if it exists

If the specified file does not exist, opening fails.

FILE_DISPOSITION_OPEN_ALWAYS 0x00000004 Opens a file, always.

If the specified file exists, the operation succeeds. If the specified file does not exist and is a valid path to a writable location, the a file is created.

FILE_DISPOSITION_TRUNCATE_EXISTING 0x00000005 Opens a file and truncates it so that its size is zero bytes, only if it exists.

If the specified file does not exist, the operation fails with a "file not found" error.

Share Mode Flags

FILESYS_SHARE_NONE 0x00000000 Prevents any process from opening a file or device if it requests delete, read, or write access.

FILESYS_SHARE_READ 0x00000001 Enables subsequent open operations on a file or device to request read access.

Enables subsequent open operations to request read access; otherwise, no process can open the file or device if it requests read access. If this flag is not specified, but the file or device has been opened for read access, the function fails.

FILESYS_SHARE_WRITE 0x00000002 Enables subsequent open operations on a file or device to request write access.

Enables subsequent open operations to request write access; otherwise, no process can open the file or device if it requests write access. If this flag is not specified, but the file or device has been opened for write access or has a file mapping with write access, the function fails.

FILESYS_SHARE_DELETE 0x00000004 Enables subsequent open operations on a file or device to request delete access.

Enables subsequent open operations to request delete access; otherwise, no process can open the file or device if it requests delete access. If this flag is not specified, but the file or device has been opened for delete access, the function fails.

Note: Delete access allows both delete and rename operations.

CBFILTER_IGNORE_SHARE_ACCESS_CHECK 0x10000000 Specifies that the driver should pass IO_IGNORE_SHARE_ACCESS_CHECK flag to the system functions.

Use this flag to bypass sharing checks performed by the I/O manager when opening local files.

Note: The filesystem still may perform these checks. Also, the internal structures are not updated with the share mode values, passed in this call. This means that subsequent file open operations will not know about the previous share mode and may succeed where they would have to fail.