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

本文介绍了如何安装类过滤驱动及设备过滤驱动,并提供了相应的代码实现。同时,还讲解了如何利用SetupDi接口来添加和移除指定位置上的过滤驱动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    前面 安装驱动程序(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.上面讨论了安装类过滤驱动,现在来讨论第二个问题,往现有设备栈中插入/删除设备过滤驱动。实现思路和前面创建虚拟设备差不多,都是通过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,
                                            &regDataType );*/
	LPTSTR deviceName =
		(LPTSTR)GetDeviceRegistryProperty(DeviceInfoSet,
		DeviceInfoData,
		SPDRP_HARDWAREID,
		&regDataType);
	//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),
                                                        &regDataType );

    // 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,
                                            &regDataType );

    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使得设备栈上有上下设备过滤驱动和类过滤驱动:

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


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


最后附上完整工程链接

Filter Drivers主要包括以下特性:   1) 一个Filter Drivers实例叫Filter Module。Filter Module附加在一个适配器的微端口驱动上, 来自相同或不同Filter Drivers的多个Filter Module都可以被堆叠在一个网络适配器上   2)Filter Module被安装驱动栈时,之上的协议驱动和之下的微端口驱动都不需要提供额外的支持功能   3) 因为Filter Module不像中间层驱动(intermediate driver)那样提供一个虚拟的微口,也不与某个设备对象联结,所以在微端口适配器(miniport adapter)之上的Filter Module 功能相当于一个修过过版本的微端口适配器(miniport adapter)。(原文:Because filter drivers do not implement virtual miniports like an intermediate driverfilter drivers are not associated with a device object. A miniport adapter with overlying filter modules functions as a modified version of the miniport adapter.)   4) NDIS使用配置信息来到决定一个Filter Module附加到一个网络适配器栈上的顺序   5) 在不用拆除整驱动栈的情况下,NDIS可以动态的插入、删除Filter Module或进行重新配置   6) 当NDIS重起驱动栈的时候协议驱动可以获得在栈上的Filter Module列表   7) Filter Drivers可以过滤下层网络适配器上绝大部分的通信。Filter Module不联结某特定的绑定(Filter modules are not associated with any particular binding between overlying protocol drivers and the miniport adapter.)   8) Filter Drivers 可以选择为过滤服务也可以选择为分流的不过滤服务,选择为哪一种是可以动态配置的(Filter drivers can select the services that are filtered and can be bypassed for the services that are not filtered. The selection of the services that are bypassed and the services that are filtered can be reconfigured dynamically.)   9) NDIS 保证有效的上下文空间,也不就是说Filter Drivers不要需要通代码COPY缓冲区来获得上下文空间  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值