mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 07:32:57 +00:00
- Merge the remaining portion of the wlan-bringup branch
- ReactOS now supports open and WEP encrypted networks (both ad-hoc and infrastructure) (WPA(2) will be supported later) - Use the wlanconf tool to configure the WLAN adapter (after installing the XP driver for your WLAN adapter) - "wlanconf -c <SSID>" connects to an infrastructure network. Adding the "-a" option connects to (or creates) an ad-hoc network. Adding "-w <WEP>" will enable WEP encryption using the supplied key. - "wlanconf -s" will scan and display a list of the surrounding networks and various attributes like signal strength, SSID, BSSID, network mode, and supported rates - "wlanconf" will display the current WLAN configuration details if the adapter is connected - The DHCP service will detect network changes and refresh its state accordingly when associating with a new wireless network svn path=/trunk/; revision=55000
This commit is contained in:
commit
cd00d99985
22 changed files with 2961 additions and 3 deletions
|
@ -14,3 +14,5 @@ if(NOT MSVC)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(tracert)
|
add_subdirectory(tracert)
|
||||||
add_subdirectory(whois)
|
add_subdirectory(whois)
|
||||||
|
add_subdirectory(wlanconf)
|
||||||
|
|
||||||
|
|
|
@ -40,4 +40,7 @@
|
||||||
<directory name="whois">
|
<directory name="whois">
|
||||||
<xi:include href="whois/whois.rbuild" />
|
<xi:include href="whois/whois.rbuild" />
|
||||||
</directory>
|
</directory>
|
||||||
|
<directory name="wlanconf">
|
||||||
|
<xi:include href="wlanconf/wlanconf.rbuild" />
|
||||||
|
</directory>
|
||||||
</group>
|
</group>
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
BEFORE include
|
||||||
|
${REACTOS_SOURCE_DIR}/include/reactos/drivers/ndisuio)
|
||||||
|
add_executable(wlanconf wlanconf.c wlanconf.rc)
|
||||||
|
set_module_type(wlanconf win32cui)
|
||||||
|
add_importlibs(wlanconf msvcrt iphlpapi kernel32)
|
||||||
|
add_cd_file(TARGET wlanconf DESTINATION reactos/system32 FOR all)
|
969
reactos/base/applications/network/wlanconf/wlanconf.c
Normal file
969
reactos/base/applications/network/wlanconf/wlanconf.c
Normal file
|
@ -0,0 +1,969 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS WLAN command-line configuration utility
|
||||||
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
|
* FILE: base/applications/network/wlanconf/wlanconf.c
|
||||||
|
* PURPOSE: Allows WLAN configuration via the command prompt
|
||||||
|
* COPYRIGHT: Copyright 2012 Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ntddndis.h>
|
||||||
|
#include <nuiouser.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
|
||||||
|
BOOL bScan = FALSE;
|
||||||
|
|
||||||
|
BOOL bConnect = FALSE;
|
||||||
|
char* sSsid = NULL;
|
||||||
|
char* sWepKey = NULL;
|
||||||
|
BOOL bAdhoc = FALSE;
|
||||||
|
|
||||||
|
BOOL bDisconnect = FALSE;
|
||||||
|
|
||||||
|
DWORD DoFormatMessage(DWORD ErrorCode)
|
||||||
|
{
|
||||||
|
LPVOID lpMsgBuf;
|
||||||
|
DWORD RetVal;
|
||||||
|
|
||||||
|
if ((RetVal = FormatMessage(
|
||||||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||||
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
ErrorCode,
|
||||||
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||||
|
(LPTSTR) &lpMsgBuf,
|
||||||
|
0,
|
||||||
|
NULL )))
|
||||||
|
{
|
||||||
|
_tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
|
||||||
|
|
||||||
|
LocalFree(lpMsgBuf);
|
||||||
|
|
||||||
|
/* return number of TCHAR's stored in output buffer
|
||||||
|
* excluding '\0' - as FormatMessage does*/
|
||||||
|
return RetVal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE
|
||||||
|
OpenDriverHandle(VOID)
|
||||||
|
{
|
||||||
|
HANDLE hDriver;
|
||||||
|
DWORD dwBytesReturned;
|
||||||
|
BOOL bSuccess;
|
||||||
|
|
||||||
|
/* Open a handle to the NDISUIO driver */
|
||||||
|
hDriver = CreateFileW(NDISUIO_DEVICE_NAME,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
NULL);
|
||||||
|
if (hDriver == INVALID_HANDLE_VALUE)
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
/* Wait for binds */
|
||||||
|
bSuccess = DeviceIoControl(hDriver,
|
||||||
|
IOCTL_NDISUIO_BIND_WAIT,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
CloseHandle(hDriver);
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hDriver;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
IsWlanAdapter(HANDLE hAdapter)
|
||||||
|
{
|
||||||
|
BOOL bSuccess;
|
||||||
|
DWORD dwBytesReturned;
|
||||||
|
NDISUIO_QUERY_OID QueryOid;
|
||||||
|
|
||||||
|
/* WLAN drivers must support this OID */
|
||||||
|
QueryOid.Oid = OID_GEN_PHYSICAL_MEDIUM;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
&QueryOid,
|
||||||
|
sizeof(QueryOid),
|
||||||
|
&QueryOid,
|
||||||
|
sizeof(QueryOid),
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess || *(PULONG)QueryOid.Data != NdisPhysicalMediumWirelessLan)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
OpenAdapterHandle(DWORD Index, HANDLE *hAdapter, IP_ADAPTER_INDEX_MAP *IpInfo)
|
||||||
|
{
|
||||||
|
HANDLE hDriver;
|
||||||
|
BOOL bSuccess;
|
||||||
|
DWORD dwBytesReturned;
|
||||||
|
DWORD QueryBindingSize = sizeof(NDISUIO_QUERY_BINDING) + (1024 * sizeof(WCHAR));
|
||||||
|
PNDISUIO_QUERY_BINDING QueryBinding;
|
||||||
|
DWORD dwStatus, dwSize, i;
|
||||||
|
PIP_INTERFACE_INFO InterfaceInfo = NULL;
|
||||||
|
|
||||||
|
/* Open the driver handle */
|
||||||
|
hDriver = OpenDriverHandle();
|
||||||
|
if (hDriver == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Allocate the binding struct */
|
||||||
|
QueryBinding = HeapAlloc(GetProcessHeap(), 0, QueryBindingSize);
|
||||||
|
if (!QueryBinding)
|
||||||
|
{
|
||||||
|
CloseHandle(hDriver);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Query the adapter binding information */
|
||||||
|
QueryBinding->BindingIndex = Index;
|
||||||
|
bSuccess = DeviceIoControl(hDriver,
|
||||||
|
IOCTL_NDISUIO_QUERY_BINDING,
|
||||||
|
QueryBinding,
|
||||||
|
QueryBindingSize,
|
||||||
|
QueryBinding,
|
||||||
|
QueryBindingSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryBinding);
|
||||||
|
CloseHandle(hDriver);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bind to the adapter */
|
||||||
|
bSuccess = DeviceIoControl(hDriver,
|
||||||
|
IOCTL_NDISUIO_OPEN_DEVICE,
|
||||||
|
(PUCHAR)QueryBinding + QueryBinding->DeviceNameOffset,
|
||||||
|
QueryBinding->DeviceNameLength,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryBinding);
|
||||||
|
CloseHandle(hDriver);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get interface info from the IP helper */
|
||||||
|
dwSize = sizeof(IP_INTERFACE_INFO);
|
||||||
|
do {
|
||||||
|
if (InterfaceInfo) HeapFree(GetProcessHeap(), 0, InterfaceInfo);
|
||||||
|
InterfaceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(IP_INTERFACE_INFO));
|
||||||
|
if (!InterfaceInfo)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryBinding);
|
||||||
|
CloseHandle(hDriver);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
dwStatus = GetInterfaceInfo(InterfaceInfo, &dwSize);
|
||||||
|
} while (dwStatus == ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
|
||||||
|
if (dwStatus != NO_ERROR)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryBinding);
|
||||||
|
HeapFree(GetProcessHeap(), 0, InterfaceInfo);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < InterfaceInfo->NumAdapters; i++)
|
||||||
|
{
|
||||||
|
if (wcsstr((PWCHAR)((PUCHAR)QueryBinding + QueryBinding->DeviceNameOffset),
|
||||||
|
InterfaceInfo->Adapter[i].Name))
|
||||||
|
{
|
||||||
|
*IpInfo = InterfaceInfo->Adapter[i];
|
||||||
|
*hAdapter = hDriver;
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryBinding);
|
||||||
|
HeapFree(GetProcessHeap(), 0, InterfaceInfo);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryBinding);
|
||||||
|
HeapFree(GetProcessHeap(), 0, InterfaceInfo);
|
||||||
|
CloseHandle(hDriver);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only works with the first adapter for now */
|
||||||
|
BOOL
|
||||||
|
OpenWlanAdapter(HANDLE *hAdapter, IP_ADAPTER_INDEX_MAP *IpInfo)
|
||||||
|
{
|
||||||
|
DWORD dwCurrentIndex;
|
||||||
|
|
||||||
|
for (dwCurrentIndex = 0; ; dwCurrentIndex++)
|
||||||
|
{
|
||||||
|
if (!OpenAdapterHandle(dwCurrentIndex, hAdapter, IpInfo))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (IsWlanAdapter(*hAdapter))
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
CloseHandle(*hAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WlanDisconnect(HANDLE hAdapter, PIP_ADAPTER_INDEX_MAP IpInfo)
|
||||||
|
{
|
||||||
|
BOOL bSuccess;
|
||||||
|
DWORD dwBytesReturned;
|
||||||
|
NDISUIO_SET_OID SetOid;
|
||||||
|
|
||||||
|
/* Release this IP address */
|
||||||
|
IpReleaseAddress(IpInfo);
|
||||||
|
|
||||||
|
/* Disassociate from the AP */
|
||||||
|
SetOid.Oid = OID_802_11_DISASSOCIATE;
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
||||||
|
&SetOid,
|
||||||
|
sizeof(SetOid),
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
_tprintf(_T("The operation completed successfully.\n"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
UCHAR
|
||||||
|
CharToHex(CHAR Char)
|
||||||
|
{
|
||||||
|
Char = toupper(Char);
|
||||||
|
|
||||||
|
switch (Char)
|
||||||
|
{
|
||||||
|
case '0':
|
||||||
|
return 0x0;
|
||||||
|
case '1':
|
||||||
|
return 0x1;
|
||||||
|
case '2':
|
||||||
|
return 0x2;
|
||||||
|
case '3':
|
||||||
|
return 0x3;
|
||||||
|
case '4':
|
||||||
|
return 0x4;
|
||||||
|
case '5':
|
||||||
|
return 0x5;
|
||||||
|
case '6':
|
||||||
|
return 0x6;
|
||||||
|
case '7':
|
||||||
|
return 0x7;
|
||||||
|
case '8':
|
||||||
|
return 0x8;
|
||||||
|
case '9':
|
||||||
|
return 0x9;
|
||||||
|
case 'A':
|
||||||
|
return 0xA;
|
||||||
|
case 'B':
|
||||||
|
return 0xB;
|
||||||
|
case 'C':
|
||||||
|
return 0xC;
|
||||||
|
case 'D':
|
||||||
|
return 0xD;
|
||||||
|
case 'E':
|
||||||
|
return 0xE;
|
||||||
|
case 'F':
|
||||||
|
return 0xF;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WlanPrintCurrentStatus(HANDLE hAdapter)
|
||||||
|
{
|
||||||
|
PNDISUIO_QUERY_OID QueryOid;
|
||||||
|
DWORD QueryOidSize;
|
||||||
|
BOOL bSuccess;
|
||||||
|
DWORD dwBytesReturned;
|
||||||
|
PNDIS_802_11_SSID SsidInfo;
|
||||||
|
CHAR SsidBuffer[NDIS_802_11_LENGTH_SSID + 1];
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
QueryOidSize = FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + sizeof(NDIS_802_11_SSID);
|
||||||
|
QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize);
|
||||||
|
if (!QueryOid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_SSID;
|
||||||
|
SsidInfo = (PNDIS_802_11_SSID)QueryOid->Data;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the SSID to our internal buffer and terminate it */
|
||||||
|
RtlCopyMemory(SsidBuffer, SsidInfo->Ssid, SsidInfo->SsidLength);
|
||||||
|
SsidBuffer[SsidInfo->SsidLength] = 0;
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
QueryOidSize = FIELD_OFFSET(NDISUIO_QUERY_OID, Data) + sizeof(NDIS_802_11_MAC_ADDRESS);
|
||||||
|
QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize);
|
||||||
|
if (!QueryOid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_BSSID;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (SsidInfo->SsidLength == 0 || !bSuccess)
|
||||||
|
{
|
||||||
|
_tprintf(_T("\nWLAN disconnected\n"));
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tprintf(_T("\nCurrent wireless configuration information:\n\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
_tprintf(_T("SSID: %s\n"), SsidBuffer);
|
||||||
|
|
||||||
|
_tprintf(_T("BSSID: "));
|
||||||
|
for (i = 0; i < sizeof(NDIS_802_11_MAC_ADDRESS); i++)
|
||||||
|
{
|
||||||
|
UINT BssidData = QueryOid->Data[i];
|
||||||
|
|
||||||
|
_tprintf(_T("%.2x"), BssidData);
|
||||||
|
|
||||||
|
if (i != sizeof(NDIS_802_11_MAC_ADDRESS) - 1)
|
||||||
|
_tprintf(_T(":"));
|
||||||
|
}
|
||||||
|
_tprintf(_T("\n"));
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
QueryOidSize = sizeof(NDISUIO_QUERY_OID);
|
||||||
|
QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize);
|
||||||
|
if (!QueryOid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_INFRASTRUCTURE_MODE;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tprintf(_T("Network mode: %s\n"), (*(PUINT)QueryOid->Data == Ndis802_11IBSS) ? "Adhoc" : "Infrastructure");
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_WEP_STATUS;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tprintf(_T("WEP enabled: %s\n"), (*(PUINT)QueryOid->Data == Ndis802_11WEPEnabled) ? "Yes" : "No");
|
||||||
|
|
||||||
|
_tprintf("\n");
|
||||||
|
QueryOid->Oid = OID_802_11_RSSI;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
/* This OID is optional */
|
||||||
|
_tprintf(_T("RSSI: %i dBm\n"), *(PINT)QueryOid->Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_TX_POWER_LEVEL;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
/* This OID is optional */
|
||||||
|
_tprintf(_T("Transmission power: %d mW\n"), *(PUINT)QueryOid->Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
_tprintf(_T("\n"));
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_NUMBER_OF_ANTENNAS;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
/* This OID is optional */
|
||||||
|
_tprintf(_T("Antenna count: %d\n"), *(PUINT)QueryOid->Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_TX_ANTENNA_SELECTED;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
UINT TransmitAntenna = *(PUINT)QueryOid->Data;
|
||||||
|
|
||||||
|
if (TransmitAntenna != 0xFFFFFFFF)
|
||||||
|
_tprintf(_T("Transmit antenna: %d\n"), TransmitAntenna);
|
||||||
|
else
|
||||||
|
_tprintf(_T("Transmit antenna: Any\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_RX_ANTENNA_SELECTED;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
UINT ReceiveAntenna = *(PUINT)QueryOid->Data;
|
||||||
|
|
||||||
|
if (ReceiveAntenna != 0xFFFFFFFF)
|
||||||
|
_tprintf(_T("Receive antenna: %d\n"), ReceiveAntenna);
|
||||||
|
else
|
||||||
|
_tprintf(_T("Receive antenna: Any\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
_tprintf(_T("\n"));
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_FRAGMENTATION_THRESHOLD;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
/* This OID is optional */
|
||||||
|
_tprintf(_T("Fragmentation threshold: %d bytes\n"), *(PUINT)QueryOid->Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_RTS_THRESHOLD;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (bSuccess)
|
||||||
|
{
|
||||||
|
/* This OID is optional */
|
||||||
|
_tprintf(_T("RTS threshold: %d bytes\n"), *(PUINT)QueryOid->Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
|
||||||
|
_tprintf(_T("\n"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WlanConnect(HANDLE hAdapter)
|
||||||
|
{
|
||||||
|
BOOL bSuccess;
|
||||||
|
DWORD dwBytesReturned, SetOidSize;
|
||||||
|
PNDISUIO_SET_OID SetOid;
|
||||||
|
PNDIS_802_11_SSID Ssid;
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
SetOidSize = sizeof(NDISUIO_SET_OID);
|
||||||
|
SetOid = HeapAlloc(GetProcessHeap(), 0, SetOidSize);
|
||||||
|
if (!SetOid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Set the network mode */
|
||||||
|
SetOid->Oid = OID_802_11_INFRASTRUCTURE_MODE;
|
||||||
|
*(PULONG)SetOid->Data = bAdhoc ? Ndis802_11IBSS : Ndis802_11Infrastructure;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
||||||
|
SetOid,
|
||||||
|
SetOidSize,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the authentication mode */
|
||||||
|
SetOid->Oid = OID_802_11_AUTHENTICATION_MODE;
|
||||||
|
*(PULONG)SetOid->Data = sWepKey ? Ndis802_11AuthModeShared : Ndis802_11AuthModeOpen;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
||||||
|
SetOid,
|
||||||
|
SetOidSize,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sWepKey)
|
||||||
|
{
|
||||||
|
PNDIS_802_11_WEP WepData;
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
|
||||||
|
SetOidSize = FIELD_OFFSET(NDISUIO_SET_OID, Data) +
|
||||||
|
FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial) +
|
||||||
|
(strlen(sWepKey) >> 1);
|
||||||
|
SetOid = HeapAlloc(GetProcessHeap(), 0, SetOidSize);
|
||||||
|
if (!SetOid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Add the WEP key */
|
||||||
|
SetOid->Oid = OID_802_11_ADD_WEP;
|
||||||
|
WepData = (PNDIS_802_11_WEP)SetOid->Data;
|
||||||
|
|
||||||
|
WepData->KeyIndex = 0x80000000;
|
||||||
|
WepData->KeyLength = strlen(sWepKey) >> 1;
|
||||||
|
WepData->Length = FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial) + WepData->KeyLength;
|
||||||
|
|
||||||
|
/* Assemble the hex key */
|
||||||
|
i = 0;
|
||||||
|
while (sWepKey[i << 1] != '\0')
|
||||||
|
{
|
||||||
|
WepData->KeyMaterial[i] = CharToHex(sWepKey[i << 1]) << 4;
|
||||||
|
WepData->KeyMaterial[i] |= CharToHex(sWepKey[(i << 1) + 1]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
||||||
|
SetOid,
|
||||||
|
SetOidSize,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the encryption status */
|
||||||
|
SetOid->Oid = OID_802_11_WEP_STATUS;
|
||||||
|
*(PULONG)SetOid->Data = sWepKey ? Ndis802_11WEPEnabled : Ndis802_11WEPDisabled;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
||||||
|
SetOid,
|
||||||
|
SetOidSize,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
SetOidSize = FIELD_OFFSET(NDISUIO_SET_OID, Data) + sizeof(NDIS_802_11_MAC_ADDRESS);
|
||||||
|
SetOid = HeapAlloc(GetProcessHeap(), 0, SetOidSize);
|
||||||
|
if (!SetOid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Set the BSSID */
|
||||||
|
SetOid->Oid = OID_802_11_BSSID;
|
||||||
|
RtlFillMemory(SetOid->Data, sizeof(NDIS_802_11_MAC_ADDRESS), 0xFF);
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
||||||
|
SetOid,
|
||||||
|
SetOidSize,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
SetOidSize = FIELD_OFFSET(NDISUIO_SET_OID, Data) + sizeof(NDIS_802_11_SSID);
|
||||||
|
SetOid = HeapAlloc(GetProcessHeap(), 0, SetOidSize);
|
||||||
|
if (!SetOid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Finally, set the SSID */
|
||||||
|
SetOid->Oid = OID_802_11_SSID;
|
||||||
|
Ssid = (PNDIS_802_11_SSID)SetOid->Data;
|
||||||
|
|
||||||
|
RtlCopyMemory(Ssid->Ssid, sSsid, strlen(sSsid));
|
||||||
|
Ssid->SsidLength = strlen(sSsid);
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
||||||
|
SetOid,
|
||||||
|
SetOidSize,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, SetOid);
|
||||||
|
|
||||||
|
if (!bSuccess)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
_tprintf(_T("The operation completed successfully.\n"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
WlanScan(HANDLE hAdapter)
|
||||||
|
{
|
||||||
|
BOOL bSuccess;
|
||||||
|
DWORD dwBytesReturned;
|
||||||
|
NDISUIO_SET_OID SetOid;
|
||||||
|
PNDISUIO_QUERY_OID QueryOid;
|
||||||
|
DWORD QueryOidSize;
|
||||||
|
PNDIS_802_11_BSSID_LIST BssidList;
|
||||||
|
DWORD i, j;
|
||||||
|
|
||||||
|
SetOid.Oid = OID_802_11_BSSID_LIST_SCAN;
|
||||||
|
|
||||||
|
/* Send the scan OID */
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_SET_OID_VALUE,
|
||||||
|
&SetOid,
|
||||||
|
sizeof(SetOid),
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Allocate space for 15 networks to be returned */
|
||||||
|
QueryOidSize = sizeof(NDISUIO_QUERY_OID) + (sizeof(NDIS_WLAN_BSSID) * 15);
|
||||||
|
QueryOid = HeapAlloc(GetProcessHeap(), 0, QueryOidSize);
|
||||||
|
if (!QueryOid)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
QueryOid->Oid = OID_802_11_BSSID_LIST;
|
||||||
|
BssidList = (PNDIS_802_11_BSSID_LIST)QueryOid->Data;
|
||||||
|
|
||||||
|
bSuccess = DeviceIoControl(hAdapter,
|
||||||
|
IOCTL_NDISUIO_QUERY_OID_VALUE,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
QueryOid,
|
||||||
|
QueryOidSize,
|
||||||
|
&dwBytesReturned,
|
||||||
|
NULL);
|
||||||
|
if (!bSuccess)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BssidList->NumberOfItems == 0)
|
||||||
|
{
|
||||||
|
_tprintf(_T("No networks found in range\n"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PNDIS_WLAN_BSSID BssidInfo = BssidList->Bssid;
|
||||||
|
for (i = 0; i < BssidList->NumberOfItems; i++)
|
||||||
|
{
|
||||||
|
PNDIS_802_11_SSID Ssid = &BssidInfo->Ssid;
|
||||||
|
NDIS_802_11_RSSI Rssi = BssidInfo->Rssi;
|
||||||
|
NDIS_802_11_NETWORK_INFRASTRUCTURE NetworkType = BssidInfo->InfrastructureMode;
|
||||||
|
CHAR SsidBuffer[NDIS_802_11_LENGTH_SSID + 1];
|
||||||
|
UINT Rate;
|
||||||
|
|
||||||
|
/* SSID member is a non-null terminated ASCII string */
|
||||||
|
RtlCopyMemory(SsidBuffer, Ssid->Ssid, Ssid->SsidLength);
|
||||||
|
SsidBuffer[Ssid->SsidLength] = 0;
|
||||||
|
|
||||||
|
_tprintf(_T("\n"));
|
||||||
|
|
||||||
|
_tprintf(_T("SSID: %s\n"), SsidBuffer);
|
||||||
|
|
||||||
|
_tprintf(_T("BSSID: "));
|
||||||
|
for (j = 0; j < sizeof(NDIS_802_11_MAC_ADDRESS); j++)
|
||||||
|
{
|
||||||
|
UINT BssidData = BssidInfo->MacAddress[j];
|
||||||
|
|
||||||
|
_tprintf(_T("%.2x"), BssidData);
|
||||||
|
|
||||||
|
if (j != sizeof(NDIS_802_11_MAC_ADDRESS) - 1)
|
||||||
|
_tprintf(_T(":"));
|
||||||
|
}
|
||||||
|
_tprintf(_T("\n"));
|
||||||
|
|
||||||
|
_tprintf(_T("Encrypted: %s\n"
|
||||||
|
"Network Type: %s\n"
|
||||||
|
"RSSI: %i dBm\n"
|
||||||
|
"Supported Rates (Mbps): "),
|
||||||
|
BssidInfo->Privacy == 0 ? "No" : "Yes",
|
||||||
|
NetworkType == Ndis802_11IBSS ? "Adhoc" : "Infrastructure",
|
||||||
|
(int)Rssi);
|
||||||
|
|
||||||
|
for (j = 0; j < NDIS_802_11_LENGTH_RATES; j++)
|
||||||
|
{
|
||||||
|
Rate = BssidInfo->SupportedRates[j];
|
||||||
|
if (Rate != 0)
|
||||||
|
{
|
||||||
|
/* Bit 7 is the basic rates bit */
|
||||||
|
Rate = Rate & 0x7F;
|
||||||
|
|
||||||
|
/* SupportedRates are in units of .5 */
|
||||||
|
if (Rate & 0x01)
|
||||||
|
{
|
||||||
|
/* Bit 0 is set so we need to add 0.5 */
|
||||||
|
_tprintf(_T("%u.5 "), (Rate >> 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Bit 0 is clear so just print the conversion */
|
||||||
|
_tprintf(_T("%u "), (Rate >> 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_tprintf(_T("\n"));
|
||||||
|
|
||||||
|
/* Move to the next entry */
|
||||||
|
BssidInfo = (PNDIS_WLAN_BSSID)((PUCHAR)BssidInfo + BssidInfo->Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, QueryOid);
|
||||||
|
|
||||||
|
return bSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID Usage()
|
||||||
|
{
|
||||||
|
_tprintf(_T("\nConfigures a WLAN adapter.\n\n"
|
||||||
|
"WLANCONF [-c SSID [-w WEP] [-a]] [-d] [-s]\n\n"
|
||||||
|
" -c SSID Connects to a supplied SSID.\n"
|
||||||
|
" -w WEP Specifies a WEP key to use.\n"
|
||||||
|
" -a Specifies the target network is ad-hoc\n"
|
||||||
|
" -d Disconnects from the current AP.\n"
|
||||||
|
" -s Scans and displays a list of access points in range.\n\n"
|
||||||
|
" Passing no parameters will print information about the current WLAN connection\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL ParseCmdline(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
INT i;
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (argv[i][0] == '-')
|
||||||
|
{
|
||||||
|
switch (argv[i][1])
|
||||||
|
{
|
||||||
|
case 's':
|
||||||
|
bScan = TRUE;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
bDisconnect = TRUE;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (i == argc - 1)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
bConnect = TRUE;
|
||||||
|
sSsid = argv[++i];
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
if (i == argc - 1)
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
sWepKey = argv[++i];
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
bAdhoc = TRUE;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
Usage();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Usage();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
HANDLE hAdapter;
|
||||||
|
IP_ADAPTER_INDEX_MAP IpInfo;
|
||||||
|
|
||||||
|
if (!ParseCmdline(argc, argv))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!OpenWlanAdapter(&hAdapter, &IpInfo))
|
||||||
|
{
|
||||||
|
_tprintf(_T("Unable to find a WLAN adapter on the system\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bScan)
|
||||||
|
{
|
||||||
|
if (!WlanScan(hAdapter))
|
||||||
|
{
|
||||||
|
DoFormatMessage(GetLastError());
|
||||||
|
CloseHandle(hAdapter);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bDisconnect)
|
||||||
|
{
|
||||||
|
if (!WlanDisconnect(hAdapter, &IpInfo))
|
||||||
|
{
|
||||||
|
DoFormatMessage(GetLastError());
|
||||||
|
CloseHandle(hAdapter);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bConnect)
|
||||||
|
{
|
||||||
|
if (!WlanConnect(hAdapter))
|
||||||
|
{
|
||||||
|
DoFormatMessage(GetLastError());
|
||||||
|
CloseHandle(hAdapter);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!WlanPrintCurrentStatus(hAdapter))
|
||||||
|
{
|
||||||
|
DoFormatMessage(GetLastError());
|
||||||
|
CloseHandle(hAdapter);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(hAdapter);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd">
|
||||||
|
<module name="wlanconf" type="win32cui" installbase="system32" installname="wlanconf.exe">
|
||||||
|
<include base="wlanconf">.</include>
|
||||||
|
<include base="ReactOS">include/reactos/drivers/ndisuio</include>
|
||||||
|
<library>iphlpapi</library>
|
||||||
|
<file>wlanconf.c</file>
|
||||||
|
<file>wlanconf.rc</file>
|
||||||
|
</module>
|
7
reactos/base/applications/network/wlanconf/wlanconf.rc
Normal file
7
reactos/base/applications/network/wlanconf/wlanconf.rc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS WLAN Configuration Tool\0"
|
||||||
|
#define REACTOS_STR_INTERNAL_NAME "wlanconf\0"
|
||||||
|
#define REACTOS_STR_ORIGINAL_FILENAME "wlanconf.exe\0"
|
||||||
|
#define REACTOS_STR_ORIGINAL_COPYRIGHT "Cameron Gutman (cameron.gutman@reactos.org)\0"
|
||||||
|
#include <reactos/version.rc>
|
||||||
|
|
||||||
|
|
|
@ -1399,6 +1399,13 @@ HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","ImagePath",0x00020000,"system
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Start",0x00010001,0x00000000
|
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Start",0x00010001,0x00000000
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Type",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\NMIDebug","Type",0x00010001,0x00000001
|
||||||
|
|
||||||
|
; NDIS User I/O driver (FIXME: Should be installed via INF and started on demand)
|
||||||
|
HKLM,"SYSTEM\CurrentControlSet\Services\Ndisuio","ErrorControl",0x00010001,0x00000001
|
||||||
|
HKLM,"SYSTEM\CurrentControlSet\Services\Ndisuio","Group",0x00000000,"NDIS"
|
||||||
|
HKLM,"SYSTEM\CurrentControlSet\Services\Ndisuio","ImagePath",0x00020000,"system32\drivers\ndisuio.sys"
|
||||||
|
HKLM,"SYSTEM\CurrentControlSet\Services\Ndisuio","Start",0x00010001,0x00000001
|
||||||
|
HKLM,"SYSTEM\CurrentControlSet\Services\Ndisuio","Type",0x00010001,0x00000001
|
||||||
|
|
||||||
; Packet driver
|
; Packet driver
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ErrorControl",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ErrorControl",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Group",0x00000000,"PNP_TDI"
|
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","Group",0x00000000,"PNP_TDI"
|
||||||
|
@ -1629,7 +1636,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ErrorControl",0x00010001,0x000
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Group",0x00000000,"TDI"
|
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Group",0x00000000,"TDI"
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ImagePath",0x00020000,"%SystemRoot%\system32\wlansvc.exe"
|
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ImagePath",0x00020000,"%SystemRoot%\system32\wlansvc.exe"
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ObjectName",0x00000000,"LocalSystem"
|
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","ObjectName",0x00000000,"LocalSystem"
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Start",0x00010001,0x00000003
|
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Start",0x00010001,0x00000002
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Type",0x00010001,0x00000110
|
HKLM,"SYSTEM\CurrentControlSet\Services\WlanSvc","Type",0x00010001,0x00000110
|
||||||
|
|
||||||
; Simple TCP services
|
; Simple TCP services
|
||||||
|
|
|
@ -76,6 +76,7 @@ base\applications\network\route\route.exe 1
|
||||||
base\applications\network\telnet\telnet.exe 1
|
base\applications\network\telnet\telnet.exe 1
|
||||||
base\applications\network\tracert\tracert.exe 1
|
base\applications\network\tracert\tracert.exe 1
|
||||||
base\applications\network\whois\whois.exe 1
|
base\applications\network\whois\whois.exe 1
|
||||||
|
base\applications\network\wlanconf\wlanconf.exe 1
|
||||||
base\applications\notepad\notepad.exe 1
|
base\applications\notepad\notepad.exe 1
|
||||||
base\applications\rapps\rapps.exe 1
|
base\applications\rapps\rapps.exe 1
|
||||||
base\applications\regedit\regedit.exe 4
|
base\applications\regedit\regedit.exe 4
|
||||||
|
@ -532,6 +533,7 @@ drivers\network\tcpip\tcpip.sys 2
|
||||||
drivers\network\tdi\tdi.sys 2
|
drivers\network\tdi\tdi.sys 2
|
||||||
drivers\network\dd\ne2000\ne2000.sys 2
|
drivers\network\dd\ne2000\ne2000.sys 2
|
||||||
drivers\network\dd\pcnet\pcnet.sys 2
|
drivers\network\dd\pcnet\pcnet.sys 2
|
||||||
|
drivers\network\ndisuio\ndisuio.sys 2
|
||||||
|
|
||||||
drivers\serial\serenum\serenum.sys 2
|
drivers\serial\serenum\serenum.sys 2
|
||||||
drivers\serial\serial\serial.sys 2
|
drivers\serial\serial\serial.sys 2
|
||||||
|
|
|
@ -2,5 +2,6 @@
|
||||||
add_subdirectory(afd)
|
add_subdirectory(afd)
|
||||||
add_subdirectory(dd)
|
add_subdirectory(dd)
|
||||||
add_subdirectory(ndis)
|
add_subdirectory(ndis)
|
||||||
|
add_subdirectory(ndisuio)
|
||||||
add_subdirectory(tcpip)
|
add_subdirectory(tcpip)
|
||||||
add_subdirectory(tdi)
|
add_subdirectory(tdi)
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
<directory name="ndis">
|
<directory name="ndis">
|
||||||
<xi:include href="ndis/ndis.rbuild" />
|
<xi:include href="ndis/ndis.rbuild" />
|
||||||
</directory>
|
</directory>
|
||||||
|
<directory name="ndisuio">
|
||||||
|
<xi:include href="ndisuio/ndisuio.rbuild" />
|
||||||
|
</directory>
|
||||||
<directory name="tcpip">
|
<directory name="tcpip">
|
||||||
<xi:include href="tcpip/tcpip.rbuild" />
|
<xi:include href="tcpip/tcpip.rbuild" />
|
||||||
</directory>
|
</directory>
|
||||||
|
|
25
reactos/drivers/network/ndisuio/CMakeLists.txt
Normal file
25
reactos/drivers/network/ndisuio/CMakeLists.txt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
add_definitions(
|
||||||
|
-DNDIS50
|
||||||
|
-D_NTDRIVER_)
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
BEFORE include
|
||||||
|
${REACTOS_SOURCE_DIR}/include/reactos/drivers/ndisuio)
|
||||||
|
|
||||||
|
list(APPEND SOURCE
|
||||||
|
createclose.c
|
||||||
|
ioctl.c
|
||||||
|
main.c
|
||||||
|
misc.c
|
||||||
|
protocol.c
|
||||||
|
readwrite.c
|
||||||
|
ndisuio.rc)
|
||||||
|
|
||||||
|
add_library(ndisuio SHARED ${SOURCE})
|
||||||
|
|
||||||
|
set_module_type(ndisuio kernelmodedriver)
|
||||||
|
add_importlibs(ndisuio ndis ntoskrnl hal)
|
||||||
|
|
||||||
|
add_pch(ndisuio ndisuio.h)
|
||||||
|
|
||||||
|
add_cd_file(TARGET ndisuio DESTINATION reactos/system32/drivers FOR all)
|
69
reactos/drivers/network/ndisuio/createclose.c
Normal file
69
reactos/drivers/network/ndisuio/createclose.c
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: createclose.c
|
||||||
|
* PURPOSE: IRP_MJ_CREATE and IRP_MJ_CLOSE handling
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
//#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchCreate(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
DPRINT("Created file object 0x%x\n", IrpSp->FileObject);
|
||||||
|
|
||||||
|
/* This is associated with an adapter during IOCTL_NDISUIO_OPEN_(WRITE_)DEVICE */
|
||||||
|
IrpSp->FileObject->FsContext = NULL;
|
||||||
|
IrpSp->FileObject->FsContext2 = NULL;
|
||||||
|
|
||||||
|
/* Completed successfully */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = FILE_OPENED;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchClose(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry = IrpSp->FileObject->FsContext2;
|
||||||
|
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
DPRINT("Closing file object 0x%x\n", IrpSp->FileObject);
|
||||||
|
|
||||||
|
/* Check if this handle was ever associated with an adapter */
|
||||||
|
if (AdapterContext != NULL)
|
||||||
|
{
|
||||||
|
ASSERT(OpenEntry != NULL);
|
||||||
|
|
||||||
|
DPRINT("Removing binding to adapter %wZ\n", &AdapterContext->DeviceName);
|
||||||
|
|
||||||
|
/* Call the our helper */
|
||||||
|
DereferenceAdapterContextWithOpenEntry(AdapterContext, OpenEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Completed */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
525
reactos/drivers/network/ndisuio/ioctl.c
Normal file
525
reactos/drivers/network/ndisuio/ioctl.c
Normal file
|
@ -0,0 +1,525 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: ioctl.c
|
||||||
|
* PURPOSE: IOCTL handling
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
//#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
WaitForBind(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
/* I've seen several code samples that use this IOCTL but there's
|
||||||
|
* no official documentation on it. I'm just implementing it as a no-op
|
||||||
|
* right now because I don't see any reason we need it. We handle an open
|
||||||
|
* and bind just fine with IRP_MJ_CREATE and IOCTL_NDISUIO_OPEN_DEVICE */
|
||||||
|
DPRINT("Wait for bind complete\n");
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
QueryBinding(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = NULL;
|
||||||
|
PNDISUIO_QUERY_BINDING QueryBinding = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
ULONG BindingLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PLIST_ENTRY CurrentEntry;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
ULONG i;
|
||||||
|
ULONG BytesCopied = 0;
|
||||||
|
|
||||||
|
if (QueryBinding && BindingLength >= sizeof(NDISUIO_QUERY_BINDING))
|
||||||
|
{
|
||||||
|
KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
|
||||||
|
i = 0;
|
||||||
|
CurrentEntry = GlobalAdapterList.Flink;
|
||||||
|
while (CurrentEntry != &GlobalAdapterList)
|
||||||
|
{
|
||||||
|
if (i == QueryBinding->BindingIndex)
|
||||||
|
{
|
||||||
|
AdapterContext = CONTAINING_RECORD(CurrentEntry, NDISUIO_ADAPTER_CONTEXT, ListEntry);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
|
||||||
|
if (AdapterContext)
|
||||||
|
{
|
||||||
|
DPRINT("Query binding for index %d is adapter %wZ\n", i, &AdapterContext->DeviceName);
|
||||||
|
BytesCopied = sizeof(NDISUIO_QUERY_BINDING);
|
||||||
|
if (AdapterContext->DeviceName.Length <= BindingLength - BytesCopied)
|
||||||
|
{
|
||||||
|
QueryBinding->DeviceNameOffset = BytesCopied;
|
||||||
|
QueryBinding->DeviceNameLength = AdapterContext->DeviceName.Length;
|
||||||
|
RtlCopyMemory((PUCHAR)QueryBinding + QueryBinding->DeviceNameOffset,
|
||||||
|
AdapterContext->DeviceName.Buffer,
|
||||||
|
QueryBinding->DeviceNameLength);
|
||||||
|
BytesCopied += AdapterContext->DeviceName.Length;
|
||||||
|
|
||||||
|
/* FIXME: Copy description too */
|
||||||
|
QueryBinding->DeviceDescrOffset = BytesCopied;
|
||||||
|
QueryBinding->DeviceDescrLength = 0;
|
||||||
|
|
||||||
|
/* Successful */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not enough buffer space */
|
||||||
|
Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid index */
|
||||||
|
Status = STATUS_NO_MORE_ENTRIES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid parameters */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = BytesCopied;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
CancelPacketRead(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_PACKET_ENTRY PacketEntry;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
/* Indicate a 0-byte packet on the queue so one read returns 0 */
|
||||||
|
PacketEntry = ExAllocatePool(PagedPool, sizeof(NDISUIO_PACKET_ENTRY));
|
||||||
|
if (PacketEntry)
|
||||||
|
{
|
||||||
|
PacketEntry->PacketLength = 0;
|
||||||
|
|
||||||
|
ExInterlockedInsertHeadList(&AdapterContext->PacketList,
|
||||||
|
&PacketEntry->ListEntry,
|
||||||
|
&AdapterContext->Spinlock);
|
||||||
|
|
||||||
|
KeSetEvent(&AdapterContext->PacketReadEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
SetAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_SET_OID SetOidRequest;
|
||||||
|
NDIS_REQUEST Request;
|
||||||
|
ULONG RequestLength;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
SetOidRequest = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
if (SetOidRequest && RequestLength >= sizeof(NDIS_OID))
|
||||||
|
{
|
||||||
|
/* Setup the NDIS request */
|
||||||
|
Request.RequestType = NdisRequestSetInformation;
|
||||||
|
Request.DATA.SET_INFORMATION.Oid = SetOidRequest->Oid;
|
||||||
|
Request.DATA.SET_INFORMATION.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
|
||||||
|
if (Request.DATA.SET_INFORMATION.InformationBufferLength != 0)
|
||||||
|
{
|
||||||
|
Request.DATA.SET_INFORMATION.InformationBuffer = SetOidRequest->Data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Request.DATA.SET_INFORMATION.InformationBuffer = NULL;
|
||||||
|
}
|
||||||
|
Request.DATA.SET_INFORMATION.BytesRead = 0;
|
||||||
|
|
||||||
|
DPRINT("Setting OID 0x%x on adapter %wZ\n", SetOidRequest->Oid, &AdapterContext->DeviceName);
|
||||||
|
|
||||||
|
/* Dispatch the request */
|
||||||
|
NdisRequest(&Status,
|
||||||
|
AdapterContext->BindingHandle,
|
||||||
|
&Request);
|
||||||
|
|
||||||
|
/* Wait for the request */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the bytes read */
|
||||||
|
if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(NDIS_OID) + Request.DATA.SET_INFORMATION.BytesRead;
|
||||||
|
|
||||||
|
DPRINT("Final request status: 0x%x (%d)\n", Status, Irp->IoStatus.Information);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Bad parameters */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
QueryAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_QUERY_OID QueryOidRequest;
|
||||||
|
NDIS_REQUEST Request;
|
||||||
|
ULONG RequestLength;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
QueryOidRequest = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID))
|
||||||
|
{
|
||||||
|
/* Setup the NDIS request */
|
||||||
|
Request.RequestType = NdisRequestQueryInformation;
|
||||||
|
Request.DATA.QUERY_INFORMATION.Oid = QueryOidRequest->Oid;
|
||||||
|
Request.DATA.QUERY_INFORMATION.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
|
||||||
|
if (Request.DATA.QUERY_INFORMATION.InformationBufferLength != 0)
|
||||||
|
{
|
||||||
|
Request.DATA.QUERY_INFORMATION.InformationBuffer = QueryOidRequest->Data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Request.DATA.QUERY_INFORMATION.InformationBuffer = NULL;
|
||||||
|
}
|
||||||
|
Request.DATA.QUERY_INFORMATION.BytesWritten = 0;
|
||||||
|
|
||||||
|
DPRINT("Querying OID 0x%x on adapter %wZ\n", QueryOidRequest->Oid, &AdapterContext->DeviceName);
|
||||||
|
|
||||||
|
/* Dispatch the request */
|
||||||
|
NdisRequest(&Status,
|
||||||
|
AdapterContext->BindingHandle,
|
||||||
|
&Request);
|
||||||
|
|
||||||
|
/* Wait for the request */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the bytes written */
|
||||||
|
if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(NDIS_OID) + Request.DATA.QUERY_INFORMATION.BytesWritten;
|
||||||
|
|
||||||
|
DPRINT("Final request status: 0x%x (%d)\n", Status, Irp->IoStatus.Information);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Bad parameters */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
OpenDeviceReadWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
ULONG NameLength;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext;
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
NameLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
if (NameLength != 0)
|
||||||
|
{
|
||||||
|
DeviceName.MaximumLength = DeviceName.Length = NameLength;
|
||||||
|
DeviceName.Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
/* Check if this already has a context */
|
||||||
|
AdapterContext = FindAdapterContextByName(&DeviceName);
|
||||||
|
if (AdapterContext != NULL)
|
||||||
|
{
|
||||||
|
DPRINT("Binding file object 0x%x to device %wZ\n", FileObject, &AdapterContext->DeviceName);
|
||||||
|
|
||||||
|
/* Reference the adapter context */
|
||||||
|
KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
|
||||||
|
if (AdapterContext->OpenCount != 0)
|
||||||
|
{
|
||||||
|
/* An open for read-write is exclusive,
|
||||||
|
* so we can't have any other open handles */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Add a reference */
|
||||||
|
ReferenceAdapterContext(AdapterContext);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid device name */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the bind succeeded */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
OpenEntry = ExAllocatePool(NonPagedPool, sizeof(*OpenEntry));
|
||||||
|
if (OpenEntry)
|
||||||
|
{
|
||||||
|
/* Set the file object pointer */
|
||||||
|
OpenEntry->FileObject = FileObject;
|
||||||
|
|
||||||
|
/* Set the permissions */
|
||||||
|
OpenEntry->WriteOnly = FALSE;
|
||||||
|
|
||||||
|
/* Associate this FO with the adapter */
|
||||||
|
FileObject->FsContext = AdapterContext;
|
||||||
|
FileObject->FsContext2 = OpenEntry;
|
||||||
|
|
||||||
|
/* Add it to the adapter's list */
|
||||||
|
InsertTailList(&AdapterContext->OpenEntryList,
|
||||||
|
&OpenEntry->ListEntry);
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Remove the reference we added */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
DereferenceAdapterContextWithOpenEntry(AdapterContext, NULL);
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid device name */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
OpenDeviceWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||||
|
{
|
||||||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
ULONG NameLength;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext;
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
NameLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||||||
|
if (NameLength != 0)
|
||||||
|
{
|
||||||
|
DeviceName.MaximumLength = DeviceName.Length = NameLength;
|
||||||
|
DeviceName.Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
|
/* Check if this already has a context */
|
||||||
|
AdapterContext = FindAdapterContextByName(&DeviceName);
|
||||||
|
if (AdapterContext != NULL)
|
||||||
|
{
|
||||||
|
/* Reference the adapter context */
|
||||||
|
KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
|
||||||
|
ReferenceAdapterContext(AdapterContext);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid device name */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the bind succeeded */
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
OpenEntry = ExAllocatePool(NonPagedPool, sizeof(*OpenEntry));
|
||||||
|
if (OpenEntry)
|
||||||
|
{
|
||||||
|
/* Set the file object pointer */
|
||||||
|
OpenEntry->FileObject = FileObject;
|
||||||
|
|
||||||
|
/* Associate this FO with the adapter */
|
||||||
|
FileObject->FsContext = AdapterContext;
|
||||||
|
FileObject->FsContext2 = OpenEntry;
|
||||||
|
|
||||||
|
/* Set permissions */
|
||||||
|
OpenEntry->WriteOnly = TRUE;
|
||||||
|
|
||||||
|
/* Add it to the adapter's list */
|
||||||
|
InsertTailList(&AdapterContext->OpenEntryList,
|
||||||
|
&OpenEntry->ListEntry);
|
||||||
|
|
||||||
|
/* Success */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Remove the reference we added */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
DereferenceAdapterContext(AdapterContext, NULL);
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid device name */
|
||||||
|
Status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry;
|
||||||
|
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
/* Handle open IOCTLs first */
|
||||||
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||||
|
{
|
||||||
|
case IOCTL_NDISUIO_OPEN_DEVICE:
|
||||||
|
return OpenDeviceReadWrite(Irp, IrpSp);
|
||||||
|
#if 0
|
||||||
|
case IOCTL_NDISUIO_OPEN_WRITE_DEVICE:
|
||||||
|
return OpenDeviceWrite(Irp, IrpSp);
|
||||||
|
#endif
|
||||||
|
case IOCTL_NDISUIO_BIND_WAIT:
|
||||||
|
return WaitForBind(Irp, IrpSp);
|
||||||
|
|
||||||
|
case IOCTL_NDISUIO_QUERY_BINDING:
|
||||||
|
return QueryBinding(Irp, IrpSp);
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Fail if this file object has no adapter associated */
|
||||||
|
if (IrpSp->FileObject->FsContext == NULL)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now handle write IOCTLs */
|
||||||
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||||
|
{
|
||||||
|
case IOCTL_NDISUIO_SET_OID_VALUE:
|
||||||
|
return SetAdapterOid(Irp, IrpSp);
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Check that we have read permissions */
|
||||||
|
OpenEntry = IrpSp->FileObject->FsContext2;
|
||||||
|
if (OpenEntry->WriteOnly)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
case IOCTL_CANCEL_READ:
|
||||||
|
return CancelPacketRead(Irp, IrpSp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case IOCTL_NDISUIO_QUERY_OID_VALUE:
|
||||||
|
return QueryAdapterOid(Irp, IrpSp);
|
||||||
|
|
||||||
|
default:
|
||||||
|
DPRINT1("Unimplemented\n");
|
||||||
|
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
104
reactos/drivers/network/ndisuio/main.c
Normal file
104
reactos/drivers/network/ndisuio/main.c
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: main.c
|
||||||
|
* PURPOSE: Driver entry point and protocol initialization
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
//#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
PDEVICE_OBJECT GlobalDeviceObject;
|
||||||
|
NDIS_HANDLE GlobalProtocolHandle;
|
||||||
|
KSPIN_LOCK GlobalAdapterListLock;
|
||||||
|
LIST_ENTRY GlobalAdapterList;
|
||||||
|
|
||||||
|
NDIS_STRING ProtocolName = RTL_CONSTANT_STRING(L"NDISUIO");
|
||||||
|
|
||||||
|
VOID NTAPI NduUnload(PDRIVER_OBJECT DriverObject)
|
||||||
|
{
|
||||||
|
DPRINT("NDISUIO: Unloaded\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
DriverEntry(PDRIVER_OBJECT DriverObject,
|
||||||
|
PUNICODE_STRING RegistryPath)
|
||||||
|
{
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
NDIS_PROTOCOL_CHARACTERISTICS Chars;
|
||||||
|
UNICODE_STRING NtDeviceName = RTL_CONSTANT_STRING(NDISUIO_DEVICE_NAME_NT);
|
||||||
|
UNICODE_STRING DosDeviceName = RTL_CONSTANT_STRING(NDISUIO_DEVICE_NAME_DOS);
|
||||||
|
|
||||||
|
/* Setup dispatch functions */
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = NduDispatchCreate;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = NduDispatchClose;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NduDispatchDeviceControl;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_READ] = NduDispatchRead;
|
||||||
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = NduDispatchWrite;
|
||||||
|
DriverObject->DriverUnload = NduUnload;
|
||||||
|
|
||||||
|
/* Setup global state */
|
||||||
|
InitializeListHead(&GlobalAdapterList);
|
||||||
|
KeInitializeSpinLock(&GlobalAdapterListLock);
|
||||||
|
|
||||||
|
/* Create the NDISUIO device object */
|
||||||
|
Status = IoCreateDevice(DriverObject,
|
||||||
|
0,
|
||||||
|
&NtDeviceName,
|
||||||
|
FILE_DEVICE_SECURE_OPEN,
|
||||||
|
0,
|
||||||
|
FALSE,
|
||||||
|
&GlobalDeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create device object with status 0x%x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a symbolic link into the DOS devices namespace */
|
||||||
|
Status = IoCreateSymbolicLink(&DosDeviceName, &NtDeviceName);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to create symbolic link with status 0x%x\n", Status);
|
||||||
|
IoDeleteDevice(GlobalDeviceObject);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register the protocol with NDIS */
|
||||||
|
RtlZeroMemory(&Chars, sizeof(Chars));
|
||||||
|
Chars.MajorNdisVersion = NDIS_MAJOR_VERSION;
|
||||||
|
Chars.MinorNdisVersion = NDIS_MINOR_VERSION;
|
||||||
|
Chars.OpenAdapterCompleteHandler = NduOpenAdapterComplete;
|
||||||
|
Chars.CloseAdapterCompleteHandler = NduCloseAdapterComplete;
|
||||||
|
Chars.SendCompleteHandler = NduSendComplete;
|
||||||
|
Chars.TransferDataCompleteHandler = NduTransferDataComplete;
|
||||||
|
Chars.ResetCompleteHandler = NduResetComplete;
|
||||||
|
Chars.RequestCompleteHandler = NduRequestComplete;
|
||||||
|
Chars.ReceiveHandler = NduReceive;
|
||||||
|
Chars.ReceiveCompleteHandler = NduReceiveComplete;
|
||||||
|
Chars.StatusHandler = NduStatus;
|
||||||
|
Chars.StatusCompleteHandler = NduStatusComplete;
|
||||||
|
Chars.Name = ProtocolName;
|
||||||
|
Chars.BindAdapterHandler = NduBindAdapter;
|
||||||
|
Chars.UnbindAdapterHandler = NduUnbindAdapter;
|
||||||
|
|
||||||
|
NdisRegisterProtocol(&Status,
|
||||||
|
&GlobalProtocolHandle,
|
||||||
|
&Chars,
|
||||||
|
sizeof(Chars));
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to register protocol with status 0x%x\n", Status);
|
||||||
|
IoDeleteSymbolicLink(&DosDeviceName);
|
||||||
|
IoDeleteDevice(GlobalDeviceObject);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("NDISUIO: Loaded\n");
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
176
reactos/drivers/network/ndisuio/misc.c
Normal file
176
reactos/drivers/network/ndisuio/misc.c
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: misc.c
|
||||||
|
* PURPOSE: Helper functions
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
AllocateAndChainBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
|
||||||
|
PNDIS_PACKET Packet,
|
||||||
|
PVOID Buffer,
|
||||||
|
ULONG BufferSize,
|
||||||
|
BOOLEAN Front)
|
||||||
|
{
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
PNDIS_BUFFER NdisBuffer;
|
||||||
|
|
||||||
|
/* Allocate the NDIS buffer mapping the pool */
|
||||||
|
NdisAllocateBuffer(&Status,
|
||||||
|
&NdisBuffer,
|
||||||
|
AdapterContext->BufferPoolHandle,
|
||||||
|
Buffer,
|
||||||
|
BufferSize);
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("No free buffer descriptors\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Front)
|
||||||
|
{
|
||||||
|
/* Chain the buffer to front */
|
||||||
|
NdisChainBufferAtFront(Packet, NdisBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Chain the buffer to back */
|
||||||
|
NdisChainBufferAtBack(Packet, NdisBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return NDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
PNDIS_PACKET
|
||||||
|
CreatePacketFromPoolBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
|
||||||
|
PVOID Buffer,
|
||||||
|
ULONG BufferSize)
|
||||||
|
{
|
||||||
|
PNDIS_PACKET Packet;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
|
||||||
|
/* Allocate a packet descriptor */
|
||||||
|
NdisAllocatePacket(&Status,
|
||||||
|
&Packet,
|
||||||
|
AdapterContext->PacketPoolHandle);
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("No free packet descriptors\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use the helper to chain the buffer */
|
||||||
|
Status = AllocateAndChainBuffer(AdapterContext, Packet,
|
||||||
|
Buffer, BufferSize, TRUE);
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
NdisFreePacket(Packet);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the packet */
|
||||||
|
return Packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CleanupAndFreePacket(PNDIS_PACKET Packet, BOOLEAN FreePool)
|
||||||
|
{
|
||||||
|
PNDIS_BUFFER Buffer;
|
||||||
|
PVOID Data;
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
/* Free each buffer and its backing pool memory */
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
/* Unchain each buffer */
|
||||||
|
NdisUnchainBufferAtFront(Packet, &Buffer);
|
||||||
|
if (!Buffer)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Get the backing memory */
|
||||||
|
NdisQueryBuffer(Buffer, &Data, &Length);
|
||||||
|
|
||||||
|
/* Free the buffer */
|
||||||
|
NdisFreeBuffer(Buffer);
|
||||||
|
|
||||||
|
if (FreePool)
|
||||||
|
{
|
||||||
|
/* Free the backing memory */
|
||||||
|
ExFreePool(Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the packet descriptor */
|
||||||
|
NdisFreePacket(Packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT
|
||||||
|
FindAdapterContextByName(PNDIS_STRING DeviceName)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
PLIST_ENTRY CurrentEntry;
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
|
||||||
|
CurrentEntry = GlobalAdapterList.Flink;
|
||||||
|
while (CurrentEntry != &GlobalAdapterList)
|
||||||
|
{
|
||||||
|
AdapterContext = CONTAINING_RECORD(CurrentEntry, NDISUIO_ADAPTER_CONTEXT, ListEntry);
|
||||||
|
|
||||||
|
/* Check if the device name matches */
|
||||||
|
if (RtlEqualUnicodeString(&AdapterContext->DeviceName, DeviceName, TRUE))
|
||||||
|
{
|
||||||
|
KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
|
||||||
|
return AdapterContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ReferenceAdapterContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext)
|
||||||
|
{
|
||||||
|
/* Increment the open count */
|
||||||
|
AdapterContext->OpenCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
DereferenceAdapterContextWithOpenEntry(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
|
/* Lock the adapter context */
|
||||||
|
KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
|
||||||
|
|
||||||
|
/* Decrement the open count */
|
||||||
|
AdapterContext->OpenCount--;
|
||||||
|
|
||||||
|
/* Cleanup the open entry if we were given one */
|
||||||
|
if (OpenEntry != NULL)
|
||||||
|
{
|
||||||
|
/* Remove the open entry */
|
||||||
|
RemoveEntryList(&OpenEntry->ListEntry);
|
||||||
|
|
||||||
|
/* Invalidate the FO */
|
||||||
|
OpenEntry->FileObject->FsContext = NULL;
|
||||||
|
OpenEntry->FileObject->FsContext2 = NULL;
|
||||||
|
|
||||||
|
/* Free the open entry */
|
||||||
|
ExFreePool(OpenEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the adapter context lock */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
}
|
210
reactos/drivers/network/ndisuio/ndisuio.h
Normal file
210
reactos/drivers/network/ndisuio/ndisuio.h
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: ndisuio.h
|
||||||
|
* PURPOSE: NDISUIO definitions
|
||||||
|
*/
|
||||||
|
#ifndef __NDISUIO_H
|
||||||
|
#define __NDISUIO_H
|
||||||
|
|
||||||
|
#include <wdm.h>
|
||||||
|
#include <ndis.h>
|
||||||
|
#include <nuiouser.h>
|
||||||
|
|
||||||
|
extern PDEVICE_OBJECT GlobalDeviceObject;
|
||||||
|
extern NDIS_HANDLE GlobalProtocolHandle;
|
||||||
|
extern LIST_ENTRY GlobalAdapterList;
|
||||||
|
extern KSPIN_LOCK GlobalAdapterListLock;
|
||||||
|
|
||||||
|
typedef struct _NDISUIO_ADAPTER_CONTEXT
|
||||||
|
{
|
||||||
|
/* Asynchronous completion */
|
||||||
|
NDIS_STATUS AsyncStatus;
|
||||||
|
KEVENT AsyncEvent;
|
||||||
|
|
||||||
|
/* NDIS binding information */
|
||||||
|
NDIS_HANDLE BindingHandle;
|
||||||
|
|
||||||
|
/* Reference count information */
|
||||||
|
ULONG OpenCount;
|
||||||
|
LIST_ENTRY OpenEntryList;
|
||||||
|
|
||||||
|
/* NDIS pools */
|
||||||
|
NDIS_HANDLE PacketPoolHandle;
|
||||||
|
NDIS_HANDLE BufferPoolHandle;
|
||||||
|
|
||||||
|
/* Receive packet list */
|
||||||
|
LIST_ENTRY PacketList;
|
||||||
|
KEVENT PacketReadEvent;
|
||||||
|
|
||||||
|
/* Mac options */
|
||||||
|
ULONG MacOptions;
|
||||||
|
|
||||||
|
/* Device name */
|
||||||
|
UNICODE_STRING DeviceName;
|
||||||
|
|
||||||
|
/* Global list entry */
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
/* Spin lock */
|
||||||
|
KSPIN_LOCK Spinlock;
|
||||||
|
} NDISUIO_ADAPTER_CONTEXT, *PNDISUIO_ADAPTER_CONTEXT;
|
||||||
|
|
||||||
|
typedef struct _NDISUIO_OPEN_ENTRY
|
||||||
|
{
|
||||||
|
/* File object */
|
||||||
|
PFILE_OBJECT FileObject;
|
||||||
|
|
||||||
|
/* Tracks how this adapter was opened (write-only or read-write) */
|
||||||
|
BOOLEAN WriteOnly;
|
||||||
|
|
||||||
|
/* List entry */
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
} NDISUIO_OPEN_ENTRY, *PNDISUIO_OPEN_ENTRY;
|
||||||
|
|
||||||
|
typedef struct _NDISUIO_PACKET_ENTRY
|
||||||
|
{
|
||||||
|
/* Length of data at the end of the struct */
|
||||||
|
ULONG PacketLength;
|
||||||
|
|
||||||
|
/* Entry on the packet list */
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
/* Packet data */
|
||||||
|
UCHAR PacketData[1];
|
||||||
|
} NDISUIO_PACKET_ENTRY, *PNDISUIO_PACKET_ENTRY;
|
||||||
|
|
||||||
|
/* NDIS version info */
|
||||||
|
#define NDIS_MAJOR_VERSION 5
|
||||||
|
#define NDIS_MINOR_VERSION 0
|
||||||
|
|
||||||
|
/* createclose.c */
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchCreate(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchClose(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
/* ioctl.c */
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
/* misc.c */
|
||||||
|
NDIS_STATUS
|
||||||
|
AllocateAndChainBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
|
||||||
|
PNDIS_PACKET Packet,
|
||||||
|
PVOID Buffer,
|
||||||
|
ULONG BufferSize,
|
||||||
|
BOOLEAN Front);
|
||||||
|
|
||||||
|
PNDIS_PACKET
|
||||||
|
CreatePacketFromPoolBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
|
||||||
|
PVOID Buffer,
|
||||||
|
ULONG BufferSize);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CleanupAndFreePacket(PNDIS_PACKET Packet,
|
||||||
|
BOOLEAN FreePool);
|
||||||
|
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT
|
||||||
|
FindAdapterContextByName(PNDIS_STRING DeviceName);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ReferenceAdapterContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
DereferenceAdapterContextWithOpenEntry(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry);
|
||||||
|
|
||||||
|
/* protocol.c */
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduOpenAdapterComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status,
|
||||||
|
NDIS_STATUS OpenStatus);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduCloseAdapterComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduSendComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_PACKET Packet,
|
||||||
|
NDIS_STATUS Status);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_PACKET Packet,
|
||||||
|
NDIS_STATUS Status,
|
||||||
|
UINT BytesTransferred);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduResetComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduRequestComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_REQUEST NdisRequest,
|
||||||
|
NDIS_STATUS Status);
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
NTAPI
|
||||||
|
NduReceive(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_HANDLE MacReceiveContext,
|
||||||
|
PVOID HeaderBuffer,
|
||||||
|
UINT HeaderBufferSize,
|
||||||
|
PVOID LookAheadBuffer,
|
||||||
|
UINT LookaheadBufferSize,
|
||||||
|
UINT PacketSize);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduStatus(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS GeneralStatus,
|
||||||
|
PVOID StatusBuffer,
|
||||||
|
UINT StatusBufferSize);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduStatusComplete(NDIS_HANDLE ProtocolBindingContext);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduBindAdapter(PNDIS_STATUS Status,
|
||||||
|
NDIS_HANDLE BindContext,
|
||||||
|
PNDIS_STRING DeviceName,
|
||||||
|
PVOID SystemSpecific1,
|
||||||
|
PVOID SystemSpecific2);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduUnbindAdapter(PNDIS_STATUS Status,
|
||||||
|
NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_HANDLE UnbindContext);
|
||||||
|
|
||||||
|
/* readwrite.c */
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchRead(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchWrite(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp);
|
||||||
|
#endif /* __NDISUIO_H */
|
19
reactos/drivers/network/ndisuio/ndisuio.rbuild
Normal file
19
reactos/drivers/network/ndisuio/ndisuio.rbuild
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||||
|
<module name="ndisuio" type="kernelmodedriver" installbase="system32/drivers" installname="ndisuio.sys">
|
||||||
|
<include base="ndisuio">.</include>
|
||||||
|
<include base="ReactOS">include/reactos/drivers/ndisuio</include>
|
||||||
|
<define name="NDIS50" />
|
||||||
|
<define name="_NTDRIVER_" />
|
||||||
|
<library>ndis</library>
|
||||||
|
<library>ntoskrnl</library>
|
||||||
|
<library>hal</library>
|
||||||
|
<pch>ndisuio.h</pch>
|
||||||
|
<file>createclose.c</file>
|
||||||
|
<file>ioctl.c</file>
|
||||||
|
<file>main.c</file>
|
||||||
|
<file>misc.c</file>
|
||||||
|
<file>protocol.c</file>
|
||||||
|
<file>readwrite.c</file>
|
||||||
|
<file>ndisuio.rc</file>
|
||||||
|
</module>
|
5
reactos/drivers/network/ndisuio/ndisuio.rc
Normal file
5
reactos/drivers/network/ndisuio/ndisuio.rc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#define REACTOS_VERSION_DLL
|
||||||
|
#define REACTOS_STR_FILE_DESCRIPTION "NDIS User-Mode I/O Protocol Driver\0"
|
||||||
|
#define REACTOS_STR_INTERNAL_NAME "ndisuio\0"
|
||||||
|
#define REACTOS_STR_ORIGINAL_FILENAME "ndisuio.sys\0"
|
||||||
|
#include <reactos/version.rc>
|
496
reactos/drivers/network/ndisuio/protocol.c
Normal file
496
reactos/drivers/network/ndisuio/protocol.c
Normal file
|
@ -0,0 +1,496 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: protocol.c
|
||||||
|
* PURPOSE: Protocol stuff
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduOpenAdapterComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status,
|
||||||
|
NDIS_STATUS OpenStatus)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter open completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduCloseAdapterComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter close completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduSendComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_PACKET Packet,
|
||||||
|
NDIS_STATUS Status)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter send completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_PACKET Packet,
|
||||||
|
NDIS_STATUS Status,
|
||||||
|
UINT BytesTransferred)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter transfer completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduResetComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS Status)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter reset completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduRequestComplete(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
PNDIS_REQUEST NdisRequest,
|
||||||
|
NDIS_STATUS Status)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
|
||||||
|
DPRINT("Asynchronous adapter request completed\n");
|
||||||
|
|
||||||
|
/* Store the final status and signal the event */
|
||||||
|
AdapterContext->AsyncStatus = Status;
|
||||||
|
KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
NTAPI
|
||||||
|
NduReceive(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_HANDLE MacReceiveContext,
|
||||||
|
PVOID HeaderBuffer,
|
||||||
|
UINT HeaderBufferSize,
|
||||||
|
PVOID LookAheadBuffer,
|
||||||
|
UINT LookaheadBufferSize,
|
||||||
|
UINT PacketSize)
|
||||||
|
{
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
|
||||||
|
PNDISUIO_PACKET_ENTRY PacketEntry;
|
||||||
|
PVOID PacketBuffer;
|
||||||
|
PNDIS_PACKET Packet;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
UINT BytesTransferred;
|
||||||
|
|
||||||
|
DPRINT("Received a %d byte packet\n", PacketSize);
|
||||||
|
|
||||||
|
/* Discard if nobody is waiting for it */
|
||||||
|
if (AdapterContext->OpenCount == 0)
|
||||||
|
return NDIS_STATUS_NOT_ACCEPTED;
|
||||||
|
|
||||||
|
/* Allocate a buffer to hold the packet data and header */
|
||||||
|
PacketBuffer = ExAllocatePool(NonPagedPool, PacketSize + HeaderBufferSize);
|
||||||
|
if (!PacketBuffer)
|
||||||
|
return NDIS_STATUS_NOT_ACCEPTED;
|
||||||
|
|
||||||
|
/* Allocate the packet descriptor and buffer */
|
||||||
|
Packet = CreatePacketFromPoolBuffer(AdapterContext,
|
||||||
|
(PUCHAR)PacketBuffer + HeaderBufferSize,
|
||||||
|
PacketSize);
|
||||||
|
if (!Packet)
|
||||||
|
{
|
||||||
|
ExFreePool(PacketBuffer);
|
||||||
|
return NDIS_STATUS_NOT_ACCEPTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Transfer the packet data into our data buffer */
|
||||||
|
if (LookaheadBufferSize == PacketSize)
|
||||||
|
{
|
||||||
|
NdisCopyLookaheadData((PVOID)((PUCHAR)PacketBuffer + HeaderBufferSize),
|
||||||
|
LookAheadBuffer,
|
||||||
|
PacketSize,
|
||||||
|
AdapterContext->MacOptions);
|
||||||
|
BytesTransferred = PacketSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NdisTransferData(&Status,
|
||||||
|
AdapterContext->BindingHandle,
|
||||||
|
MacReceiveContext,
|
||||||
|
0,
|
||||||
|
PacketSize,
|
||||||
|
Packet,
|
||||||
|
&BytesTransferred);
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to transfer data with status 0x%x\n", Status);
|
||||||
|
CleanupAndFreePacket(Packet, TRUE);
|
||||||
|
return NDIS_STATUS_NOT_ACCEPTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the header data */
|
||||||
|
RtlCopyMemory(PacketBuffer, HeaderBuffer, HeaderBufferSize);
|
||||||
|
|
||||||
|
/* Free the packet descriptor and buffers
|
||||||
|
but not the pool because we still need it */
|
||||||
|
CleanupAndFreePacket(Packet, FALSE);
|
||||||
|
|
||||||
|
/* Allocate a packet entry from pool */
|
||||||
|
PacketEntry = ExAllocatePool(NonPagedPool, sizeof(NDISUIO_PACKET_ENTRY) + BytesTransferred + HeaderBufferSize - 1);
|
||||||
|
if (!PacketEntry)
|
||||||
|
{
|
||||||
|
ExFreePool(PacketBuffer);
|
||||||
|
return NDIS_STATUS_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the packet entry and copy in packet data */
|
||||||
|
PacketEntry->PacketLength = BytesTransferred + HeaderBufferSize;
|
||||||
|
RtlCopyMemory(PacketEntry->PacketData, PacketBuffer, PacketEntry->PacketLength);
|
||||||
|
|
||||||
|
/* Free the old buffer */
|
||||||
|
ExFreePool(PacketBuffer);
|
||||||
|
|
||||||
|
/* Insert the packet on the adapter's packet list */
|
||||||
|
ExInterlockedInsertTailList(&AdapterContext->PacketList,
|
||||||
|
&PacketEntry->ListEntry,
|
||||||
|
&AdapterContext->Spinlock);
|
||||||
|
|
||||||
|
/* Signal the read event */
|
||||||
|
KeSetEvent(&AdapterContext->PacketReadEvent,
|
||||||
|
IO_NETWORK_INCREMENT,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
return NDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext)
|
||||||
|
{
|
||||||
|
/* No op */
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduStatus(NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_STATUS GeneralStatus,
|
||||||
|
PVOID StatusBuffer,
|
||||||
|
UINT StatusBufferSize)
|
||||||
|
{
|
||||||
|
/* FIXME: Implement status tracking */
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduStatusComplete(NDIS_HANDLE ProtocolBindingContext)
|
||||||
|
{
|
||||||
|
/* FIXME: Implement status tracking */
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NDIS_STATUS
|
||||||
|
UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql;
|
||||||
|
PLIST_ENTRY CurrentEntry;
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry;
|
||||||
|
PNDISUIO_PACKET_ENTRY PacketEntry;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
|
||||||
|
DPRINT("Unbinding adapter %wZ\n", &AdapterContext->DeviceName);
|
||||||
|
|
||||||
|
/* FIXME: We don't do anything with outstanding reads */
|
||||||
|
|
||||||
|
/* Remove the adapter context from the global list */
|
||||||
|
KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
|
||||||
|
RemoveEntryList(&AdapterContext->ListEntry);
|
||||||
|
KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
|
||||||
|
|
||||||
|
/* Free the device name string */
|
||||||
|
RtlFreeUnicodeString(&AdapterContext->DeviceName);
|
||||||
|
|
||||||
|
/* Invalidate all handles to this adapter */
|
||||||
|
CurrentEntry = AdapterContext->OpenEntryList.Flink;
|
||||||
|
while (CurrentEntry != &AdapterContext->OpenEntryList)
|
||||||
|
{
|
||||||
|
OpenEntry = CONTAINING_RECORD(CurrentEntry, NDISUIO_OPEN_ENTRY, ListEntry);
|
||||||
|
|
||||||
|
/* Make sure the entry is sane */
|
||||||
|
ASSERT(OpenEntry->FileObject);
|
||||||
|
|
||||||
|
/* Remove the adapter context pointer */
|
||||||
|
ASSERT(AdapterContext == OpenEntry->FileObject->FsContext);
|
||||||
|
OpenEntry->FileObject->FsContext = NULL;
|
||||||
|
AdapterContext->OpenCount--;
|
||||||
|
|
||||||
|
/* Remove the open entry pointer */
|
||||||
|
ASSERT(OpenEntry == OpenEntry->FileObject->FsContext2);
|
||||||
|
OpenEntry->FileObject->FsContext2 = NULL;
|
||||||
|
|
||||||
|
/* Move to the next entry */
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
|
||||||
|
/* Free the open entry */
|
||||||
|
ExFreePool(OpenEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this fails, we have a refcount mismatch somewhere */
|
||||||
|
ASSERT(AdapterContext->OpenCount == 0);
|
||||||
|
|
||||||
|
/* Free all pending packet entries */
|
||||||
|
CurrentEntry = AdapterContext->PacketList.Flink;
|
||||||
|
while (CurrentEntry != &AdapterContext->PacketList)
|
||||||
|
{
|
||||||
|
PacketEntry = CONTAINING_RECORD(CurrentEntry, NDISUIO_PACKET_ENTRY, ListEntry);
|
||||||
|
|
||||||
|
/* Move to the next entry */
|
||||||
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
|
|
||||||
|
/* Free the packet entry */
|
||||||
|
ExFreePool(PacketEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the close request */
|
||||||
|
NdisCloseAdapter(&Status,
|
||||||
|
AdapterContext->BindingHandle);
|
||||||
|
|
||||||
|
/* Wait for a pending close */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the context */
|
||||||
|
ExFreePool(AdapterContext);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NDIS_STATUS
|
||||||
|
BindAdapterByName(PNDIS_STRING DeviceName)
|
||||||
|
{
|
||||||
|
NDIS_STATUS OpenErrorStatus;
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext;
|
||||||
|
NDIS_MEDIUM SupportedMedia[1] = {NdisMedium802_3};
|
||||||
|
UINT SelectedMedium;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
NDIS_REQUEST Request;
|
||||||
|
|
||||||
|
/* Allocate the adapter context */
|
||||||
|
AdapterContext = ExAllocatePool(NonPagedPool, sizeof(*AdapterContext));
|
||||||
|
if (!AdapterContext)
|
||||||
|
{
|
||||||
|
return NDIS_STATUS_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the adapter context */
|
||||||
|
RtlZeroMemory(AdapterContext, sizeof(*AdapterContext));
|
||||||
|
KeInitializeEvent(&AdapterContext->AsyncEvent, SynchronizationEvent, FALSE);
|
||||||
|
KeInitializeEvent(&AdapterContext->PacketReadEvent, SynchronizationEvent, FALSE);
|
||||||
|
KeInitializeSpinLock(&AdapterContext->Spinlock);
|
||||||
|
InitializeListHead(&AdapterContext->PacketList);
|
||||||
|
InitializeListHead(&AdapterContext->OpenEntryList);
|
||||||
|
AdapterContext->OpenCount = 0;
|
||||||
|
|
||||||
|
AdapterContext->DeviceName.Length =
|
||||||
|
AdapterContext->DeviceName.MaximumLength = DeviceName->Length;
|
||||||
|
AdapterContext->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceName->Length);
|
||||||
|
if (!AdapterContext->DeviceName.Buffer)
|
||||||
|
{
|
||||||
|
ExFreePool(AdapterContext);
|
||||||
|
return NDIS_STATUS_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the device name into the adapter context */
|
||||||
|
RtlCopyMemory(AdapterContext->DeviceName.Buffer, DeviceName->Buffer, DeviceName->Length);
|
||||||
|
|
||||||
|
DPRINT("Binding adapter %wZ\n", &AdapterContext->DeviceName);
|
||||||
|
|
||||||
|
/* Create the buffer pool */
|
||||||
|
NdisAllocateBufferPool(&Status,
|
||||||
|
&AdapterContext->BufferPoolHandle,
|
||||||
|
50);
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to allocate buffer pool with status 0x%x\n", Status);
|
||||||
|
RtlFreeUnicodeString(&AdapterContext->DeviceName);
|
||||||
|
ExFreePool(AdapterContext);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the packet pool */
|
||||||
|
NdisAllocatePacketPool(&Status,
|
||||||
|
&AdapterContext->PacketPoolHandle,
|
||||||
|
25,
|
||||||
|
PROTOCOL_RESERVED_SIZE_IN_PACKET);
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to allocate packet pool with status 0x%x\n", Status);
|
||||||
|
NdisFreeBufferPool(AdapterContext->BufferPoolHandle);
|
||||||
|
RtlFreeUnicodeString(&AdapterContext->DeviceName);
|
||||||
|
ExFreePool(AdapterContext);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the open request */
|
||||||
|
NdisOpenAdapter(&Status,
|
||||||
|
&OpenErrorStatus,
|
||||||
|
&AdapterContext->BindingHandle,
|
||||||
|
&SelectedMedium,
|
||||||
|
SupportedMedia,
|
||||||
|
1,
|
||||||
|
GlobalProtocolHandle,
|
||||||
|
AdapterContext,
|
||||||
|
DeviceName,
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* Wait for a pending open */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the final status */
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status);
|
||||||
|
NdisFreePacketPool(AdapterContext->PacketPoolHandle);
|
||||||
|
NdisFreeBufferPool(AdapterContext->BufferPoolHandle);
|
||||||
|
RtlFreeUnicodeString(&AdapterContext->DeviceName);
|
||||||
|
ExFreePool(AdapterContext);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the MAC options */
|
||||||
|
Request.RequestType = NdisRequestQueryInformation;
|
||||||
|
Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS;
|
||||||
|
Request.DATA.QUERY_INFORMATION.InformationBuffer = &AdapterContext->MacOptions;
|
||||||
|
Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(ULONG);
|
||||||
|
NdisRequest(&Status,
|
||||||
|
AdapterContext->BindingHandle,
|
||||||
|
&Request);
|
||||||
|
|
||||||
|
/* Wait for a pending request */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the final status */
|
||||||
|
if (Status != NDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
NDIS_STATUS CloseStatus;
|
||||||
|
|
||||||
|
DPRINT1("Failed to get MAC options with status 0x%x\n", Status);
|
||||||
|
|
||||||
|
NdisCloseAdapter(&CloseStatus,
|
||||||
|
AdapterContext->BindingHandle);
|
||||||
|
if (CloseStatus == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
NdisFreePacketPool(AdapterContext->PacketPoolHandle);
|
||||||
|
NdisFreeBufferPool(AdapterContext->BufferPoolHandle);
|
||||||
|
RtlFreeUnicodeString(&AdapterContext->DeviceName);
|
||||||
|
ExFreePool(AdapterContext);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the adapter context to the global list */
|
||||||
|
ExInterlockedInsertTailList(&GlobalAdapterList,
|
||||||
|
&AdapterContext->ListEntry,
|
||||||
|
&GlobalAdapterListLock);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduBindAdapter(PNDIS_STATUS Status,
|
||||||
|
NDIS_HANDLE BindContext,
|
||||||
|
PNDIS_STRING DeviceName,
|
||||||
|
PVOID SystemSpecific1,
|
||||||
|
PVOID SystemSpecific2)
|
||||||
|
{
|
||||||
|
/* Use our helper function to create a context for this adapter */
|
||||||
|
*Status = BindAdapterByName(DeviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
NduUnbindAdapter(PNDIS_STATUS Status,
|
||||||
|
NDIS_HANDLE ProtocolBindingContext,
|
||||||
|
NDIS_HANDLE UnbindContext)
|
||||||
|
{
|
||||||
|
/* This is forced unbind. UnbindAdapterByContext() will take care of
|
||||||
|
* invalidating file handles pointer to this adapter for us */
|
||||||
|
*Status = UnbindAdapterByContext(ProtocolBindingContext);
|
||||||
|
}
|
||||||
|
|
209
reactos/drivers/network/ndisuio/readwrite.c
Normal file
209
reactos/drivers/network/ndisuio/readwrite.c
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS NDIS User I/O driver
|
||||||
|
* FILE: readwrite.c
|
||||||
|
* PURPOSE: Handles IRP_MJ_READ and IRP_MJ_WRITE
|
||||||
|
* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ndisuio.h"
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
ReadIrpCancel(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_PACKET_ENTRY PacketEntry;
|
||||||
|
|
||||||
|
/* Release the cancel spin lock */
|
||||||
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
||||||
|
|
||||||
|
/* Indicate a 0-byte packet on the queue to cancel the read */
|
||||||
|
PacketEntry = ExAllocatePool(NonPagedPool, sizeof(NDISUIO_PACKET_ENTRY));
|
||||||
|
if (PacketEntry)
|
||||||
|
{
|
||||||
|
PacketEntry->PacketLength = 0;
|
||||||
|
|
||||||
|
ExInterlockedInsertHeadList(&AdapterContext->PacketList,
|
||||||
|
&PacketEntry->ListEntry,
|
||||||
|
&AdapterContext->Spinlock);
|
||||||
|
|
||||||
|
KeSetEvent(&AdapterContext->PacketReadEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchRead(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDISUIO_OPEN_ENTRY OpenEntry = IrpSp->FileObject->FsContext2;
|
||||||
|
KIRQL OldIrql, OldCancelIrql;
|
||||||
|
NTSTATUS Status;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
PNDISUIO_PACKET_ENTRY PacketEntry = NULL;
|
||||||
|
ULONG BytesCopied = 0;
|
||||||
|
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
if (OpenEntry->WriteOnly)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make the read cancellable */
|
||||||
|
IoAcquireCancelSpinLock(&OldCancelIrql);
|
||||||
|
IoSetCancelRoutine(Irp, ReadIrpCancel);
|
||||||
|
if (Irp->Cancel)
|
||||||
|
{
|
||||||
|
IoReleaseCancelSpinLock(OldCancelIrql);
|
||||||
|
|
||||||
|
/* Indicate a 0 byte read */
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
IoReleaseCancelSpinLock(OldCancelIrql);
|
||||||
|
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
|
||||||
|
|
||||||
|
/* Check if we have a packet */
|
||||||
|
if (IsListEmpty(&AdapterContext->PacketList))
|
||||||
|
{
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
|
||||||
|
/* Wait for a packet (in the context of the calling user thread) */
|
||||||
|
Status = KeWaitForSingleObject(&AdapterContext->PacketReadEvent,
|
||||||
|
UserRequest,
|
||||||
|
UserMode,
|
||||||
|
TRUE,
|
||||||
|
NULL);
|
||||||
|
if (Status != STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Remove the cancel routine */
|
||||||
|
IoAcquireCancelSpinLock(&OldCancelIrql);
|
||||||
|
IoSetCancelRoutine(Irp, NULL);
|
||||||
|
IoReleaseCancelSpinLock(OldCancelIrql);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Remove the cancel routine */
|
||||||
|
IoAcquireCancelSpinLock(&OldCancelIrql);
|
||||||
|
IoSetCancelRoutine(Irp, NULL);
|
||||||
|
IoReleaseCancelSpinLock(OldCancelIrql);
|
||||||
|
|
||||||
|
/* Remove the first packet in the list */
|
||||||
|
ListEntry = RemoveHeadList(&AdapterContext->PacketList);
|
||||||
|
PacketEntry = CONTAINING_RECORD(ListEntry, NDISUIO_PACKET_ENTRY, ListEntry);
|
||||||
|
|
||||||
|
/* Release the adapter lock */
|
||||||
|
KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
|
||||||
|
|
||||||
|
/* And we're done with this loop */
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we got a packet */
|
||||||
|
if (PacketEntry != NULL)
|
||||||
|
{
|
||||||
|
/* Find the right amount of bytes to copy */
|
||||||
|
BytesCopied = PacketEntry->PacketLength;
|
||||||
|
if (BytesCopied > IrpSp->Parameters.Read.Length)
|
||||||
|
BytesCopied = IrpSp->Parameters.Read.Length;
|
||||||
|
|
||||||
|
/* Copy the packet */
|
||||||
|
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,
|
||||||
|
&PacketEntry->PacketData[0],
|
||||||
|
BytesCopied);
|
||||||
|
|
||||||
|
/* Free the packet entry */
|
||||||
|
ExFreePool(PacketEntry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Something failed */
|
||||||
|
BytesCopied = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complete the IRP */
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = BytesCopied;
|
||||||
|
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NduDispatchWrite(PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
|
||||||
|
PNDIS_PACKET Packet;
|
||||||
|
NDIS_STATUS Status;
|
||||||
|
ULONG BytesCopied = 0;
|
||||||
|
|
||||||
|
ASSERT(DeviceObject == GlobalDeviceObject);
|
||||||
|
|
||||||
|
/* Create a packet and buffer descriptor for this user buffer */
|
||||||
|
Packet = CreatePacketFromPoolBuffer(AdapterContext,
|
||||||
|
Irp->AssociatedIrp.SystemBuffer,
|
||||||
|
IrpSp->Parameters.Write.Length);
|
||||||
|
if (Packet)
|
||||||
|
{
|
||||||
|
/* Send it via NDIS */
|
||||||
|
NdisSend(&Status,
|
||||||
|
AdapterContext->BindingHandle,
|
||||||
|
Packet);
|
||||||
|
|
||||||
|
/* Wait for the send */
|
||||||
|
if (Status == NDIS_STATUS_PENDING)
|
||||||
|
{
|
||||||
|
KeWaitForSingleObject(&AdapterContext->AsyncEvent,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
Status = AdapterContext->AsyncStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if it succeeded */
|
||||||
|
if (Status == NDIS_STATUS_SUCCESS)
|
||||||
|
BytesCopied = IrpSp->Parameters.Write.Length;
|
||||||
|
|
||||||
|
CleanupAndFreePacket(Packet, FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No memory */
|
||||||
|
Status = STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complete the IRP */
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = BytesCopied;
|
||||||
|
IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
|
@ -42,6 +42,22 @@ typedef enum _NDIS_DEVICE_POWER_STATE {
|
||||||
NdisDeviceStateMaximum
|
NdisDeviceStateMaximum
|
||||||
} NDIS_DEVICE_POWER_STATE, *PNDIS_DEVICE_POWER_STATE;
|
} NDIS_DEVICE_POWER_STATE, *PNDIS_DEVICE_POWER_STATE;
|
||||||
|
|
||||||
|
typedef enum _NDIS_802_11_WEP_STATUS
|
||||||
|
{
|
||||||
|
Ndis802_11WEPEnabled,
|
||||||
|
Ndis802_11WEPDisabled,
|
||||||
|
Ndis802_11WEPKeyAbsent,
|
||||||
|
Ndis802_11WEPNotSupported
|
||||||
|
} NDIS_802_11_WEP_STATUS, *PNDIS_802_11_WEP_STATUS;
|
||||||
|
|
||||||
|
typedef enum _NDIS_802_11_AUTHENTICATION_MODE
|
||||||
|
{
|
||||||
|
Ndis802_11AuthModeOpen,
|
||||||
|
Ndis802_11AuthModeShared,
|
||||||
|
Ndis802_11AuthModeAutoSwitch,
|
||||||
|
Ndis802_11AuthModeMax
|
||||||
|
} NDIS_802_11_AUTHENTICATION_MODE, *PNDIS_802_11_AUTHENTICATION_MODE;
|
||||||
|
|
||||||
typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE
|
typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE
|
||||||
{
|
{
|
||||||
Ndis802_11IBSS,
|
Ndis802_11IBSS,
|
||||||
|
@ -117,6 +133,14 @@ typedef struct _NDIS_802_11_BSSID_LIST
|
||||||
NDIS_WLAN_BSSID Bssid[1];
|
NDIS_WLAN_BSSID Bssid[1];
|
||||||
} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST;
|
} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST;
|
||||||
|
|
||||||
|
typedef struct _NDIS_802_11_WEP
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
ULONG KeyIndex;
|
||||||
|
ULONG KeyLength;
|
||||||
|
UCHAR KeyMaterial[1];
|
||||||
|
} NDIS_802_11_WEP, *PNDIS_802_11_WEP;
|
||||||
|
|
||||||
typedef struct _NDIS_PM_WAKE_UP_CAPABILITIES {
|
typedef struct _NDIS_PM_WAKE_UP_CAPABILITIES {
|
||||||
NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
|
NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
|
||||||
NDIS_DEVICE_POWER_STATE MinPatternWakeUp;
|
NDIS_DEVICE_POWER_STATE MinPatternWakeUp;
|
||||||
|
@ -265,8 +289,34 @@ typedef ULONG NDIS_OID, *PNDIS_OID;
|
||||||
#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
|
#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
|
||||||
#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
|
#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
|
||||||
|
|
||||||
#define OID_802_11_BSSID_LIST 0x0D010217
|
/* IEEE 802.11 (WLAN) OIDs */
|
||||||
#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A
|
#define OID_802_11_BSSID 0x0D010101
|
||||||
|
#define OID_802_11_SSID 0x0D010102
|
||||||
|
#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0D010203
|
||||||
|
#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204
|
||||||
|
#define OID_802_11_TX_POWER_LEVEL 0x0D010205
|
||||||
|
#define OID_802_11_RSSI 0x0D010206
|
||||||
|
#define OID_802_11_RSSI_TRIGGER 0x0D010207
|
||||||
|
#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108
|
||||||
|
#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0D010209
|
||||||
|
#define OID_802_11_RTS_THRESHOLD 0x0D01020A
|
||||||
|
#define OID_802_11_NUMBER_OF_ANTENNAS 0x0D01020B
|
||||||
|
#define OID_802_11_RX_ANTENNA_SELECTED 0x0D01020C
|
||||||
|
#define OID_802_11_TX_ANTENNA_SELECTED 0x0D01020D
|
||||||
|
#define OID_802_11_SUPPORTED_RATES 0x0D01020E
|
||||||
|
#define OID_802_11_DESIRED_RATES 0x0D010210
|
||||||
|
#define OID_802_11_CONFIGURATION 0x0D010211
|
||||||
|
#define OID_802_11_STATISTICS 0x0D020212
|
||||||
|
#define OID_802_11_ADD_WEP 0x0D010113
|
||||||
|
#define OID_802_11_REMOVE_WEP 0x0D010114
|
||||||
|
#define OID_802_11_DISASSOCIATE 0x0D010115
|
||||||
|
#define OID_802_11_POWER_MODE 0x0D010216
|
||||||
|
#define OID_802_11_BSSID_LIST 0x0D010217
|
||||||
|
#define OID_802_11_AUTHENTICATION_MODE 0x0D010118
|
||||||
|
#define OID_802_11_PRIVACY_FILTER 0x0D010119
|
||||||
|
#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A
|
||||||
|
#define OID_802_11_WEP_STATUS 0x0D01011B
|
||||||
|
#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C
|
||||||
|
|
||||||
/* OID_GEN_MINIPORT_INFO constants */
|
/* OID_GEN_MINIPORT_INFO constants */
|
||||||
#define NDIS_MINIPORT_BUS_MASTER 0x00000001
|
#define NDIS_MINIPORT_BUS_MASTER 0x00000001
|
||||||
|
|
59
reactos/include/reactos/drivers/ndisuio/nuiouser.h
Executable file
59
reactos/include/reactos/drivers/ndisuio/nuiouser.h
Executable file
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef __NUIOUSER_H
|
||||||
|
#define __NUIOUSER_H
|
||||||
|
|
||||||
|
/* Device names (NT and DOS style) */
|
||||||
|
#define NDISUIO_DEVICE_NAME_NT L"\\Device\\Ndisuio"
|
||||||
|
#define NDISUIO_DEVICE_NAME_DOS L"\\DosDevices\\Ndisuio"
|
||||||
|
|
||||||
|
/* Device name for user apps */
|
||||||
|
#define NDISUIO_DEVICE_NAME L"\\\\.\\\\Ndisuio"
|
||||||
|
|
||||||
|
/* Links a file handle with a bound NIC */
|
||||||
|
#define IOCTL_NDISUIO_OPEN_DEVICE \
|
||||||
|
CTL_CODE(FILE_DEVICE_NETWORK, 0x200, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
/* Queries an OID for the bound NIC */
|
||||||
|
#define IOCTL_NDISUIO_QUERY_OID_VALUE \
|
||||||
|
CTL_CODE(FILE_DEVICE_NETWORK, 0x201, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
#define IOCTL_NDISUIO_SET_ETHER_TYPE \
|
||||||
|
CTL_CODE(FILE_DEVICE_NETWORK, 0x202, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
/* Queries binding information during enumeration */
|
||||||
|
#define IOCTL_NDISUIO_QUERY_BINDING \
|
||||||
|
CTL_CODE(FILE_DEVICE_NETWORK, 0x203, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
/* Waits for any pending bindings */
|
||||||
|
#define IOCTL_NDISUIO_BIND_WAIT \
|
||||||
|
CTL_CODE(FILE_DEVICE_NETWORK, 0x204, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
/* Sets an OID for a bound NIC */
|
||||||
|
#define IOCTL_NDISUIO_SET_OID_VALUE \
|
||||||
|
CTL_CODE(FILE_DEVICE_NETWORK, 0x205, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
/* Passed as a parameter to IOCTL_NDISUIO_QUERY_OID_VALUE */
|
||||||
|
typedef struct _NDISUIO_QUERY_OID
|
||||||
|
{
|
||||||
|
NDIS_OID Oid;
|
||||||
|
UCHAR Data[sizeof(ULONG)];
|
||||||
|
} NDISUIO_QUERY_OID, *PNDISUIO_QUERY_OID;
|
||||||
|
|
||||||
|
/* Passed as a parameter to IOCTL_NDISUIO_SET_OID_VALUE */
|
||||||
|
typedef struct _NDISUIO_SET_OID
|
||||||
|
{
|
||||||
|
NDIS_OID Oid;
|
||||||
|
UCHAR Data[sizeof(ULONG)];
|
||||||
|
} NDISUIO_SET_OID, *PNDISUIO_SET_OID;
|
||||||
|
|
||||||
|
/* Passed as a parameter to IOCTL_NDISUIO_QUERY_BINDING */
|
||||||
|
typedef struct _NDISUIO_QUERY_BINDING
|
||||||
|
{
|
||||||
|
ULONG BindingIndex;
|
||||||
|
ULONG DeviceNameOffset;
|
||||||
|
ULONG DeviceNameLength;
|
||||||
|
ULONG DeviceDescrOffset;
|
||||||
|
ULONG DeviceDescrLength;
|
||||||
|
} NDISUIO_QUERY_BINDING, *PNDISUIO_QUERY_BINDING;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue