C# example to use EaseTag Filter Driver SDK

Download EaseTag Tiered Storage Filter Driver SDK Setup File
Download EaseTag Tiered Storage Filter Driver SDK Zip File
///////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright 2012 EaseFilter Technologies Inc.
// All Rights Reserved
//
// This software is part of a licensed software product and may
// only be used or copied in accordance with the terms of that license.
//
///////////////////////////////////////////////////////////////////////////////

using System;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;

namespace CSharpExample
{

static public class EaseTag
{
public delegate Boolean FilterDelegate(IntPtr sendData, IntPtr replyData);
public delegate void DisconnectDelegate();
static GCHandle gchFilter;
static GCHandle gchDisconnect;
static bool isFilterStarted = false;
public const int MAX_FILE_NAME_LENGTH = 512;
public const int MAX_SID_LENGTH = 256;
public const int MAX_MESSAGE_LENGTH = 65536;
public const int MAX_PATH = 260;
public const int MAX_ERROR_MESSAGE_SIZE = 1024;

public const uint MESSAGE_SEND_VERIFICATION_NUMBER = 0xFF000001;

//the key represent the tag data is using the following structure
public const uint EASETAG_KEY = 0xbba65d6f;

public struct EASETAG_DATA 
{
public uint	EaseTagKey;
public uint	Flags;
public uint	FileNameLength;
// public string	fileName;
}

public enum MessageType : uint
{
MESSAGE_TYPE_RESTORE_BLOCK_OR_FILE = 0x00000001,
MESSAGE_TYPE_RESTORE_FILE = 0x00000002,
}

public enum NTSTATUS : uint
{
STATUS_SUCCESS = 0,
STATUS_UNSUCCESSFUL = 0xc0000001,
}


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MessageSendData
{
public uint MessageId; //this is the request sequential number.
public IntPtr FileObject; //the address of FileObject,it is equivalent to file handle,it is unique per file stream open.
public IntPtr FsContext; //the address of FsContext,it is unique per file.
public uint MessageType; //the I/O request type.
public uint ProcessId; //the process ID for the process associated with the thread that originally requested the I/O operation.
public uint ThreadId; //the thread ID which requested the I/O operation.
public long Offset; //the read/write offset.
public uint Length; //the read/write length.
public long FileSize; //the size of the file for the I/O operation.
public long TransactionTime; //the transaction time in UTC of this request.
public long CreationTime; //the creation time in UTC of the file.
public long LastAccessTime; //the last access time in UTC of the file.
public long LastWriteTime; //the last write time in UTC of the file.
public uint FileAttributes; //the file attributes.
public uint DesiredAccess; //the DesiredAccess for file open, please reference CreateFile windows API.
public uint Disposition; //the Disposition for file open, please reference CreateFile windows API.
public uint SharedAccess; //the SharedAccess for file open, please reference CreateFile windows API.
public uint CreateOptions; //the CreateOptions for file open, please reference CreateFile windows API.
public uint CreateStatus; //the CreateStatus after file was openned, please reference CreateFile windows API.
public uint InfoClass; //the information class or security information
public uint Status; //the I/O status which returned from file system.
public uint FileNameLength; //the file name length in byte.
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_FILE_NAME_LENGTH)]
public string FileName; //the file name of the I/O operation.
public uint SidLength; //the length of the security identifier.
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_SID_LENGTH)]
public byte[] Sid; //the security identifier data.
public uint DataBufferLength; //the data buffer length.
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_MESSAGE_LENGTH)]
public byte[] DataBuffer; //the data buffer which contains read/write/query information/set information data.
public uint VerificationNumber; //the verification number which verifiys the data structure integerity.
}

public enum FilterStatus : uint
{
BLOCK_DATA_WAS_RETURNED = 0x00000008, //Set this flag if return read block databuffer to filter.
STUB_FILE_WAS_RESTORED = 0x00000010, //Set this flag if the stub file was restored.
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct MessageReplyData
{
public uint MessageId;
public uint MessageType;
public uint ReturnStatus;
public uint FilterStatus;
public uint DataBufferLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 65536)]
public byte[] DataBuffer;
}

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool InstallDriver();

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool UnInstallDriver();

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool SetRegistrationKey([MarshalAs(UnmanagedType.LPStr)]string key);

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool Disconnect();

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool GetLastErrorMessage(
[MarshalAs(UnmanagedType.LPWStr)] 
string errorMessage,
ref int messageLength);

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool RegisterMessageCallback(
int threadCount,
IntPtr filterCallback,
IntPtr disconnectCallback);

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool ResetConfigData();

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool SetConnectionTimeout(uint timeOutInSeconds);

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool AddExcludedProcessId(uint processId);

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool RemoveExcludeProcessId(uint processId);

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool GetFileHandleInFilter(
[MarshalAs(UnmanagedType.LPWStr)]string fileName,
ref IntPtr fileHandle);

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool OpenStubFile(
[MarshalAs(UnmanagedType.LPWStr)]string fileName,
FileAccess access,
FileShare share,
ref IntPtr fileHandle);

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool CreateStubFile(
[MarshalAs(UnmanagedType.LPWStr)]string fileName,
long fileSize, //if it is 0 and the file exist,it will use the current file size.
uint fileAttributes, //if it is 0 and the file exist, it will use the current file attributes.
uint tagDataLength,
IntPtr tagData,
bool overwriteIfExist,
ref IntPtr fileHandle);


[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool GetTagData(
IntPtr fileHandle,
ref int tagDataLength,
IntPtr tagData);

public static bool GetTagData(IntPtr fileHandle, out byte[] tagData, out string lastError)
{
bool ret = false;
IntPtr tagPtr = IntPtr.Zero;
int tagDataLength = 0;

lastError = string.Empty;
tagData = null;

ret = GetTagData(fileHandle, ref tagDataLength, tagPtr);

if (!ret)
{
if (tagDataLength > 0)
{
tagPtr = Marshal.AllocHGlobal((int)tagDataLength);
ret = GetTagData(fileHandle, ref tagDataLength, tagPtr);

}
}

if (!ret)
{
lastError = GetLastErrorMessage();
}
else
{
tagData = new byte[tagDataLength];
Marshal.Copy(tagPtr, tagData, 0, tagDataLength);
}

if (tagPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(tagPtr);
}

return ret;
}

[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool RemoveTagData(
IntPtr fileHandle);


[DllImport("FilterAPI.dll", SetLastError = true)]
public static extern bool AddTagData(
IntPtr fileHandle,
int tagDataLength,
IntPtr tagData);


public static bool AddTagData(
IntPtr fileHandle,
byte[] tagData)
{
GCHandle pinnedArray = GCHandle.Alloc(tagData, GCHandleType.Pinned);
IntPtr pointer = pinnedArray.AddrOfPinnedObject();

bool ret = AddTagData(fileHandle, tagData.Length, pointer);

pinnedArray.Free();


return ret;

}


[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool ConvertSidToStringSid(
[In] IntPtr sid,
[Out] out IntPtr sidString);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LocalFree(IntPtr hMem);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr handle);

public static string GetLastErrorMessage()
{
int len = MAX_ERROR_MESSAGE_SIZE;
string errorMessage = new string((char)0, len);

if (!GetLastErrorMessage(errorMessage, ref len))
{
errorMessage = new string((char)0, len);
if (!GetLastErrorMessage(errorMessage, ref len))
{
return "failed to get last error message.";
}
}

return errorMessage;
}

static public bool StartFilter(string registerKey, int threadCount, FilterDelegate filterCallback, DisconnectDelegate disconnectCallback)
{
if (!isFilterStarted)
{
if (!SetRegistrationKey(registerKey))
{
return false;
}

gchFilter = GCHandle.Alloc(filterCallback);
IntPtr filterCallbackPtr = Marshal.GetFunctionPointerForDelegate(filterCallback);

gchDisconnect = GCHandle.Alloc(disconnectCallback);
IntPtr disconnectCallbackPtr = Marshal.GetFunctionPointerForDelegate(disconnectCallback);

isFilterStarted = RegisterMessageCallback(threadCount, filterCallbackPtr, disconnectCallbackPtr);

}

return isFilterStarted;
}

static public void StopFilter()
{
if (isFilterStarted)
{
Disconnect();
gchFilter.Free();
gchDisconnect.Free();
isFilterStarted = false;
}

return;
}

static public bool IsFilterStarted
{
get { return isFilterStarted; }
}

}
}