1114 lines
35 KiB
C
1114 lines
35 KiB
C
#include <precomp.h>
|
|
#include "tracing.h"
|
|
#include "utils.h"
|
|
#include "intflist.h"
|
|
#include "deviceio.h"
|
|
#include "intfhdl.h"
|
|
|
|
//------------------------------------------------------
|
|
// Open a handle to Ndisuio and returns it to the caller
|
|
DWORD
|
|
DevioGetNdisuioHandle (
|
|
PHANDLE pHandle) // OUT opened handle to Ndisuio
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
HANDLE hHandle;
|
|
DWORD dwOutSize;
|
|
|
|
DbgAssert((pHandle != NULL, "NULL pointer to output handle?"));
|
|
|
|
hHandle = CreateFileA(
|
|
"\\\\.\\\\Ndisuio",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
if (hHandle == INVALID_HANDLE_VALUE)
|
|
{
|
|
dwErr = GetLastError();
|
|
DbgPrint((TRC_ERR,"Err: Open Ndisuio->%d", dwErr));
|
|
goto exit;
|
|
}
|
|
|
|
// make sure NDISUIO binds to all relevant interfaces
|
|
if (!DeviceIoControl(
|
|
hHandle,
|
|
IOCTL_NDISUIO_BIND_WAIT,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
&dwOutSize,
|
|
NULL))
|
|
{
|
|
dwErr = GetLastError();
|
|
DbgPrint((TRC_ERR,"Err: IOCTL_NDISUIO_BIND_WAIT->%d", dwErr));
|
|
goto exit;
|
|
}
|
|
|
|
*pHandle = hHandle;
|
|
|
|
exit:
|
|
return dwErr;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// Checks the NDISUIO_QUERY_BINDING object for consistency
|
|
// against the length for this binding as returned by NDISUIO.
|
|
DWORD
|
|
DevioCheckNdisBinding(
|
|
PNDISUIO_QUERY_BINDING pndBinding,
|
|
ULONG nBindingLen)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
// check for the data to contain at least the NDISUIO_QUERY_BINDING
|
|
// header (that is offsets & lengths fields should be there)
|
|
if (nBindingLen < sizeof(NDISUIO_QUERY_BINDING))
|
|
dwErr = ERROR_INVALID_DATA;
|
|
|
|
// check the offsets are correctly set over the NDISUIO_QUERY_BINDING header
|
|
// and within the length indicated by nBindingLen
|
|
if (dwErr == ERROR_SUCCESS &&
|
|
((pndBinding->DeviceNameOffset < sizeof(NDISUIO_QUERY_BINDING)) ||
|
|
(pndBinding->DeviceNameOffset > nBindingLen) ||
|
|
(pndBinding->DeviceDescrOffset < sizeof(NDISUIO_QUERY_BINDING)) ||
|
|
(pndBinding->DeviceDescrOffset > nBindingLen)
|
|
)
|
|
)
|
|
dwErr = ERROR_INVALID_DATA;
|
|
|
|
// check whether the lengths are correctly set within the limits
|
|
if (dwErr == ERROR_SUCCESS &&
|
|
((pndBinding->DeviceNameLength > nBindingLen - pndBinding->DeviceNameOffset) ||
|
|
(pndBinding->DeviceDescrLength > nBindingLen - pndBinding->DeviceDescrOffset)
|
|
)
|
|
)
|
|
dwErr = ERROR_INVALID_DATA;
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// Get the NDISUIO_QUERY_BINDING for the interface index nIntfIndex.
|
|
// If hNdisuio is valid, this handle is used, otherwise a local handle
|
|
// is opened, used and closed before returning.
|
|
DWORD
|
|
DevioGetIntfBindingByIndex(
|
|
HANDLE hNdisuio, // IN opened handle to NDISUIO. If INVALID_HANDLE_VALUE, open one locally
|
|
UINT nIntfIndex, // IN interface index to look for
|
|
PRAW_DATA prdOutput) // OUT result of the IOCTL
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
BOOL bLocalHandle = FALSE;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioGetIntfBindingByIndex(%d..)", nIntfIndex));
|
|
|
|
// assert what are the expected valid parameters
|
|
DbgAssert((prdOutput != NULL &&
|
|
prdOutput->dwDataLen > sizeof(NDISUIO_QUERY_BINDING),
|
|
"Invalid input parameters"));
|
|
|
|
// see if Ndisuio should be opened locally
|
|
if (hNdisuio == INVALID_HANDLE_VALUE)
|
|
{
|
|
dwErr = DevioGetNdisuioHandle(&hNdisuio);
|
|
bLocalHandle = (dwErr == ERROR_SUCCESS);
|
|
}
|
|
|
|
// if everything went well, go query the driver for the Binding structure
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
PNDISUIO_QUERY_BINDING pndBinding;
|
|
DWORD dwOutSize;
|
|
|
|
ZeroMemory(prdOutput->pData, prdOutput->dwDataLen);
|
|
pndBinding = (PNDISUIO_QUERY_BINDING)prdOutput->pData;
|
|
pndBinding->BindingIndex = nIntfIndex;
|
|
if (!DeviceIoControl(
|
|
hNdisuio,
|
|
IOCTL_NDISUIO_QUERY_BINDING,
|
|
prdOutput->pData,
|
|
prdOutput->dwDataLen,
|
|
prdOutput->pData,
|
|
prdOutput->dwDataLen,
|
|
&dwOutSize,
|
|
NULL))
|
|
{
|
|
// if the index is over the number of interfaces
|
|
// we'll have here ERROR_NO_MORE_ITEMS which will be carried out
|
|
// to the caller
|
|
dwErr = GetLastError();
|
|
DbgPrint((TRC_ERR,"Err: IOCTL_NDISUIO_QUERY_BINDING->%d", dwErr));
|
|
}
|
|
else
|
|
{
|
|
dwErr = DevioCheckNdisBinding(pndBinding, dwOutSize);
|
|
}
|
|
}
|
|
|
|
// close the handle if it was opened locally
|
|
if (bLocalHandle)
|
|
CloseHandle(hNdisuio);
|
|
|
|
DbgPrint((TRC_TRACK,"DevioGetIntfBindingByIndex]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// Get the NDISUIO_QUERY_BINDING for the interface having
|
|
// the GUID wszGuid. If hNdisuio is INVALID_HANDLE_VALUE
|
|
// a local handle is opened, used and closed at the end
|
|
DWORD
|
|
DevioGetInterfaceBindingByGuid(
|
|
HANDLE hNdisuio, // IN opened handle to NDISUIO
|
|
LPWSTR wszGuid, // IN interface GUID as "{guid}"
|
|
PRAW_DATA prdOutput) // OUT result of the IOCTL
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
BOOL bLocalHandle = FALSE;
|
|
INT i;
|
|
|
|
// assert what are the expected valid parameters
|
|
DbgAssert((wszGuid != NULL &&
|
|
prdOutput != NULL &&
|
|
prdOutput->dwDataLen > sizeof(NDISUIO_QUERY_BINDING),
|
|
"Invalid input parameter"));
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioGetInterfaceBindingByGuid(%S..)", wszGuid));
|
|
|
|
// see if Ndisuio should be opened locally
|
|
if (hNdisuio == INVALID_HANDLE_VALUE)
|
|
{
|
|
dwErr = DevioGetNdisuioHandle(&hNdisuio);
|
|
bLocalHandle = (dwErr == ERROR_SUCCESS);
|
|
}
|
|
|
|
// iterate through all the interfaces, one by one!! No other better way to do this
|
|
for (i = 0; dwErr == ERROR_SUCCESS; i++)
|
|
{
|
|
PNDISUIO_QUERY_BINDING pndBinding;
|
|
DWORD dwOutSize;
|
|
LPWSTR wsName;
|
|
|
|
ZeroMemory(prdOutput->pData, prdOutput->dwDataLen);
|
|
pndBinding = (PNDISUIO_QUERY_BINDING)prdOutput->pData;
|
|
pndBinding->BindingIndex = i;
|
|
if (!DeviceIoControl(
|
|
hNdisuio,
|
|
IOCTL_NDISUIO_QUERY_BINDING,
|
|
prdOutput->pData,
|
|
prdOutput->dwDataLen,
|
|
prdOutput->pData,
|
|
prdOutput->dwDataLen,
|
|
&dwOutSize,
|
|
NULL))
|
|
{
|
|
// if the IOCTL failed, get the error code
|
|
dwErr = GetLastError();
|
|
// translate the NO_MORE_ITEMS error in FILE_NOT_FOUND
|
|
// since the caller is not iterating, is searching for a specific adapter
|
|
if (dwErr == ERROR_NO_MORE_ITEMS)
|
|
dwErr = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
else
|
|
{
|
|
dwErr = DevioCheckNdisBinding(pndBinding, dwOutSize);
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
// Device name is "\DEVICE\{guid}" and is L'\0' terminated
|
|
// wszGuid is "{guid}"
|
|
wsName = (LPWSTR)((LPBYTE)pndBinding + pndBinding->DeviceNameOffset);
|
|
// if the GUID matches, this is the adapter we were looking for
|
|
if (wcsstr(wsName, wszGuid) != NULL)
|
|
{
|
|
// the adapter's BINDING record is already filled in
|
|
// prdOutput - so just get out of here.
|
|
dwErr = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if handle was opened locally, close it here
|
|
if (bLocalHandle)
|
|
CloseHandle(hNdisuio);
|
|
|
|
DbgPrint((TRC_TRACK,"DevioGetInterfaceBindingByGuid]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioGetIntfStats(PINTF_CONTEXT pIntf)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR ndisDeviceString[128];
|
|
NIC_STATISTICS ndisStats;
|
|
UNICODE_STRING uniIntfGuid;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioGetIntfStats(0x%p)", pIntf));
|
|
|
|
wcscpy(ndisDeviceString, L"\\DEVICE\\");
|
|
wcscat(ndisDeviceString, pIntf->wszGuid);
|
|
RtlInitUnicodeString(&uniIntfGuid, ndisDeviceString);
|
|
ZeroMemory(&ndisStats, sizeof(NIC_STATISTICS));
|
|
ndisStats.Size = sizeof(NIC_STATISTICS);
|
|
|
|
if (!NdisQueryStatistics(&uniIntfGuid, &ndisStats))
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
pIntf->ulMediaState = ndisStats.MediaState;
|
|
pIntf->ulMediaType = ndisStats.MediaType;
|
|
pIntf->ulPhysicalMediaType = ndisStats.PhysicalMediaType;
|
|
}
|
|
|
|
DbgPrint((TRC_TRACK,"DevioGetIntfStats]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioGetIntfMac(PINTF_CONTEXT pIntf)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
RAW_DATA rdBuffer = {0, NULL};
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioGetIntfMac(0x%p)", pIntf));
|
|
|
|
dwErr = DevioRefreshIntfOIDs(
|
|
pIntf,
|
|
INTF_HANDLE,
|
|
NULL);
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
dwErr = DevioQueryBinaryOID(
|
|
pIntf->hIntf,
|
|
OID_802_3_CURRENT_ADDRESS,
|
|
&rdBuffer,
|
|
sizeof(NDIS_802_11_MAC_ADDRESS));
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
if (rdBuffer.dwDataLen == sizeof(NDIS_802_11_MAC_ADDRESS))
|
|
{
|
|
memcpy(&(pIntf->ndLocalMac), rdBuffer.pData, sizeof(NDIS_802_11_MAC_ADDRESS));
|
|
}
|
|
else
|
|
{
|
|
dwErr = ERROR_INVALID_DATA;
|
|
}
|
|
|
|
MemFree(rdBuffer.pData);
|
|
}
|
|
|
|
DbgPrint((TRC_TRACK,"DevioGetIntfMac]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------
|
|
// Notify dependent components the wireless configuration has failed.
|
|
// Specifically this notification goes to TCP allowing TCP to generate
|
|
// the NetReady notification asap (instead of waiting for an IP address
|
|
// to be plumbed down, which might never happen anyhow).
|
|
DWORD
|
|
DevioNotifyFailure(
|
|
LPWSTR wszIntfGuid)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR ndisDeviceString[128];
|
|
UNICODE_STRING UpperComponent;
|
|
UNICODE_STRING LowerComponent;
|
|
UNICODE_STRING BindList;
|
|
struct
|
|
{
|
|
IP_PNP_RECONFIG_REQUEST Reconfig;
|
|
IP_PNP_INIT_COMPLETE InitComplete;
|
|
} Request;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioNotifyFailure(%S)", wszIntfGuid));
|
|
|
|
wcscpy(ndisDeviceString, L"\\DEVICE\\");
|
|
wcscat(ndisDeviceString, wszIntfGuid);
|
|
RtlInitUnicodeString(&UpperComponent, L"Tcpip");
|
|
RtlInitUnicodeString(&LowerComponent, ndisDeviceString);
|
|
RtlInitUnicodeString(&BindList, NULL);
|
|
|
|
ZeroMemory(&Request, sizeof(Request));
|
|
Request.Reconfig.version = IP_PNP_RECONFIG_VERSION;
|
|
Request.Reconfig.NextEntryOffset = (USHORT)((PUCHAR)&Request.InitComplete - (PUCHAR)&Request.Reconfig);
|
|
Request.InitComplete.Header.EntryType = IPPnPInitCompleteEntryType;
|
|
|
|
dwErr = NdisHandlePnPEvent(
|
|
NDIS,
|
|
RECONFIGURE,
|
|
&LowerComponent,
|
|
&UpperComponent,
|
|
&BindList,
|
|
&Request,
|
|
sizeof(Request));
|
|
|
|
DbgPrint((TRC_TRACK,"DevioNotifyFailure]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioOpenIntfHandle(LPWSTR wszIntfGuid, PHANDLE phIntf)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR ndisDeviceString[128];
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioOpenIntfHandle(%S)", wszIntfGuid));
|
|
DbgAssert((phIntf!=NULL, "Invalid out param in DevioOpenIntfHandle"));
|
|
|
|
wcscpy(ndisDeviceString, L"\\DEVICE\\");
|
|
wcscat(ndisDeviceString, wszIntfGuid);
|
|
|
|
dwErr = OpenIntfHandle(ndisDeviceString, phIntf);
|
|
|
|
DbgPrint((TRC_TRACK,"DevioOpenIntfHandle]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioCloseIntfHandle(PINTF_CONTEXT pIntf)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioCloseIntfHandle(0x%p)", pIntf));
|
|
|
|
// destroy the handle only if we did have one in the first instance. Otherwise
|
|
// based only on the GUID we might mess the ref counter on a handle opened by
|
|
// some other app (i.e. 802.1x)
|
|
if (pIntf != NULL && pIntf->hIntf != INVALID_HANDLE_VALUE)
|
|
{
|
|
WCHAR ndisDeviceString[128];
|
|
|
|
wcscpy(ndisDeviceString, L"\\DEVICE\\");
|
|
wcscat(ndisDeviceString, pIntf->wszGuid);
|
|
|
|
dwErr = CloseIntfHandle(ndisDeviceString);
|
|
pIntf->hIntf = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
DbgPrint((TRC_TRACK,"DevioCloseIntfHandle]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioSetIntfOIDs(
|
|
PINTF_CONTEXT pIntfContext,
|
|
PINTF_ENTRY pIntfEntry,
|
|
DWORD dwInFlags,
|
|
PDWORD pdwOutFlags)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
DWORD dwLErr = ERROR_SUCCESS;
|
|
DWORD dwOutFlags = 0;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioSetIntfOIDs(0x%p, 0x%p)", pIntfContext, pIntfEntry));
|
|
|
|
if (pIntfContext == NULL || pIntfEntry == NULL)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
// Set the Infrastructure Mode, if requested
|
|
if (dwInFlags & INTF_INFRAMODE)
|
|
{
|
|
dwLErr = DevioSetEnumOID(
|
|
pIntfContext->hIntf,
|
|
OID_802_11_INFRASTRUCTURE_MODE,
|
|
pIntfEntry->nInfraMode);
|
|
if (dwLErr != ERROR_SUCCESS)
|
|
{
|
|
// set the mode in the client's structure to what it
|
|
// is currently set in the driver
|
|
pIntfEntry->nInfraMode = pIntfContext->wzcCurrent.InfrastructureMode;
|
|
}
|
|
else
|
|
{
|
|
pIntfContext->wzcCurrent.InfrastructureMode = pIntfEntry->nInfraMode;
|
|
dwOutFlags |= INTF_INFRAMODE;
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
// Set the Authentication mode if requested
|
|
if (dwInFlags & INTF_AUTHMODE)
|
|
{
|
|
dwLErr = DevioSetEnumOID(
|
|
pIntfContext->hIntf,
|
|
OID_802_11_AUTHENTICATION_MODE,
|
|
pIntfEntry->nAuthMode);
|
|
if (dwLErr != ERROR_SUCCESS)
|
|
{
|
|
// set the mode in the client's structure to what it
|
|
// is currently set in the driver
|
|
pIntfEntry->nAuthMode = pIntfContext->wzcCurrent.AuthenticationMode;
|
|
}
|
|
else
|
|
{
|
|
pIntfContext->wzcCurrent.AuthenticationMode = pIntfEntry->nAuthMode;
|
|
dwOutFlags |= INTF_AUTHMODE;
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
// Ask the driver to reload the default WEP key if requested
|
|
if (dwInFlags & INTF_LDDEFWKEY)
|
|
{
|
|
dwLErr = DevioSetEnumOID(
|
|
pIntfContext->hIntf,
|
|
OID_802_11_RELOAD_DEFAULTS,
|
|
(DWORD)Ndis802_11ReloadWEPKeys);
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_LDDEFWKEY;
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
// Add the WEP key if requested
|
|
if (dwInFlags & INTF_ADDWEPKEY)
|
|
{
|
|
// the call below takes care of the case rdCtrlData is bogus
|
|
dwLErr = DevioSetBinaryOID(
|
|
pIntfContext->hIntf,
|
|
OID_802_11_ADD_WEP,
|
|
&pIntfEntry->rdCtrlData);
|
|
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_ADDWEPKEY;
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
// Remove the WEP key if requested
|
|
if (dwInFlags & INTF_REMWEPKEY)
|
|
{
|
|
if (pIntfEntry->rdCtrlData.dwDataLen >= sizeof(NDIS_802_11_WEP) &&
|
|
pIntfEntry->rdCtrlData.pData != NULL)
|
|
{
|
|
PNDIS_802_11_WEP pndWepKey = (PNDIS_802_11_WEP)pIntfEntry->rdCtrlData.pData;
|
|
|
|
dwLErr = DevioSetEnumOID(
|
|
pIntfContext->hIntf,
|
|
OID_802_11_REMOVE_WEP,
|
|
pndWepKey->KeyIndex);
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_REMWEPKEY;
|
|
}
|
|
else
|
|
{
|
|
dwLErr = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
// Set the WEP Status if requested
|
|
if (dwInFlags & INTF_WEPSTATUS)
|
|
{
|
|
dwLErr = DevioSetEnumOID(
|
|
pIntfContext->hIntf,
|
|
OID_802_11_WEP_STATUS,
|
|
pIntfEntry->nWepStatus);
|
|
if (dwLErr != ERROR_SUCCESS)
|
|
{
|
|
// set the mode in the client's structure to what it
|
|
// is currently set in the driver
|
|
pIntfEntry->nWepStatus = pIntfContext->wzcCurrent.Privacy;
|
|
}
|
|
else
|
|
{
|
|
pIntfContext->wzcCurrent.Privacy = pIntfEntry->nWepStatus;
|
|
dwOutFlags |= INTF_WEPSTATUS;
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
// Plumb the new SSID down to the driver. If success, copy this new
|
|
// SSID into the interface's context
|
|
if (dwInFlags & INTF_SSID)
|
|
{
|
|
// ntddndis.h defines NDIS_802_11_SSID with a maximum of
|
|
// 32 UCHARs for the SSID name
|
|
if (pIntfEntry->rdSSID.dwDataLen > 32)
|
|
{
|
|
dwLErr = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
NDIS_802_11_SSID ndSSID = {0};
|
|
RAW_DATA rdBuffer;
|
|
|
|
ndSSID.SsidLength = pIntfEntry->rdSSID.dwDataLen;
|
|
memcpy(&ndSSID.Ssid, pIntfEntry->rdSSID.pData, ndSSID.SsidLength);
|
|
rdBuffer.dwDataLen = sizeof(NDIS_802_11_SSID);
|
|
rdBuffer.pData = (LPBYTE)&ndSSID;
|
|
|
|
dwLErr = DevioSetBinaryOID(
|
|
pIntfContext->hIntf,
|
|
OID_802_11_SSID,
|
|
&rdBuffer);
|
|
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
{
|
|
// copy over the new SSID into the interface's context
|
|
CopyMemory(&pIntfContext->wzcCurrent.Ssid, &ndSSID, sizeof(NDIS_802_11_SSID));
|
|
dwOutFlags |= INTF_SSID;
|
|
// on the same time, if a new SSID has been set, it means we broke whatever association
|
|
// we had before, hence the BSSID field can no longer be correct:
|
|
ZeroMemory(&pIntfContext->wzcCurrent.MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS));
|
|
}
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
// set the new BSSID to the driver. If this succeeds, copy
|
|
// the data that was passed down to the interface's context (allocate
|
|
// space for it if not already allocated).
|
|
if (dwInFlags & INTF_BSSID)
|
|
{
|
|
dwLErr = DevioSetBinaryOID(
|
|
pIntfContext->hIntf,
|
|
OID_802_11_BSSID,
|
|
&pIntfEntry->rdBSSID);
|
|
// if the BSSID is not a MAC address, the call above should fail!
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
{
|
|
DbgAssert((pIntfEntry->rdBSSID.dwDataLen == sizeof(NDIS_802_11_MAC_ADDRESS),
|
|
"Data to be set is %d bytes, which is not a MAC address!",
|
|
pIntfEntry->rdBSSID.dwDataLen));
|
|
|
|
memcpy(&pIntfContext->wzcCurrent.MacAddress, pIntfEntry->rdBSSID.pData, sizeof(NDIS_802_11_MAC_ADDRESS));
|
|
dwOutFlags |= INTF_BSSID;
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
exit:
|
|
if (pdwOutFlags != NULL)
|
|
*pdwOutFlags = dwOutFlags;
|
|
|
|
DbgPrint((TRC_TRACK,"DevioSetIntfOIDs]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioRefreshIntfOIDs(
|
|
PINTF_CONTEXT pIntf,
|
|
DWORD dwInFlags,
|
|
PDWORD pdwOutFlags)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
DWORD dwLErr = ERROR_SUCCESS;
|
|
DWORD dwOutFlags = 0;
|
|
RAW_DATA rdBuffer;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioRefreshIntfOIDs(0x%p)", pIntf));
|
|
|
|
if (pIntf == NULL)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
// if the interface handle is invalid or there is an explicit requested
|
|
// to reopen the interface's handle do it as the first thing
|
|
if (pIntf->hIntf == INVALID_HANDLE_VALUE || dwInFlags & INTF_HANDLE)
|
|
{
|
|
if (pIntf->hIntf != INVALID_HANDLE_VALUE)
|
|
{
|
|
dwErr = DevioCloseIntfHandle(pIntf);
|
|
DbgAssert((dwErr == ERROR_SUCCESS,
|
|
"Couldn't close handle for Intf %S",
|
|
pIntf->wszGuid));
|
|
}
|
|
dwErr = DevioOpenIntfHandle(pIntf->wszGuid, &pIntf->hIntf);
|
|
DbgAssert((dwErr == ERROR_SUCCESS,
|
|
"DevioOpenIntfHandle failed for Intf context 0x%p",
|
|
pIntf));
|
|
if (dwErr == ERROR_SUCCESS && (dwInFlags & INTF_HANDLE))
|
|
dwOutFlags |= INTF_HANDLE;
|
|
}
|
|
|
|
// if failed to refresh the interface's handle (this is the only way
|
|
// dwErr could not be success) then we already have a closed handle
|
|
// so there's no point in going further
|
|
if (dwErr != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
// if requested to scan the interface's BSSID list, do it as
|
|
// the next thing. Note however that rescanning is asynchronous.
|
|
// Querying for the BSSID_LIST in the same shot with forcing a rescan
|
|
// might not result in getting the most up to date list.
|
|
if (dwInFlags & INTF_LIST_SCAN)
|
|
{
|
|
// indicate to the driver to rescan the BSSID_LIST for this adapter
|
|
dwLErr = DevioSetEnumOID(
|
|
pIntf->hIntf,
|
|
OID_802_11_BSSID_LIST_SCAN,
|
|
0);
|
|
DbgAssert((dwLErr == ERROR_SUCCESS,
|
|
"DevioSetEnumOID(BSSID_LIST_SCAN) failed for Intf hdl 0x%x",
|
|
pIntf->hIntf));
|
|
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_LIST_SCAN;
|
|
else if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
if (dwInFlags & INTF_AUTHMODE)
|
|
{
|
|
// query the authentication mode for the interface
|
|
dwLErr = DevioQueryEnumOID(
|
|
pIntf->hIntf,
|
|
OID_802_11_AUTHENTICATION_MODE,
|
|
(LPDWORD)&pIntf->wzcCurrent.AuthenticationMode);
|
|
DbgAssert((dwLErr == ERROR_SUCCESS,
|
|
"DevioQueryEnumOID(AUTH_MODE) failed for Intf hdl 0x%x",
|
|
pIntf->hIntf));
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_AUTHMODE;
|
|
else if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
if (dwInFlags & INTF_INFRAMODE)
|
|
{
|
|
// query the infrastructure mode for the interface
|
|
dwLErr = DevioQueryEnumOID(
|
|
pIntf->hIntf,
|
|
OID_802_11_INFRASTRUCTURE_MODE,
|
|
(LPDWORD)&pIntf->wzcCurrent.InfrastructureMode);
|
|
DbgAssert((dwLErr == ERROR_SUCCESS,
|
|
"DevioQueryEnumOID(INFRA_MODE) failed for Intf hdl 0x%x",
|
|
pIntf->hIntf));
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_INFRAMODE;
|
|
else if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
if (dwInFlags & INTF_WEPSTATUS)
|
|
{
|
|
// query the WEP_STATUS for the interface
|
|
dwLErr = DevioQueryEnumOID(
|
|
pIntf->hIntf,
|
|
OID_802_11_WEP_STATUS,
|
|
(LPDWORD)&pIntf->wzcCurrent.Privacy);
|
|
DbgAssert((dwLErr == ERROR_SUCCESS,
|
|
"DevioQueryEnumOID(WEP_STATUS) failed for Intf hdl 0x%x",
|
|
pIntf->hIntf));
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_WEPSTATUS;
|
|
else if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
if (dwInFlags & INTF_BSSID)
|
|
{
|
|
// query the BSSID (MAC address) for the interface
|
|
rdBuffer.dwDataLen = 0;
|
|
rdBuffer.pData = NULL;
|
|
dwLErr = DevioQueryBinaryOID(
|
|
pIntf->hIntf,
|
|
OID_802_11_BSSID,
|
|
&rdBuffer,
|
|
6);
|
|
DbgAssert((dwLErr == ERROR_SUCCESS,
|
|
"DevioQueryBinaryOID(BSSID) failed for Intf hdl 0x%x",
|
|
pIntf->hIntf));
|
|
|
|
// if the call above succeeded...
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
{
|
|
DbgAssert((rdBuffer.dwDataLen == 6, "BSSID len %d is not a MAC address len??", rdBuffer.dwDataLen));
|
|
|
|
// ...and returned correctly a MAC address
|
|
if (rdBuffer.dwDataLen == sizeof(NDIS_802_11_MAC_ADDRESS))
|
|
{
|
|
// copy it in the interface's context
|
|
memcpy(&pIntf->wzcCurrent.MacAddress, rdBuffer.pData, rdBuffer.dwDataLen);
|
|
}
|
|
else
|
|
{
|
|
ZeroMemory(&pIntf->wzcCurrent.MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS));
|
|
dwLErr = ERROR_INVALID_DATA;
|
|
}
|
|
}
|
|
|
|
// free whatever might have had been allocated in DevioQueryBinaryOID
|
|
MemFree(rdBuffer.pData);
|
|
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_BSSID;
|
|
else if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
if (dwInFlags & INTF_SSID)
|
|
{
|
|
PNDIS_802_11_SSID pndSSID;
|
|
// query the SSID for the interface
|
|
rdBuffer.dwDataLen = 0;
|
|
rdBuffer.pData = NULL;
|
|
dwLErr = DevioQueryBinaryOID(
|
|
pIntf->hIntf,
|
|
OID_802_11_SSID,
|
|
&rdBuffer,
|
|
sizeof(NDIS_802_11_SSID));
|
|
DbgAssert((dwLErr == ERROR_SUCCESS,
|
|
"DevioQueryBinaryOID(SSID) failed for Intf hdl 0x%x",
|
|
pIntf->hIntf));
|
|
// if we succeeded up to here then we can't fail further for this OID
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
dwOutFlags |= INTF_SSID;
|
|
else if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
|
|
// copy the pointer to the buffer that was allocated in Query call
|
|
pndSSID = (PNDIS_802_11_SSID)rdBuffer.pData;
|
|
|
|
if (pndSSID != NULL)
|
|
{
|
|
// HACK - if the driver doesn't return the NDIS_802_11_SSID structure but just
|
|
// the SSID itself, correct this!
|
|
if (pndSSID->SsidLength > 32)
|
|
{
|
|
DbgAssert((FALSE,"Driver returns SSID instead of NDIS_802_11_SSID structure"));
|
|
// we have enough space in the buffer to slide the data up (it was shifted down
|
|
// in DevioQueryBinaryOID.
|
|
MoveMemory(pndSSID->Ssid, pndSSID, rdBuffer.dwDataLen);
|
|
pndSSID->SsidLength = rdBuffer.dwDataLen;
|
|
}
|
|
// copy over the current SSID into the interface's context if there was no error
|
|
CopyMemory(&pIntf->wzcCurrent.Ssid, pndSSID, sizeof(NDIS_802_11_SSID));
|
|
}
|
|
|
|
// free whatever might have been allocated in DevioQueryBinaryOID
|
|
MemFree(pndSSID);
|
|
}
|
|
|
|
if (dwInFlags & INTF_BSSIDLIST)
|
|
{
|
|
rdBuffer.dwDataLen = 0;
|
|
rdBuffer.pData = NULL;
|
|
// estimate a buffer large enough for 20 SSIDs.
|
|
dwLErr = DevioQueryBinaryOID(
|
|
pIntf->hIntf,
|
|
OID_802_11_BSSID_LIST,
|
|
&rdBuffer,
|
|
sizeof(NDIS_802_11_BSSID_LIST) + 19*sizeof(NDIS_WLAN_BSSID));
|
|
DbgAssert((dwLErr == ERROR_SUCCESS,
|
|
"DevioQueryBinaryOID(BSSID_LIST) failed for Intf hdl 0x%x",
|
|
pIntf->hIntf));
|
|
// if we succeeded getting the visible list we should have a valid
|
|
// rdBuffer.pData, even if it shows '0 entries'
|
|
if (dwLErr == ERROR_SUCCESS)
|
|
{
|
|
PWZC_802_11_CONFIG_LIST pNewVList;
|
|
|
|
pNewVList = WzcNdisToWzc((PNDIS_802_11_BSSID_LIST)rdBuffer.pData);
|
|
if (rdBuffer.pData == NULL || pNewVList != NULL)
|
|
{
|
|
// cleanup whatever we might have had before
|
|
MemFree(pIntf->pwzcVList);
|
|
// copy the new visible list we got
|
|
pIntf->pwzcVList = pNewVList;
|
|
dwOutFlags |= INTF_BSSIDLIST;
|
|
}
|
|
else
|
|
dwLErr = GetLastError();
|
|
|
|
// whatever the outcome is, free the buffer returned from the driver
|
|
MemFree(rdBuffer.pData);
|
|
}
|
|
// if any error happened here, save it unless some other error has already
|
|
// been saved
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
exit:
|
|
if (pdwOutFlags != NULL)
|
|
*pdwOutFlags = dwOutFlags;
|
|
|
|
DbgPrint((TRC_TRACK,"DevioRefreshIntfOIDs]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioQueryEnumOID(
|
|
HANDLE hIntf,
|
|
NDIS_OID Oid,
|
|
DWORD *pdwEnumValue)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
NDISUIO_QUERY_OID QueryOid;
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioQueryEnumOID(0x%x, 0x%x)", hIntf, Oid));
|
|
DbgAssert((pdwEnumValue != NULL, "Invalid out param in DevioQueryEnumOID"));
|
|
|
|
if (hIntf == INVALID_HANDLE_VALUE || pdwEnumValue == NULL)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
// the NDISUIO_QUERY_OID includes data for 1 dword, sufficient for getting
|
|
// an enumerative value from the driver. This spares us of an additional
|
|
// allocation.
|
|
ZeroMemory(&QueryOid, sizeof(NDISUIO_QUERY_OID));
|
|
QueryOid.Oid = Oid;
|
|
if (!DeviceIoControl (
|
|
hIntf,
|
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
|
(LPVOID)&QueryOid,
|
|
sizeof(NDISUIO_QUERY_OID),
|
|
(LPVOID)&QueryOid,
|
|
sizeof(NDISUIO_QUERY_OID),
|
|
&dwBytesReturned,
|
|
NULL)) // no overlapping routine
|
|
{
|
|
dwErr = GetLastError();
|
|
DbgPrint((TRC_ERR, "Err: IOCTL_NDISUIO_QUERY_OID_VALUE->%d", dwErr));
|
|
goto exit;
|
|
}
|
|
//dwErr = GetLastError();
|
|
//DbgAssert((dwErr == ERROR_SUCCESS, "DeviceIoControl suceeded, but GetLastError() is =0x%x", dwErr));
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
*pdwEnumValue = *(LPDWORD)QueryOid.Data;
|
|
|
|
exit:
|
|
DbgPrint((TRC_TRACK,"DevioQueryEnumOID]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioSetEnumOID(
|
|
HANDLE hIntf,
|
|
NDIS_OID Oid,
|
|
DWORD dwEnumValue)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
NDISUIO_SET_OID SetOid;
|
|
DWORD dwBytesReturned = 0;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioSetEnumOID(0x%x, 0x%x, %d)", hIntf, Oid, dwEnumValue));
|
|
|
|
if (hIntf == INVALID_HANDLE_VALUE)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
// the NDISUIO_SET_OID includes data for 1 dword, sufficient for setting
|
|
// an enumerative value from the driver. This spares us of an additional
|
|
// allocation.
|
|
SetOid.Oid = Oid;
|
|
*(LPDWORD)SetOid.Data = dwEnumValue;
|
|
if (!DeviceIoControl (
|
|
hIntf,
|
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
|
(LPVOID)&SetOid,
|
|
sizeof(NDISUIO_SET_OID),
|
|
NULL,
|
|
0,
|
|
&dwBytesReturned,
|
|
NULL)) // no overlapping routine
|
|
{
|
|
dwErr = GetLastError();
|
|
DbgPrint((TRC_ERR, "Err: IOCTL_NDISUIO_SET_OID_VALUE->%d", dwErr));
|
|
goto exit;
|
|
}
|
|
//dwErr = GetLastError();
|
|
//DbgAssert((dwErr == ERROR_SUCCESS, "DeviceIoControl suceeded, but GetLastError() is =0x%x", dwErr));
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
exit:
|
|
DbgPrint((TRC_TRACK,"DevioSetEnumOID]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
#define DATA_MEM_MIN 32 // the minimum mem block to be sent out to the ioctl
|
|
#define DATA_MEM_MAX 65536 // the maximum mem block that will be sent out to the ioctl (64K)
|
|
#define DATA_MEM_INC 512 // increment the existent block in 512 bytes increment
|
|
DWORD
|
|
DevioQueryBinaryOID(
|
|
HANDLE hIntf,
|
|
NDIS_OID Oid,
|
|
PRAW_DATA pRawData, // buffer is internally allocated
|
|
DWORD dwMemEstimate) // how much memory is estimated the result needs
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
PNDISUIO_QUERY_OID pQueryOid=NULL;
|
|
|
|
DbgPrint((TRC_TRACK, "[DevioQueryBinaryOID(0x%x, 0x%x)", hIntf, Oid));
|
|
|
|
if (hIntf == INVALID_HANDLE_VALUE ||
|
|
pRawData == NULL)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
if (dwMemEstimate < DATA_MEM_MIN)
|
|
dwMemEstimate = DATA_MEM_MIN;
|
|
do
|
|
{
|
|
DWORD dwBuffSize;
|
|
DWORD dwBytesReturned;
|
|
|
|
MemFree(pQueryOid);
|
|
|
|
if (dwMemEstimate > DATA_MEM_MAX)
|
|
dwMemEstimate = DATA_MEM_MAX;
|
|
dwBuffSize = FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + dwMemEstimate;
|
|
pQueryOid = (PNDISUIO_QUERY_OID) MemCAlloc(dwBuffSize);
|
|
if (pQueryOid == NULL)
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
pQueryOid->Oid = Oid;
|
|
if (DeviceIoControl (
|
|
hIntf,
|
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
|
(LPVOID)pQueryOid,
|
|
dwBuffSize,
|
|
(LPVOID)pQueryOid,
|
|
dwBuffSize,
|
|
&dwBytesReturned,
|
|
NULL))
|
|
{
|
|
DbgAssert((
|
|
dwBytesReturned <= dwBuffSize,
|
|
"DeviceIoControl returned %d > %d that was passed down!",
|
|
dwBytesReturned,
|
|
dwBuffSize));
|
|
|
|
pRawData->pData = (LPBYTE)pQueryOid;
|
|
pRawData->dwDataLen = dwBytesReturned - FIELD_OFFSET(NDISUIO_QUERY_OID, Data);
|
|
|
|
if (pRawData->dwDataLen != 0)
|
|
{
|
|
MoveMemory(pQueryOid, pQueryOid->Data, pRawData->dwDataLen);
|
|
}
|
|
else
|
|
{
|
|
pRawData->pData = NULL;
|
|
MemFree(pQueryOid);
|
|
pQueryOid = NULL;
|
|
}
|
|
|
|
dwErr = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
dwErr = GetLastError();
|
|
|
|
if (((dwErr == ERROR_INSUFFICIENT_BUFFER) || (dwErr == ERROR_INVALID_USER_BUFFER)) &&
|
|
(dwMemEstimate < DATA_MEM_MAX))
|
|
{
|
|
dwMemEstimate += DATA_MEM_INC;
|
|
dwErr = ERROR_SUCCESS;
|
|
}
|
|
|
|
} while (dwErr == ERROR_SUCCESS);
|
|
|
|
exit:
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
MemFree(pQueryOid);
|
|
pRawData->pData= NULL;
|
|
pRawData->dwDataLen = 0;
|
|
}
|
|
|
|
DbgPrint((TRC_TRACK, "DevioQueryBinaryOID]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DevioSetBinaryOID(
|
|
HANDLE hIntf,
|
|
NDIS_OID Oid,
|
|
PRAW_DATA pRawData)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
PNDISUIO_SET_OID pSetOid = NULL;
|
|
DWORD dwBytesReturned = 0;
|
|
DWORD dwBufferSize;
|
|
|
|
DbgPrint((TRC_TRACK,"[DevioSetBinaryOID(0x%x,0x%x,...)", hIntf, Oid));
|
|
|
|
if (hIntf == INVALID_HANDLE_VALUE ||
|
|
pRawData == NULL ||
|
|
pRawData->dwDataLen == 0 ||
|
|
pRawData->pData == NULL)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
dwBufferSize = FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + pRawData->dwDataLen;
|
|
pSetOid = (PNDISUIO_SET_OID) MemCAlloc(dwBufferSize);
|
|
if (pSetOid == NULL)
|
|
{
|
|
dwErr = GetLastError();
|
|
goto exit;
|
|
}
|
|
pSetOid->Oid = Oid;
|
|
CopyMemory(pSetOid->Data, pRawData->pData, pRawData->dwDataLen);
|
|
|
|
if (!DeviceIoControl (
|
|
hIntf,
|
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
|
(LPVOID)pSetOid,
|
|
dwBufferSize,
|
|
NULL,
|
|
0,
|
|
&dwBytesReturned,
|
|
NULL)) // no overlapping routine
|
|
{
|
|
dwErr = GetLastError();
|
|
DbgPrint((TRC_ERR, "Err: IOCTL_NDISUIO_SET_OID_VALUE->%d", dwErr));
|
|
goto exit;
|
|
}
|
|
//dwErr = GetLastError();
|
|
//DbgAssert((dwErr == ERROR_SUCCESS, "DeviceIoControl suceeded, but GetLastError() is 0x%x", dwErr));
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
exit:
|
|
MemFree(pSetOid);
|
|
DbgPrint((TRC_TRACK,"DevioSetBinaryOID]=%d", dwErr));
|
|
return dwErr;
|
|
}
|