Friday, May 16, 2008

How to share an event with kernel and user mode applications

Follow the simple steps to do.

1. Create event object in user mode application

****User mode****
HANDLE SharedEvent;
SharedEvent = CreateEvent(NULL, TRUE, FALSE, "SharedEvent");
*****************

2. Open event object in kernel mode application
we use BaseNamedObjects in the event name because when user mode application creates event,
Object managet creates it under BaseNamedObjects namespace.

****Kernel mode****
HANDLE SharedEventHandle = NULL;
PKEVENT SharedEvent = NULL;
RtlInitUnicodeString(&EventName, L"\\BaseNamedObjects\\SharedEvent");
SharedEvent = IoCreateNotificationEvent(&EventName, &SharedEventHandle);
ObReferenceObject(SharedEvent);
*****************

3. Wait on the event in any user or kernel mode application

****User mode****
WaitForSingleObject(SharedEvent, INFINITE);
*****************

4. Signal event from any user or kernel mode application

****Kernel mode****
KeSetEvent(SharedEvent, 0, FALSE);
*****************

5. Close any resources in both user and kernel mode

****User mode****
CloseHandle(SharedEvent);
*****************

****Kernel mode****
ZwClose(SharedEventHandle);
ObDereferenceObject(SharedEvent);
*******************

- vikas

Thursday, May 15, 2008

How to enable or disable the device

Here is the function to enable or disable the device.
You need to use setupapi.

INPUTS
bEnable - True enables the device, false disable it
hDevInfo - Handle to device information set get from SetupDiGetClassDevs or similiar function
spDevInfoData - It is device information data for the device you are enabling

BOOL EnableDevice(BOOL bEnable,HDEVINFO hDevInfo,SP_DEVINFO_DATA& spDevInfoData)
{
SP_PROPCHANGE_PARAMS spPropChangeParams;
SP_DEVINSTALL_PARAMS devParams;

if( bEnable )
{
// Enable both on global and config-specific profile
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
spPropChangeParams.StateChange = DICS_ENABLE;
spPropChangeParams.Scope = DICS_FLAG_GLOBAL;
spPropChangeParams.HwProfile = 0;

// We don't care if this function fails. we will get it at config specific profile
if(SetupDiSetClassInstallParams(hDevInfo,
&spDevInfoData,
&spPropChangeParams.ClassInstallHeader,
sizeof(spPropChangeParams)) )
{
SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,hDevInfo,&spDevInfoData);
}

// Perform enable on config-specific profile
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
spPropChangeParams.StateChange = DICS_ENABLE;
spPropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;
spPropChangeParams.HwProfile = 0;
}
else
{
// Perform disable on config-specific profile
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
spPropChangeParams.StateChange = DICS_DISABLE;
spPropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;
spPropChangeParams.HwProfile = 0;
}

if(!SetupDiSetClassInstallParams(hDevInfo,
&spDevInfoData,
&spPropChangeParams.ClassInstallHeader,
sizeof(spPropChangeParams)) ||
!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,hDevInfo,&spDevInfoData) )
{
// Failed to invoke DIF_PROPERTYCHANGE
}
else
{
// Config specific profile sets reboot flag if it needs reboot.
devParams.cbSize = sizeof(devParams);
if(SetupDiGetDeviceInstallParams(hDevInfo,&spDevInfoData,&devParams) &&
(devParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) )
{
// It needs reboot or restart
}
else
{
// We are done successfully.
return TRUE;
}
}
return FALSE;
}