Powered By Blogger

i have to thank one person (seriously I forgot this name... i am really bad a remembering names and numbers), he posted an article in codeproject.com regarding this functionality. Then I found more helpful code in completing the circle.. :) 
WINCE600\PUBLIC\COMMON\OAK\DRIVERS\NETSAMP\NDISPWR
This is a sample program given in windows ce 6.0 showing how to query and the set the power state of network interface using deviceIocontrols (specifically,  ndis ioctls for binding and unbinding the adapter after a power state change) and setDevicePower functions. 

Here is the code for controlling (enabling and disabling, its the same operation as in enabling and disabling a network interface in network connection applet in control panel) an NIC.

Pay attention to the high lighted part of code.

void ControlNIC(wchar_t* InterfaceName,BOOL bEnable)
{
HANDLE                          hNdisPwr;
NDISPWR_SAVEPOWERSTATE SavePowerState;
TCHAR                           szName[MAX_PATH];
int                             nChars;
TCHAR*                          pszAdapter;
TCHAR                           multiSz[257];
DWORD                           cbBuffer = sizeof(multiSz);

hNdisPwr = CreateFile((PTCHAR)NDISPWR_DEVICE_NAME,
                                                          0x00,0x00,NULL,
                                                         OPEN_EXISTING,
                                                       FILE_ATTRIBUTE_NORMAL
                                                                | FILE_FLAG_OVERLAPPED,
                                                        (HANDLE)INVALID_HANDLE_VALUE);

if (hNdisPwr != INVALID_HANDLE_VALUE)
{
SavePowerState.pwcAdapterName = InterfaceName;
if (bEnable)
{
SavePowerState.CePowerState   = PwrDeviceUnspecified;
}
else
{
SavePowerState.CePowerState   = D4;
}

BOOL ret = DeviceIoControl(hNdisPwr,
                                                    IOCTL_NPW_SAVE_POWER_STATE,
                                                    &SavePowerState,
                                                    sizeof(NDISPWR_SAVEPOWERSTATE),
                                                    NULL,0x00,NULL,NULL);
// TODO: take care of the return value 'ret '

CloseHandle(hNdisPwr);

                // Just composing a Class-Qualified Device Name, to pass on to SetDevicePower
pszAdapter = new TCHAR[wcslen(InterfaceName)+1];
wcscpy_s(pszAdapter,wcslen(InterfaceName)+1,InterfaceName);
nChars = _sntprintf_s(szName,
                                                             MAX_PATH-1,
                                                             MAX_PATH-1,
                                                             _T("%s\\%s"),
                                                           PMCLASS_NDIS_MINIPORT,
                                                           pszAdapter);
szName[MAX_PATH-1]=0;

DWORD res = 0;
if(bEnable)
{
res = SetDevicePower(szName, 
                                                                     POWER_NAME, 
                                                                    PwrDeviceUnspecified);
}
else
{
res = SetDevicePower(szName, 
                                                                      POWER_NAME, 
                                                                      D4);
}

// TODO: take care of the return value 'res'

StringCchCopy(multiSz, (cbBuffer / sizeof(TCHAR))-1, pszAdapter);
multiSz[::_tcslen(multiSz)+1] = _T('\0'); // Multi sz needs an extra null

BOOL bRes;

if (bEnable)
{
bRes = DoNdisIOControl(IOCTL_NDIS_BIND_ADAPTER,
                                                                          multiSz,
                                                                          (_tcslen(multiSz)+2) * sizeof(TCHAR),
                                                                         NULL,NULL);
}
else
{
bRes = DoNdisIOControl(IOCTL_NDIS_UNBIND_ADAPTER,
                                                                            multiSz, 
                                                                           (_tcslen(multiSz)+2) * sizeof(TCHAR), 
                                                                          NULL,NULL);
}
// TODO: take care of the return value 'bRes '
}

}
While changing the power state of a device, be sure for bind and unbind an adapter so that NDIS can take care of the protocol drivers. 

4 comments:

Kültür Mantarı said...

very useful article. thanks .

I'm using Evc++ . When try to compile this method, i get an error like below ;

error C2065: DoNdisIOControl : undeclared identifier

my include class like below;

#include "Atlbase.h"
#include "Winreg.h"

#include "winioctl.h"
#include "ntddndis.h"

#include "windows.h"
#include "tchar.h"
#include "stdio.h"
#include "stdarg.h"
#include "netcon.h"
#include "iphlpapi.h"
#include "pm.h"
#include "winsock.h"
#include "ndispwr.h"
#include "string.h"

have any idea

Vaisakh P S said...

DoNdisIOControl is just a wrapper function i provided to do the ioctl calls... i can send u the fulll source code if u want ;)

Vaisakh P S said...

sorry for the delay in reply dude... been busy in last couple of weeks :)

Vaisakh P S said...

here is the code for DoNdisIOControl

BOOL DoNdisIOControl(DWORD dwCommand, LPVOID pInBuffer,DWORD cbInBuffer, LPVOID pOutBuffer,DWORD * pcbOutBuffer)
{
HANDLE hNdis;
BOOL fResult = FALSE;

hNdis = ::CreateFile(DD_NDIS_DEVICE_NAME, GENERIC_READ |GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS,0, NULL);
if (INVALID_HANDLE_VALUE != hNdis)
{
fResult = ::DeviceIoControl(hNdis, dwCommand, pInBuffer, cbInBuffer,pOutBuffer, (pcbOutBuffer ? *pcbOutBuffer : 0),pcbOutBuffer, NULL);
::CloseHandle(hNdis);
}
return fResult;
}