mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:23:05 +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()
|
||||
add_subdirectory(tracert)
|
||||
add_subdirectory(whois)
|
||||
add_subdirectory(wlanconf)
|
||||
|
||||
|
|
|
@ -40,4 +40,7 @@
|
|||
<directory name="whois">
|
||||
<xi:include href="whois/whois.rbuild" />
|
||||
</directory>
|
||||
<directory name="wlanconf">
|
||||
<xi:include href="wlanconf/wlanconf.rbuild" />
|
||||
</directory>
|
||||
</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","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
|
||||
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ErrorControl",0x00010001,0x00000001
|
||||
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","ImagePath",0x00020000,"%SystemRoot%\system32\wlansvc.exe"
|
||||
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
|
||||
|
||||
; Simple TCP services
|
||||
|
|
|
@ -76,6 +76,7 @@ base\applications\network\route\route.exe 1
|
|||
base\applications\network\telnet\telnet.exe 1
|
||||
base\applications\network\tracert\tracert.exe 1
|
||||
base\applications\network\whois\whois.exe 1
|
||||
base\applications\network\wlanconf\wlanconf.exe 1
|
||||
base\applications\notepad\notepad.exe 1
|
||||
base\applications\rapps\rapps.exe 1
|
||||
base\applications\regedit\regedit.exe 4
|
||||
|
@ -532,6 +533,7 @@ drivers\network\tcpip\tcpip.sys 2
|
|||
drivers\network\tdi\tdi.sys 2
|
||||
drivers\network\dd\ne2000\ne2000.sys 2
|
||||
drivers\network\dd\pcnet\pcnet.sys 2
|
||||
drivers\network\ndisuio\ndisuio.sys 2
|
||||
|
||||
drivers\serial\serenum\serenum.sys 2
|
||||
drivers\serial\serial\serial.sys 2
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
add_subdirectory(afd)
|
||||
add_subdirectory(dd)
|
||||
add_subdirectory(ndis)
|
||||
add_subdirectory(ndisuio)
|
||||
add_subdirectory(tcpip)
|
||||
add_subdirectory(tdi)
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
<directory name="ndis">
|
||||
<xi:include href="ndis/ndis.rbuild" />
|
||||
</directory>
|
||||
<directory name="ndisuio">
|
||||
<xi:include href="ndisuio/ndisuio.rbuild" />
|
||||
</directory>
|
||||
<directory name="tcpip">
|
||||
<xi:include href="tcpip/tcpip.rbuild" />
|
||||
</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
|
||||
} 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
|
||||
{
|
||||
Ndis802_11IBSS,
|
||||
|
@ -117,6 +133,14 @@ typedef struct _NDIS_802_11_BSSID_LIST
|
|||
NDIS_WLAN_BSSID Bssid[1];
|
||||
} 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 {
|
||||
NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp;
|
||||
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_LATE_COLLISIONS 0x01020207
|
||||
|
||||
/* IEEE 802.11 (WLAN) OIDs */
|
||||
#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 */
|
||||
#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