前面 ​​ 安装驱动程序(1)----驱动预安装​​ 一文讨论了总线驱动/功能驱动和单层过滤驱动的安装,本文将讨论过滤驱动的安装。可能你会觉得奇怪,过滤驱动有必要需要单独讨论吗?

答案是肯定的。1.笔者的同事,前阵子遇到一个类过滤驱动,由于某些原因安装的时候出现问题。笔者凑过去一看,inf文件仅仅提供了ClassGuid,居然没有HardwareID这一栏。而以devcon install安装需要提供hardwareID,因此devcon被pass了,得另谋出路;2.设备堆栈中有多个过滤驱动,仍以toaster为例,如果为toaster选择安装%WinDDK%\src\general\toaster\wdm\inf\%ARCH%\toasterf.inf,那toaster设备栈上将有5个驱动程序:类过滤驱动clsupper/clslower,设备过滤驱动devupper/devlower和功能驱动本身toaster。如果想添加/移除制定位置上的一个过滤驱动,怎么办?带着这2个问题,我们往下看。

    先说安装类过滤驱动。MS提供了类过滤驱动的inf文件模板,位于%WinDDK%\src\setup\infs\clasfilt\ClasFilt.inf,只要替换其中的classguid和sys文件名并在inf文件中指明UpperFilter或LowerFilter即可。以toaster为例,如果想安装下层类过滤驱动,按如下方式修改ClassFilt.inf,即可(又要恢复虚拟机快照了):

[Version]
signature = "$Windows NT$"



; Distribution Media information
;
[SourceDisksNames]
1 = %ClasFilt.MediaDesc%


[SourceDisksFiles]
;原本是clasfilt.sys
clslower.sys = 1


[DestinationDirs]
;
; Driver to be installed in the drivers subdirectory.
;
DefaultDestDir = 12 ; DIRID_DRIVERS



[DefaultInstall.NT]
;CopyFiles = @clasfilt.sys 指向要拷贝的sys文件路径
CopyFiles = @clslower.sys
AddReg = ClassFilter_AddReg

[ClassFilter_AddReg]
;替换{setup-ClassGUID}为toaster的classguid 原本为HKLM, System\CurrentControlSet\Control

\Class\{setup-ClassGUID}, UpperFilters, 0x00010008, clasfilt
HKLM, System\CurrentControlSet\Control\Class\{b85b7c50-6a01-11d2-b841-00c04fad5171},

LowerFilters, 0x00010008, clasfilt


[DefaultInstall.NT.Services]
AddService = clasfilt, , clasfilt_Service_Inst, clasfilt_EventLog_Inst


[clasfilt_Service_Inst]
DisplayName = %ClasFilt.SvcDesc%
ServiceType = %SERVICE_KERNEL_DRIVER%
StartType = %SERVICE_DEMAND_START%
ErrorControl = %SERVICE_ERROR_IGNORE%
;原本为ServiceBinary = %12%\clasfilt.sys 指向驱动程序二进制文件的路径
ServiceBinary = %12%\clslower.sys

[clasfilt_EventLog_Inst]
AddReg = clasfilt_EventLog_AddReg


[clasfilt_EventLog_AddReg]
;HKR,,EventMessageFile, %REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot

%%\System32\drivers\clasfilt.sys"
HKR,,EventMessageFile, %REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%

%\System32\drivers\clslower.sys"
HKR,,TypesSupported, %REG_DWORD%, 7


[Strings]
;在注册表中显示的名字
ClasFilt.SvcDesc = "Lower Class Filter Driver"

; Change the media description to describe your media.
;
ClasFilt.MediaDesc = "Class Filter Driver Disc"


; Useful constants
SERVICE_KERNEL_DRIVER = 1
SERVICE_DEMAND_START = 3
SERVICE_ERROR_IGNORE = 0
REG_EXPAND_SZ = 0x00020000
REG_DWORD = 0x00010001

修改inf文件后,可以通过右键安装,也可以通过代码现实:

TCHAR szCommandLine[] = TEXT("DefaultInstall 132 .\\clasfilt.inf"); 
InstallHinfSection(NULL, NULL, szCommandLine, SW_SHOW);

来看下安装类过滤驱动前后对比:

以下是安装前

安装驱动程序(2)----安装过滤驱动_#define

安装驱动程序(2)----安装过滤驱动_#pragma_02

以下是右键安装后:

安装驱动程序(2)----安装过滤驱动_windows_03

安装驱动程序(2)----安装过滤驱动_windows_04

2.上面讨论了安装类过滤驱动,现在来讨论第二个问题,往现有设备栈中插入/删除设备过滤驱动。实现思路和前面创建虚拟设备差不多,都是通过SetupDi接口从注册表中获得信息。不过由于描述整个过程过于复杂,我决定还是直接贴出代码:

#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable : 4129)

#include <driverspecs.h>
#define _In_
#define _Inout_
#define _In_reads_
//#include "BtAcpi.h"

#pragma comment(lib,"setupapi.lib")
#pragma comment(lib,"difxapi.lib")
#pragma comment(lib,"Shlwapi.lib")
#pragma comment(lib,"bthprops.lib")

#include "CommonHeaders.h"
#include "addprofiledriver.h"

#if DBG
#include <assert.h>
#define ASSERT(condition) assert(condition)
#else
#define ASSERT(condition)
#endif

#ifdef _DEBUG
#define LOGMESSAGE(str) printf str;
#else
#define LOGMESSAGE(str)
#endif

DEFINE_GUID(GUID_DEVCLASS_MSTOASTER, 0xb85b7c50, 0x6a01, 0x11d2, 0xb8, 0x41, 0x00, 0xc0, 0x4f, 0xad, 0x51, 0x71);
//{b85b7c50-6a01-11d2-b841-00c04fad5171}

#define CMD_REMOVE_FILTER "/removefilter"
#define CMD_ADD_FILTER "/addfilter"

typedef enum TOS_ADD_FILTER_ERR_NO {
TOS_ADD_FILTER_GENERIC_ERROR = 1,
TOS_ADD_FILTER_COPY_SUCCESS,
TOS_ADD_FILTER_COPY_FAILED,
TOS_ADD_FILTER_FILE_NOT_FOUND,
TOS_ADD_FILTER_CREATE_SRV_FAILED,
TOS_ADD_FILTER_CREATE_SRV_SUCCESS,
TOS_ADD_FILTER_DELETE_SRV_FAILED,
TOS_ADD_FILTER_DELETE_SRV_SUCCESS,
TOS_ADD_PROFILE_DRV_SUCCESS,
TOS_ADD_FILTER_SRV_FAIL_HANDLED,
TOS_ADJUST_PRIVILEGES_FAILES,
TOS_SERVICE_MARKED_FOR_DELETION
};

typedef enum TOS_FIND_FILTER_ERR_NO {
TOS_FIND_FILTER_GENERIC_ERROR = 1,
TOS_FIND_FILTER_REG_FOUND,
TOS_FIND_FILTER_REG_NOT_FOUND,
TOS_FILTER_FILE_FOUND,
TOS_FILTER_FILE_NOT_FOUND,
TOS_64_BIT_OS,
TOS_NOT_64_BIT_OS
};

typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);


BOOLEAN
AddFilterDriver(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
_In_ IN LPTSTR Filter,
IN BOOLEAN UpperFilter
);

BOOLEAN
RemoveFilterDriver(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
_In_ IN LPTSTR Filter,
IN BOOLEAN UpperFilter
);


BOOLEAN CreateFilterService(IN LPTSTR Filter, WCHAR *filterFilePath);
BOOLEAN DeleteFilterService(IN LPTSTR Filter);

VOID RebootDevice();
INT32 FilterCopyFile(BOOL createService);
void
PrintFilters(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN BOOLEAN UpperFilters
);

LPTSTR
GetFilters(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN BOOLEAN UpperFilters
);

void PrintDeviceName(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData
);

BOOLEAN
DeviceNameMatches(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
_In_ IN LPTSTR DeviceName
);

PBYTE
GetDeviceRegistryProperty(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN DWORD Property,
OUT PDWORD PropertyRegDataType
);

BOOLEAN
RestartDevice(
IN HDEVINFO DeviceInfoSet,
IN OUT PSP_DEVINFO_DATA DeviceInfoData
);

BOOLEAN
PrependSzToMultiSz(
_In_ LPTSTR SzToPrepend,
_Inout_ LPTSTR *MultiSz
);

size_t
MultiSzLength(
_In_ IN LPTSTR MultiSz
);

size_t
MultiSzSearchAndDeleteCaseInsensitive(
_In_ IN LPTSTR FindThis,
_In_ IN LPTSTR FindWithin,
OUT size_t *NewStringLength
);

void GetFilterVersion(char *Version);
int GetFilterFileStatus();
int Is64BitProcess();
int uninstallFilter();
int installFilter();

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(X) (sizeof(X) / sizeof(*X))
#endif

int CreateServicepassed = 0;
HDEVINFO devInfoGlobal = INVALID_HANDLE_VALUE;
SP_DEVINFO_DATA devInfoDataGlobal;
BOOLEAN createServiceFail = FALSE;
BOOLEAN isFilterDriverUnInstallSuccess = FALSE;
BOOLEAN isFilterDriverInstallSuccess = FALSE;

int __cdecl _tmain(int argc, LPTSTR argv[])
{
// structs needed to contain information about devices
HDEVINFO devInfo = INVALID_HANDLE_VALUE;
SP_DEVINFO_DATA devInfoData;

// indices for stepping through devices, and device interface guids
int argIndex = 1;
int deviceIndex;

// variables used to deal with the command-line options of this program
BOOLEAN upperFilter = FALSE;

LPTSTR filterToAdd = TOS_BTFILTER_NAME;
LPTSTR filterToRemove = NULL;

LPTSTR filterDrvArg = NULL;
LPTSTR profileDrvArg = NULL;

BOOLEAN keepGoing = TRUE;
BOOLEAN createService = TRUE;





// parse arguments; nothing too exciting here //


if (argc <= 1 || argc >= 5){
return TOS_ADD_FILTER_GENERIC_ERROR;
}

for (argIndex = 1; argIndex < argc; argIndex++) {
#pragma prefast(suppress:6385, "Previously checked argIndex being less than argc. No buffer overflow.")
if ((_tcscmp(argv[argIndex], _T(CMD_REMOVE_FILTER)) == 0) || (_tcscmp(argv[argIndex], _T(CMD_ADD_FILTER)) == 0)
|| (_tcscmp(argv[argIndex], _T(CMD_COPY_FILTER_DRV_FILE)) == 0))
{
filterDrvArg = argv[argIndex];
}
else if ((_tcscmp(argv[argIndex], _T(CMD_ADD_A2DP_SCO_PROFILE)) == 0) || (_tcscmp(argv[argIndex], _T(CMD_ADD_A2DP_PROFILE)) == 0)
|| (_tcscmp(argv[argIndex], _T(CMD_ADD_SCO_PROFILE)) == 0) || (_tcscmp(argv[argIndex], _T(CMD_REMOVE_A2DP_SCO_PROFILE)) == 0)
|| (_tcscmp(argv[argIndex], _T(CMD_REMOVE_A2DP_PROFILE)) == 0) || (_tcscmp(argv[argIndex], _T(CMD_REMOVE_SCO_PROFILE)) == 0))
{
profileDrvArg = argv[argIndex];
}
else if (_tcscmp(argv[argIndex], _T(CMD_FORCE_REBOOT)) == 0) {
RebootDevice();
}
else {
return TOS_ADD_FILTER_GENERIC_ERROR;
}
}
if (NULL != profileDrvArg)
{
if (InstallProfileDriver(profileDrvArg, 6)) {
LOGMESSAGE(("Silent Profile Driver installation success!!! \r\n"));
}
else {
if (InstallProfileDriver(profileDrvArg, 0)) {
LOGMESSAGE(("Profile Driver installation success!!! \r\n"));
}
else {
LOGMESSAGE(("Profile Driver installation failed!!! \r\n"));
return TOS_ADD_FILTER_GENERIC_ERROR;
}
}
}

if (NULL == filterDrvArg)
{
return TOS_ADD_PROFILE_DRV_SUCCESS;
}

if (_tcscmp(filterDrvArg, _T(CMD_REMOVE_FILTER)) == 0) {
createService = FALSE;
LOGMESSAGE(("Deleting Filter!!! \r\n"));
}
else if (_tcscmp(filterDrvArg, _T(CMD_ADD_FILTER)) == 0) {
createService = TRUE;
LOGMESSAGE(("Adding Filter driver!!! \r\n"));
}
else if (_tcscmp(filterDrvArg, _T(CMD_COPY_FILTER_DRV_FILE)) == 0) {
int ret = FilterCopyFile(FALSE);

return ret;
}
else {
return (TOS_ADD_FILTER_GENERIC_ERROR);
}

if (createService == FALSE) {
filterToRemove = TOS_BTFILTER_NAME;
filterToAdd = NULL;
}

devInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_MSTOASTER,
NULL,
NULL,
DIGCF_PRESENT);

if (devInfo == INVALID_HANDLE_VALUE) {
LOGMESSAGE(("got INVALID_HANDLE_VALUE!\n"));
return (TOS_ADD_FILTER_GENERIC_ERROR);
}

// as per DDK docs on SetupDiEnumDeviceInfo
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

// step through the list of devices for this handle
// get device info at index deviceIndex, the function returns FALSE
// when there is no device at the given index.
for (deviceIndex = 0;
SetupDiEnumDeviceInfo(devInfo, deviceIndex, &devInfoData);
deviceIndex++) {

// setting this variable to FALSE will cause all of the if
// statements to fall through, cutting off processing for this
// device.
keepGoing = TRUE;

LPTSTR buffer = NULL;
LPTSTR hardWareName = L"{B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsToaster";

DWORD buffersize = 0;
DWORD DataT;

SetupDiGetDeviceRegistryProperty(
devInfo,
&devInfoData,
SPDRP_HARDWAREID,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize);

if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
buffer = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, buffersize * 2);

if (buffer == NULL)
continue;

SetupDiGetDeviceRegistryProperty(
devInfo,
&devInfoData,
SPDRP_HARDWAREID,
&DataT,
(PBYTE)buffer,
buffersize,
&buffersize);

if (!memcmp(buffer, hardWareName, 16))
{
LOGMESSAGE(("hardware USB adapter found !!!!\r\n"));
HeapFree(GetProcessHeap(), 0, buffer);
}
else {
HeapFree(GetProcessHeap(), 0, buffer);
continue;
}

// print the device name
if (keepGoing) {

PrintDeviceName(devInfo, &devInfoData);
}
devInfoGlobal = devInfo;
devInfoDataGlobal = devInfoData;

// print the drivers, if we are not adding or removing one
if (keepGoing && filterToAdd == NULL && filterToRemove == NULL) {
PrintFilters(devInfo, &devInfoData, upperFilter);
}


int ret;
// add the filter, then try to restart the device
if ((keepGoing && filterToAdd != NULL))
{
ret = installFilter();

if (ret == TOS_SERVICE_MARKED_FOR_DELETION)
{
uninstallFilter();
//Sleep(1000);
uninstallFilter();
//Sleep(1000);
uninstallFilter();
//Sleep(1000);
installFilter();
}
}

// remove the filter, then try to restart the device
if ((keepGoing && filterToRemove != NULL))
{
uninstallFilter();
//Sleep(1000);
uninstallFilter();
//Sleep(1000);
uninstallFilter();
}
}

// clean up the device list
if (devInfo != INVALID_HANDLE_VALUE) {

if (!SetupDiDestroyDeviceInfoList(devInfo)) {
LOGMESSAGE(("unable to delete device info list! error: %u\n",
GetLastError()));
}
}

if (TRUE == isFilterDriverUnInstallSuccess) {
return TOS_ADD_FILTER_DELETE_SRV_SUCCESS;
}

if (!isFilterDriverInstallSuccess) {
return TOS_ADD_FILTER_GENERIC_ERROR;
}
//Sleep(100000);
return (TOS_ADD_FILTER_CREATE_SRV_SUCCESS);
}


/*
* add the given filter driver to the list of upper filter drivers for the
* device.
*
* After the call, the device must be restarted in order for the new setting to
* take effect. This can be accomplished with a call to RestartDevice(), or by
* rebooting the machine.
*
* returns TRUE if successful, FALSE otherwise
*
* note: The filter is prepended to the list of drivers, which will put it at
* the bottom of the filter driver stack
*
* parameters:
* DeviceInfoSet - The device information set which contains DeviceInfoData
* DeviceInfoData - Information needed to deal with the given device
* Filter - the filter to add
*/
BOOLEAN
AddFilterDriver(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
_In_ IN LPTSTR Filter,
IN BOOLEAN UpperFilter
)
{
size_t length = 0; // character length
size_t size = 0; // buffer size
LPTSTR buffer = GetFilters( DeviceInfoSet, DeviceInfoData, UpperFilter );

ASSERT(DeviceInfoData != NULL);
ASSERT(Filter != NULL);

if( buffer == NULL )
{
// if there is no such value in the registry, then there are no upper
// filter drivers loaded, and we can just put one there

// make room for the string, string null terminator, and multisz null
// terminator
length = _tcslen(Filter)+1;
size = (length+1)*sizeof(_TCHAR);
buffer = (LPTSTR)malloc(size);
if( buffer == NULL )
{
LOGMESSAGE(("in AddUpperFilterDriver(): unable to allocate memory!\n"));
return (FALSE);
}
memset(buffer, 0, size);

// copy the string into the new buffer

memcpy(buffer, Filter, length*sizeof(_TCHAR));

}
else
{
LPTSTR buffer2;
// remove all instances of filter from driver list
MultiSzSearchAndDeleteCaseInsensitive( Filter, buffer, &length );

// allocate a buffer large enough to add the new filter
// MultiSzLength already includes length of terminating NULL

// determing the new length of the string
length = MultiSzLength(buffer) + _tcslen(Filter) + 1;
size = length*sizeof(_TCHAR);

buffer2 = (LPTSTR)malloc(size);
if (buffer2 == NULL) {
LOGMESSAGE(("Out of memory adding filter\n"));
return (0);
}
memset(buffer2, 0, size);

// swap the buffers out
memcpy(buffer2, buffer, MultiSzLength(buffer)*sizeof(_TCHAR));
free(buffer);
buffer = buffer2;

// add the driver to the driver list
PrependSzToMultiSz(Filter, &buffer);

}

// set the new list of filters in place
if( !SetupDiSetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
(UpperFilter ? SPDRP_UPPERFILTERS : SPDRP_LOWERFILTERS),
(PBYTE)buffer,
(DWORD)(MultiSzLength(buffer)*sizeof(_TCHAR)) )
)
{
LOGMESSAGE(("in AddUpperFilterDriver(): "
"couldn't set registry value! error: %u\n", GetLastError()));
free( buffer );
return (FALSE);
}

// no need for buffer anymore
free( buffer );

return (TRUE);
}


/*
* remove all instances of the given filter driver from the list of upper
* filter drivers for the device.
*
* After the call, the device must be restarted in order for the new setting to
* take effect. This can be accomplished with a call to RestartDevice(), or by
* rebooting the machine.
*
* returns TRUE if successful, FALSE otherwise
*
* parameters:
* DeviceInfoSet - The device information set which contains DeviceInfoData
* DeviceInfoData - Information needed to deal with the given device
* Filter - the filter to remove
*/
BOOLEAN
RemoveFilterDriver(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
_In_ IN LPTSTR Filter,
IN BOOLEAN UpperFilter
)
{
size_t length = 0;
size_t size = 0;
LPTSTR buffer = GetFilters( DeviceInfoSet, DeviceInfoData, UpperFilter );
BOOL success = FALSE;

ASSERT(DeviceInfoData != NULL);
ASSERT(Filter != NULL);

if( buffer == NULL )
{
// if there is no such value in the registry, then there are no upper
// filter drivers loaded, and we are done
return (TRUE);
}
else
{
// remove all instances of filter from driver list
MultiSzSearchAndDeleteCaseInsensitive( Filter, buffer, &length );
}

length = MultiSzLength(buffer);

ASSERT ( length > 0 );

if( length == 1 )
{
// if the length of the list is 1, the return value from
// MultiSzLength() was just accounting for the trailing '\0', so we can
// delete the registry key, by setting it to NULL.
success = SetupDiSetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
(UpperFilter ? SPDRP_UPPERFILTERS : SPDRP_LOWERFILTERS),
NULL,
0 );
}
else
{
// set the new list of drivers into the registry
size = length*sizeof(_TCHAR);
success = SetupDiSetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
(UpperFilter ? SPDRP_UPPERFILTERS : SPDRP_LOWERFILTERS),
(PBYTE)buffer,
(DWORD)size );
}

// no need for buffer anymore
free( buffer );

if( !success )
{
LOGMESSAGE(("in RemoveUpperFilterDriver(): "
"couldn't set registry value! error: %u\n", GetLastError()));
return (FALSE);
}

return (TRUE);
}

/*
* print the list of upper filters for the given device
*
* parameters:
* DeviceInfoSet - The device information set which contains DeviceInfoData
* DeviceInfoData - Information needed to deal with the given device
*/
void
PrintFilters(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN BOOLEAN UpperFilters
)
{
// get the list of filters
LPTSTR buffer = GetFilters( DeviceInfoSet, DeviceInfoData, UpperFilters );
LPTSTR filterName;
size_t filterPosition;

if( buffer == NULL )
{
// if there is no such value in the registry, then there are no upper
// filter drivers loaded
LOGMESSAGE(("There are no upper filter drivers loaded for this device.\n"));
}
else
{
// go through the multisz and print out each driver
filterPosition=0;
filterName = buffer;
while( *filterName != _T('\0') )
{
#ifdef _DEBUG
_tprintf(_T("%u: %s\n"), filterPosition, filterName);
#endif
filterName += _tcslen(filterName)+1;
filterPosition++;
}

// no need for buffer anymore
free( buffer );
}

return;
}

/*
* print the device name
*
* parameters:
* DeviceInfoSet - The device information set which contains DeviceInfoData
* DeviceInfoData - Information needed to deal with the given device
*/
void PrintDeviceName(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData
)
{
DWORD regDataType;
//char s1[1000];

/*LPTSTR deviceName =
(LPTSTR) GetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
®DataType );*/
LPTSTR deviceName =
(LPTSTR)GetDeviceRegistryProperty(DeviceInfoSet,
DeviceInfoData,
SPDRP_HARDWAREID,
®DataType);
//SPDRP_HARDWAREID

_tprintf(_T("%s\n"), deviceName);
//wchar_t(s1, "%s", deviceName);
//const char* cpy = _T(deviceName);
//char *y;
if( deviceName != NULL )
{
// just to make sure we are getting the expected type of buffer
if( regDataType != REG_SZ )
{
LOGMESSAGE(("in PrintDeviceName(): registry key is not an SZ!\n"));
}
else
{
// if the device name starts with \Device, cut that off (all
// devices will start with it, so it is redundant)

if( _tcsncmp(deviceName, _T("\\Device"), 7) == 0 )
{
memmove(deviceName,
deviceName+7,
(_tcslen(deviceName)-6)*sizeof(_TCHAR) );
}

_tprintf(_T("%s\n"), deviceName);
}
free( deviceName );
}
else
{
LOGMESSAGE(("in PrintDeviceName(): registry key is NULL! error: %u\n",
GetLastError()));
}

return;
}

/*
* Returns a buffer containing the list of upper filters for the device. (NULL
* is returned if there is no buffer, or an error occurs)
* The buffer must be freed by the caller.
*
* parameters:
* DeviceInfoSet - The device information set which contains DeviceInfoData
* DeviceInfoData - Information needed to deal with the given device
*/
LPTSTR
GetFilters(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN BOOLEAN UpperFilters
)
{
DWORD regDataType;
LPTSTR buffer = (LPTSTR) GetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
(UpperFilters ? SPDRP_UPPERFILTERS : SPDRP_LOWERFILTERS),
®DataType );

// just to make sure we are getting the expected type of buffer
if( buffer != NULL && regDataType != REG_MULTI_SZ )
{
LOGMESSAGE(("in GetUpperFilters(): "
"registry key is not a MULTI_SZ!\n"));
free( buffer );
return (NULL);
}

return (buffer);
}

/*
* return true if DeviceName matches the name of the device specified by
* DeviceInfoData
*
* parameters:
* DeviceInfoSet - The device information set which contains DeviceInfoData
* DeviceInfoData - Information needed to deal with the given device
* DeviceName - the name to try to match
*/
BOOLEAN
DeviceNameMatches(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
_In_ IN LPTSTR DeviceName
)
{
BOOLEAN matching = FALSE;
DWORD regDataType;

// get the device name
LPTSTR deviceName =
(LPTSTR) GetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
®DataType );

if( deviceName != NULL )
{
// just to make sure we are getting the expected type of buffer
if( regDataType != REG_SZ )
{
LOGMESSAGE(("in DeviceNameMatches(): registry key is not an SZ!\n"));
matching = FALSE;
}
else
{
// if the device name starts with \Device, cut that off (all
// devices will start with it, so it is redundant)

if( _tcsncmp(deviceName, _T("\\Device"), 7) == 0 )
{
memmove(deviceName,
deviceName+7,
(_tcslen(deviceName)-6)*sizeof(_TCHAR) );
}

// do the strings match?
matching = (_tcscmp(deviceName, DeviceName) == 0) ? TRUE : FALSE;
}
free( deviceName );
}
else
{
LOGMESSAGE(("in DeviceNameMatches(): registry key is NULL!\n"));
matching = FALSE;
}

return (matching);
}

/*
* A wrapper around SetupDiGetDeviceRegistryProperty, so that I don't have to
* deal with memory allocation anywhere else
*
* parameters:
* DeviceInfoSet - The device information set which contains DeviceInfoData
* DeviceInfoData - Information needed to deal with the given device
* Property - which property to get (SPDRP_XXX)
* PropertyRegDataType - the type of registry property
*/
PBYTE
GetDeviceRegistryProperty(
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData,
IN DWORD Property,
OUT PDWORD PropertyRegDataType
)
{
DWORD length = 0;
PBYTE buffer = NULL;

// get the required length of the buffer
if( SetupDiGetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
Property,
NULL, // registry data type
NULL, // buffer
0, // buffer size
&length // required size
) )
{
// we should not be successful at this point, so this call succeeding
// is an error condition
LOGMESSAGE(("in GetDeviceRegistryProperty(): "
"call SetupDiGetDeviceRegistryProperty did not fail? (%x)\n",
GetLastError()));
return (NULL);
}

if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
{
// this means there are no upper filter drivers loaded, so we can just
// return.
return (NULL);
}

// since we don't have a buffer yet, it is "insufficient"; we allocate
// one and try again.
buffer = (BYTE*)malloc( length );
if( buffer == NULL )
{
LOGMESSAGE(("in GetDeviceRegistryProperty(): "
"unable to allocate memory!\n"));
return (NULL);
}
if( !SetupDiGetDeviceRegistryProperty( DeviceInfoSet,
DeviceInfoData,
Property,
PropertyRegDataType,
buffer,
length,
NULL // required size
) )
{
LOGMESSAGE(("in GetDeviceRegistryProperty(): "
"couldn't get registry property! error: %u\n",
GetLastError()));
free( buffer );
return (NULL);
}

// ok, we are finally done, and can return the buffer
return (buffer);
}


/*
* restarts the given device
*
* call CM_Query_And_Remove_Subtree (to unload the driver)
* call CM_Reenumerate_DevNode on the _parent_ (to reload the driver)
*
* parameters:
* DeviceInfoSet - The device information set which contains DeviceInfoData
* DeviceInfoData - Information needed to deal with the given device
*/
BOOLEAN
RestartDevice(
IN HDEVINFO DeviceInfoSet,
IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
{
SP_PROPCHANGE_PARAMS params;
SP_DEVINSTALL_PARAMS installParams;

// for future compatibility; this will zero out the entire struct, rather
// than just the fields which exist now
memset(¶ms, 0, sizeof(SP_PROPCHANGE_PARAMS));

// initialize the SP_CLASSINSTALL_HEADER struct at the beginning of the
// SP_PROPCHANGE_PARAMS struct, so that SetupDiSetClassInstallParams will
// work
params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;

// initialize SP_PROPCHANGE_PARAMS such that the device will be stopped.
params.StateChange = DICS_STOP;
params.Scope = DICS_FLAG_CONFIGSPECIFIC;
params.HwProfile = 0; // current profile

// prepare for the call to SetupDiCallClassInstaller (to stop the device)
if( !SetupDiSetClassInstallParams( DeviceInfoSet,
DeviceInfoData,
(PSP_CLASSINSTALL_HEADER) ¶ms,
sizeof(SP_PROPCHANGE_PARAMS)
) )
{
LOGMESSAGE(("in RestartDevice(): couldn't set the install parameters!"));
LOGMESSAGE((" error: %u\n", GetLastError()));
return (FALSE);
}

// stop the device
if( !SetupDiCallClassInstaller( DIF_PROPERTYCHANGE,
DeviceInfoSet,
DeviceInfoData )
)
{
LOGMESSAGE(("in RestartDevice(): call to class installer (STOP) failed!"));
LOGMESSAGE((" error: %u\n", GetLastError()));
return (FALSE);
}

// restarting the device
params.StateChange = DICS_START;

// prepare for the call to SetupDiCallClassInstaller (to stop the device)
if( !SetupDiSetClassInstallParams( DeviceInfoSet,
DeviceInfoData,
(PSP_CLASSINSTALL_HEADER) ¶ms,
sizeof(SP_PROPCHANGE_PARAMS)
) )
{
LOGMESSAGE(("in RestartDevice(): couldn't set the install parameters!"));
LOGMESSAGE((" error: %u\n", GetLastError()));
return (FALSE);
}

// restart the device
if( !SetupDiCallClassInstaller( DIF_PROPERTYCHANGE,
DeviceInfoSet,
DeviceInfoData )
)
{
LOGMESSAGE(("in RestartDevice(): call to class installer (START) failed!"));
LOGMESSAGE((" error: %u\n", GetLastError()));
return (FALSE);
}

installParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);

// same as above, the call will succeed, but we still need to check status
if( !SetupDiGetDeviceInstallParams( DeviceInfoSet,
DeviceInfoData,
&installParams )
)
{
LOGMESSAGE(("in RestartDevice(): couldn't get the device install params!"));
LOGMESSAGE((" error: %u\n", GetLastError()));
return (FALSE);
}

// to see if the machine needs to be rebooted
if( installParams.Flags & DI_NEEDREBOOT )
{
return (FALSE);
}

// if we get this far, then the device has been stopped and restarted
return (TRUE);
}


/*
* prepend the given string to a MultiSz
*
* returns true if successful, false if not (will only fail in memory
* allocation)
*
* note: This WILL allocate and free memory, so don't keep pointers to the
* MultiSz passed in.
*
* parameters:
* SzToPrepend - string to prepend
* MultiSz - pointer to a MultiSz which will be prepended-to
*/
BOOLEAN
PrependSzToMultiSz(
_In_ LPTSTR SzToPrepend,
_Inout_ LPTSTR *MultiSz
)
{
size_t szLen;
size_t multiSzLen;
LPTSTR newMultiSz = NULL;

ASSERT(SzToPrepend != NULL);
ASSERT(MultiSz != NULL);

if (SzToPrepend == NULL || MultiSz == NULL) {
return (FALSE);
}

// get the size, in bytes, of the two buffers
szLen = (_tcslen(SzToPrepend)+1)*sizeof(_TCHAR);
multiSzLen = MultiSzLength(*MultiSz)*sizeof(_TCHAR);
newMultiSz = (LPTSTR)malloc( szLen+multiSzLen );

if( newMultiSz == NULL )
{
return (FALSE);
}

// recopy the old MultiSz into proper position into the new buffer.
// the (char*) cast is necessary, because newMultiSz may be a wchar*, and
// szLen is in bytes.

memcpy( ((char*)newMultiSz) + szLen, *MultiSz, multiSzLen );

// copy in the new string
StringCbCopy( newMultiSz, szLen, SzToPrepend );

free( *MultiSz );
*MultiSz = newMultiSz;

return (TRUE);
}


/*
* returns the length (in characters) of the buffer required to hold this
* MultiSz, INCLUDING the trailing null.
*
* example: MultiSzLength("foo\0bar\0") returns 9
*
* note: since MultiSz cannot be null, a number >= 1 will always be returned
*
* parameters:
* MultiSz - the MultiSz to get the length of
*/
size_t
MultiSzLength(
_In_ IN LPTSTR MultiSz
)
{
size_t len = 0;
size_t totalLen = 0;

ASSERT( MultiSz != NULL );

// search for trailing null character
while( *MultiSz != _T('\0') )
{
len = _tcslen(MultiSz)+1;
MultiSz += len;
totalLen += len;
}

// add one for the trailing null character
return (totalLen+1);
}


/*
* Deletes all instances of a string from within a multi-sz.
*
* parameters:
* FindThis - the string to find and remove
* FindWithin - the string having the instances removed
* NewStringLength - the new string length
*/
size_t
MultiSzSearchAndDeleteCaseInsensitive(
_In_ IN LPTSTR FindThis,
_In_ IN LPTSTR FindWithin,
OUT size_t *NewLength
)
{
LPTSTR search;
size_t currentOffset;
DWORD instancesDeleted;
size_t searchLen;

ASSERT(FindThis != NULL);
ASSERT(FindWithin != NULL);
ASSERT(NewLength != NULL);

currentOffset = 0;
instancesDeleted = 0;
search = FindWithin;

*NewLength = MultiSzLength(FindWithin);

// loop while the multisz null terminator is not found
while ( *search != _T('\0') )
{
// length of string + null char; used in more than a couple places
searchLen = _tcslen(search) + 1;

// if this string matches the current one in the multisz...
if( _tcsicmp(search, FindThis) == 0 )
{
// they match, shift the contents of the multisz, to overwrite the
// string (and terminating null), and update the length
instancesDeleted++;
*NewLength -= searchLen;
memmove( search,
search + searchLen,
(*NewLength - currentOffset) * sizeof(TCHAR) );
}
else
{
// they don't mactch, so move pointers, increment counters
currentOffset += searchLen;
search += searchLen;
}
}

return (instancesDeleted);
}

BOOLEAN CreateFilterService(IN LPTSTR Filter, WCHAR *filterFilePath) {
UNREFERENCED_PARAMETER(filterFilePath);
SC_HANDLE sc_mng = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);

if (sc_mng == NULL) {
LOGMESSAGE(("CreateFilterService : OpenSCManager failed (%d)\n", GetLastError()));
return FALSE;
}

// Mohit : No need to check return value of CreateService() , as it will always return fail without reboot.
SC_HANDLE handle = CreateService(sc_mng, Filter, NULL, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, filterFilePath, NULL, NULL, NULL, NULL, NULL);
if (handle == NULL)
{
CreateServicepassed = 0;
LOGMESSAGE(("CreateFilterService : CreateService failed (%d)\n", GetLastError()));
if (GetLastError() == ERROR_SERVICE_EXISTS) // Mohit : If service already exists
{
handle = OpenService(sc_mng, Filter, SERVICE_ALL_ACCESS);
if (handle == NULL)
{
LOGMESSAGE(("CreateFilterService : OpenService failed (%d)\n", GetLastError()));
}
else
{
LOGMESSAGE(("CreateFilterService : OpenService Passed\n"));
}
}
if (GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE) // Mohit : If service already exists
{
LOGMESSAGE(("CreateFilterService: DeleteService Failed due to error: ERROR_SERVICE_MARKED_FOR_DELETE \n"));
CreateServicepassed = TOS_SERVICE_MARKED_FOR_DELETION;
//Sleep(100);

//system("BTRestart.exe");
}
}
else
{
CreateServicepassed = 1;
LOGMESSAGE(("CreateFilterService : CreateService passed\n"));
}


CloseServiceHandle(handle);
CloseServiceHandle(sc_mng);
return TRUE;
}

BOOLEAN DeleteFilterService(IN LPTSTR Filter) {
BOOLEAN ret = TRUE;
SC_HANDLE sc_mng = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
WCHAR SystemFilePath[MAX_PATH];

if (sc_mng == NULL) {
LOGMESSAGE(("DeleteFilterService : OpenSCManager failed (%d)\n", GetLastError()));
return FALSE;
}

SC_HANDLE handle = OpenService(sc_mng, Filter, SERVICE_ALL_ACCESS);

if (handle == NULL) {
LOGMESSAGE(("DeleteFilterService: OpenService Failed (%d) \n", GetLastError()));
if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
{
LOGMESSAGE(("DeleteFilterService: OpenService Failed due to error: ERROR_SERVICE_DOES_NOT_EXIST \n"));
}
CloseServiceHandle(sc_mng);
//return FALSE;
goto NEXT;
}
else
{
LOGMESSAGE(("DeleteFilterService: OpenService Passed \n"));
}

//StopServ
BOOL ret1,ret2;
ret1 = DeleteService(handle);
if (ret1 == FALSE) {
LOGMESSAGE(("DeleteFilterService: DeleteService Failed (%d) \n", GetLastError()));
if (GetLastError() == 1072) // Mohit : ERROR_SERVICE_MARKED_FOR_DELETE
{
LOGMESSAGE(("DeleteFilterService: DeleteService Failed due to error: ERROR_SERVICE_MARKED_FOR_DELETE \n"));
SERVICE_STATUS ServiceStatusStruct;
ret2 = QueryServiceStatus(handle, &ServiceStatusStruct);
if (ret2 == 0)
{
LOGMESSAGE(("DeleteFilterService: QueryServiceStatus Failed (%d) \n", GetLastError()));
}
else
{
LOGMESSAGE(("DeleteFilterService: QueryServiceStatus Failed (%d) \n", ServiceStatusStruct.dwCurrentState));
}
}
CloseServiceHandle(sc_mng);
//return FALSE;
}
else
{
LOGMESSAGE(("DeleteFilterService: DeleteService Passed \n"));
}

NEXT: if (!GetSystemDirectory((LPWSTR)SystemFilePath, sizeof(SystemFilePath))) {
LOGMESSAGE(("Unable to get system file path \r\n"));
// TODO copy default C:\\Windows\\System32\\drivers\\TosBTFilter.sys path
return TOS_ADD_FILTER_GENERIC_ERROR;
}
else {
PTSTR LastSystemSlash;
LastSystemSlash = _tcsrchr(SystemFilePath, _T('\\'));

if (!LastSystemSlash)
{
LOGMESSAGE(("Last system slash error \r\n"));
// TODO - Copy default C:\\Windows\\System32\\drivers\\TosBTFilter.sys
return TOS_ADD_FILTER_GENERIC_ERROR;
}
else {
LastSystemSlash++;
TCHAR ToAppendDriverPath[] = _T(TOS_BTFILTER_SYSTEM_PATH);
if (ARRAY_SIZE(ToAppendDriverPath) > ARRAY_SIZE(SystemFilePath) - (LastSystemSlash - SystemFilePath))
{
LOGMESSAGE(("Array size exceeded \r\n"));
// TODO - Copy default C:\\Windows\\System32\\drivers\\TosBTFilter.sys
return TOS_ADD_FILTER_GENERIC_ERROR;
}
memcpy(LastSystemSlash, ToAppendDriverPath, sizeof(ToAppendDriverPath));
}
}

if (FALSE == AdjustProcessPrivileges())
{
return TOS_ADJUST_PRIVILEGES_FAILES;
}
//BOOL ret2;

CloseServiceHandle(handle);
CloseServiceHandle(sc_mng);

system("BTRestart.exe");

ret1 = DeleteFile(SystemFilePath);

if (ret1 == FALSE) {
LOGMESSAGE(("DeleteFile failed, error code = %u \r\n", GetLastError()));
if (GetLastError() == 2) // Mohit : File not found
{
LOGMESSAGE(("DeleteFilterService: DeleteFile Failed as the File is not found(.sys file) \n"));
//ret = FALSE;
//return ret;
}

}

return ret;
}

void RebootDevice() {
LOGMESSAGE(("rebooting device \r\n"));
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES |
TOKEN_QUERY,
&hToken);

TOKEN_PRIVILEGES tk;
tk.PrivilegeCount = 1;
tk.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

LookupPrivilegeValue(
NULL,
TEXT("SeShutdownPrivilege"),
&tk.Privileges[0].Luid);

AdjustTokenPrivileges(
hToken,
FALSE,
&tk,
0,
NULL,
0);

ExitWindowsEx(0x00000002, 0);
}


INT32 FilterCopyFile(BOOL createService) {

WCHAR FilterFilePath[MAX_PATH];
WCHAR SystemFilePath[MAX_PATH];
LPTSTR filterToAdd = TOS_BTFILTER_NAME;

PTSTR LastSlash;
if (!GetModuleFileName(NULL, FilterFilePath, MAX_PATH)) {
LOGMESSAGE(("Unable to get module name \r\n"));
return TOS_ADD_FILTER_GENERIC_ERROR;
}

LastSlash = _tcsrchr(FilterFilePath, _T('\\'));

if (!LastSlash)
{
LOGMESSAGE(("FilterCopyFile: Last slash error \r\n"));
// TODO - this shouldn't happen. treat it as an error.
return TOS_ADD_FILTER_GENERIC_ERROR;
}

LastSlash++;

TCHAR ToAppend[] = _T(TOS_BTFILTER_TNAME);

if (ARRAY_SIZE(ToAppend) > ARRAY_SIZE(FilterFilePath) - (LastSlash - FilterFilePath))
{
LOGMESSAGE(("FilterCopyFile: Array size exceeded\r\n"));
return TOS_ADD_FILTER_GENERIC_ERROR;
}

memcpy(LastSlash, ToAppend, sizeof(ToAppend));

if (!PathFileExists(FilterFilePath))
return TOS_ADD_FILTER_FILE_NOT_FOUND;

if (!GetSystemDirectory((LPWSTR)SystemFilePath, sizeof(SystemFilePath))) {
LOGMESSAGE(("FilterCopyFile: Unable to get system file path \r\n"));
// TODO copy default C:\\Windows\\System32\\drivers\\TosBTFilter.sys path
return TOS_ADD_FILTER_GENERIC_ERROR;
}
else {
PTSTR LastSystemSlash;
LastSystemSlash = _tcsrchr(SystemFilePath, _T('\\'));

if (!LastSystemSlash)
{
LOGMESSAGE(("FilterCopyFile: Last system slash error \r\n"));
// TODO - Copy default C:\\Windows\\System32\\drivers\\TosBTFilter.sys
return TOS_ADD_FILTER_GENERIC_ERROR;
}
else {
LastSystemSlash++;
TCHAR ToAppendDriverPath[] = _T(TOS_BTFILTER_SYSTEM_PATH);
if (ARRAY_SIZE(ToAppendDriverPath) > ARRAY_SIZE(SystemFilePath) - (LastSystemSlash - SystemFilePath))
{
LOGMESSAGE(("FilterCopyFile: Array size exceeded \r\n"));
// TODO - Copy default C:\\Windows\\System32\\drivers\\TosBTFilter.sys
return TOS_ADD_FILTER_GENERIC_ERROR;
}
memcpy(LastSystemSlash, ToAppendDriverPath, sizeof(ToAppendDriverPath));
}
}

int ret = TOS_ADD_FILTER_GENERIC_ERROR;

if (FALSE == AdjustProcessPrivileges())
{
return TOS_ADJUST_PRIVILEGES_FAILES;
}


int fileStatus = GetFilterFileStatus();
int DriverVersionSame;


/*LPTSTR ExistedFilterDriver = L"C:\Windows\System32\drivers\TosBTFilter.sys";*/

if (fileStatus == TOS_FILTER_FILE_NOT_FOUND)
{
LOGMESSAGE(("FilterCopyFile: Driver File Doesnt Exist , so need to copy it. \r\n"));
if (!CopyFile(FilterFilePath, SystemFilePath, FALSE))
{
//LOGMESSAGE(("CopyFile Failed \r\n"));
LOGMESSAGE(("FilterCopyFile: CopyFile failed, error code = %u \r\n", GetLastError()));
ret = TOS_ADD_FILTER_COPY_FAILED;
}
else {
LOGMESSAGE(("FilterCopyFile: File Copied \r\n"));
ret = TOS_ADD_FILTER_COPY_SUCCESS;
}
}

if (fileStatus == TOS_FILTER_FILE_FOUND)
{
char Version[4] = { 0 };

//char InstalledVer[24] = "08/31/2015,11.20.46.927"; // Need to change this version with each new driver release.
char InstalledVer[4] = "1.0"; // Need to change this version with each new driver release.
char i;

LOGMESSAGE(("FilterCopyFile: Driver File already Exists , so need to check Driver Version before copy. \r\n"));
GetFilterVersion(Version);
for (i = 0; i < 3; i++)
{
if (Version[i] != InstalledVer[i])
break;
}

LOGMESSAGE(("FilterCopyFile: i = %d \r\n", i));

if (i == 3)
{
DriverVersionSame = 1;
LOGMESSAGE(("FilterCopyFile: Driver Version is same, So no need to copy Driver File \r\n"));
ret = TOS_ADD_FILTER_COPY_SUCCESS;
}
else
{
DriverVersionSame = 0;
LOGMESSAGE(("FilterCopyFile: Driver Version is diferent, So we need to copy Driver File \r\n")); // This is the case of update , need to implement moe complex logic or restart
if (!CopyFile(FilterFilePath, SystemFilePath, FALSE))
{
//LOGMESSAGE(("CopyFile Failed \r\n"));
LOGMESSAGE(("FilterCopyFile: CopyFile failed, error code = %u \r\n", GetLastError()));
ret = TOS_ADD_FILTER_COPY_FAILED;
}
else {
LOGMESSAGE(("FilterCopyFile: File Copied \r\n"));
ret = TOS_ADD_FILTER_COPY_SUCCESS;
}
}

}


if (createService == FALSE || ret != TOS_ADD_FILTER_COPY_SUCCESS)
return ret;

if (!CreateFilterService(filterToAdd, SystemFilePath))
ret = TOS_ADD_FILTER_CREATE_SRV_FAILED;
else
ret = TOS_ADD_FILTER_CREATE_SRV_SUCCESS;

LOGMESSAGE(("FilterCopyFile: ret = %d \r\n", ret));
return ret;
}


void GetFilterVersion(char *Version)
{
char ch, ch1, ch2, ch3, ch4, i;
char VersionNum[4];
FILE *fp;

//printf("Enter the name of file you wish to see\n");
//gets(file_name);

fp = fopen("TosBTFilter.inf", "r"); // read mode

if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}

//printf("The contents of %s file are :\n", file_name);

while ((ch = (char)fgetc(fp)) != EOF)
{
ch1 = ch;
if (ch1 == 'V')
{
ch2 = (char)fgetc(fp);
ch3 = (char)fgetc(fp);
ch4 = (char)fgetc(fp);
if ((ch2 == 'e') && (ch3 == 'r') && (ch4 == '='))
{
for (i = 0; i < 3; i++)
{
VersionNum[i] = (char)fgetc(fp);
}
}
}
}
//printf("%c", ch);
for (i = 0; i < 3; i++)
{
Version[i] = VersionNum[i];
}

fclose(fp);

}


int GetFilterFileStatus() {
WCHAR SystemFilePath[MAX_PATH];

if (!GetSystemDirectory((LPWSTR)SystemFilePath, sizeof(SystemFilePath))) {
//LOGMESSAGE(L"Unable to get system file path \r\n");
return TOS_FILTER_FILE_NOT_FOUND;
}
else {
PTSTR LastSystemSlash;
LastSystemSlash = _tcsrchr(SystemFilePath, _T('\\'));

if (!LastSystemSlash)
{
//LOGMESSAGE(L"Last system slash error \r\n");
return TOS_FILTER_FILE_NOT_FOUND;
}
else {
LastSystemSlash++;
//TCHAR ToAppendDriverPath[] = _T("system32\\drivers\\TosBTFilter.sys");

TCHAR ToAppendDriverPath[] = _T(TOS_BTFILTER_SYSTEM_PATH);
if (ARRAY_SIZE(ToAppendDriverPath) > ARRAY_SIZE(SystemFilePath) - (LastSystemSlash - SystemFilePath))
{
//LOGMESSAGE(L"Array size exceeded \r\n");
return TOS_FILTER_FILE_NOT_FOUND;
}

memcpy(LastSystemSlash, ToAppendDriverPath, sizeof(ToAppendDriverPath));
}
}

PVOID OldValue = NULL;
int osVersion = Is64BitProcess();

if (osVersion == TOS_FIND_FILTER_GENERIC_ERROR)
{
return TOS_FIND_FILTER_GENERIC_ERROR;
}

if (osVersion == TOS_NOT_64_BIT_OS)
{
int ret = PathFileExists(SystemFilePath);
if (ret)
return TOS_FILTER_FILE_FOUND;
else
return TOS_FILTER_FILE_NOT_FOUND;
}
else if (Wow64DisableWow64FsRedirection(&OldValue))
{
int ret = 0;
ret = PathFileExists(SystemFilePath);

if (FALSE == Wow64RevertWow64FsRedirection(OldValue))
{
//LOGMESSAGE(L"Wow64RevertWow64FsRedirection failed \r\n");
// Failure to re-enable redirection should be considered
// a criticial failure and execution aborted.
return TOS_FIND_FILTER_GENERIC_ERROR;
}

if (ret)
return TOS_FILTER_FILE_FOUND;
else
return TOS_FILTER_FILE_NOT_FOUND;
}
else {
return TOS_FIND_FILTER_GENERIC_ERROR;
}
}

int Is64BitProcess()
{
LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;

BOOL bIsWow64 = FALSE;

//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
GetModuleHandle(TEXT("kernel32")), "IsWow64Process");

if (NULL != fnIsWow64Process)
{
if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
{
return TOS_FIND_FILTER_GENERIC_ERROR;
}
}

if (bIsWow64) {
return TOS_64_BIT_OS;
}
else {
return TOS_NOT_64_BIT_OS;
}
}


int uninstallFilter()
{
BOOLEAN upperFilter = TRUE;
LPTSTR filterToRemove = L"Devupper";
if (FALSE == AdjustProcessPrivileges())
{
return TOS_ADJUST_PRIVILEGES_FAILES;
}
if (!RemoveFilterDriver(devInfoGlobal,
&devInfoDataGlobal,
filterToRemove,
upperFilter)) {

LOGMESSAGE(("uninstallFilter: Unable to remove filter!\n"));
return TOS_ADD_FILTER_DELETE_SRV_FAILED;

}

else {
isFilterDriverUnInstallSuccess = TRUE;
if (FALSE == AdjustProcessPrivileges())
{
return TOS_ADJUST_PRIVILEGES_FAILES;
}
if (!DeleteFilterService(filterToRemove)) {
LOGMESSAGE(("uninstallFilter: TOS_ADD_FILTER_DELETE_SRV_FAILED !!! \r\n"));
//return TOS_ADD_FILTER_DELETE_SRV_FAILED;
}

//system("BTRestart.exe");

if (createServiceFail == TRUE) {
LOGMESSAGE(("uninstallFilter: Failed to uninstall driver\n"));
return TOS_ADD_FILTER_SRV_FAIL_HANDLED;
}
}

return TOS_ADD_FILTER_DELETE_SRV_SUCCESS;
}


int installFilter()
{
LPTSTR filterToAdd = TOS_BTFILTER_NAME;
BOOLEAN createService = TRUE;
//int ret;

if (!AddFilterDriver(devInfoGlobal,
&devInfoDataGlobal,
filterToAdd,
0))
{
isFilterDriverInstallSuccess = FALSE;
LOGMESSAGE(("installFilter: Unable to add filter!\n"));
return TOS_ADD_FILTER_SRV_FAIL_HANDLED;
}
else
{
int ret = FilterCopyFile(createService);

if (CreateServicepassed == TOS_SERVICE_MARKED_FOR_DELETION)
{
return TOS_SERVICE_MARKED_FOR_DELETION;
}

if (ret == TOS_ADD_FILTER_CREATE_SRV_SUCCESS)
{
isFilterDriverInstallSuccess = TRUE;
if (FALSE == AdjustProcessPrivileges())
{
return TOS_ADJUST_PRIVILEGES_FAILES;
}
//Sleep(100);

system("BTRestart.exe");

if (CreateServicepassed == 0)
{
LOGMESSAGE(("installFilter: Failed to installl driver\n"));
return TOS_ADD_FILTER_SRV_FAIL_HANDLED;
}

return TOS_ADD_FILTER_CREATE_SRV_SUCCESS;
}
}

return TOS_ADD_FILTER_CREATE_SRV_SUCCESS;
}

最后贴一下运行效果。开始时,为toaster驱动安装totasterf.inf使得设备栈上有上下设备过滤驱动和类过滤驱动:

安装驱动程序(2)----安装过滤驱动_#pragma_05

下面是设备管理器和注册表中toaster的信息:

安装驱动程序(2)----安装过滤驱动_#include_06

安装驱动程序(2)----安装过滤驱动_#include_07

运行程序addfilter /removefilter后,设备管理器和注册表中toaster的内容变为:

安装驱动程序(2)----安装过滤驱动_#include_08

最后附上完整工程​​链接​​