diff --git a/reactos/base/applications/network/CMakeLists.txt b/reactos/base/applications/network/CMakeLists.txt index 02eb61db45a..b7f2d0ea652 100644 --- a/reactos/base/applications/network/CMakeLists.txt +++ b/reactos/base/applications/network/CMakeLists.txt @@ -14,3 +14,5 @@ if(NOT MSVC) endif() add_subdirectory(tracert) add_subdirectory(whois) +add_subdirectory(wlanconf) + diff --git a/reactos/base/applications/network/network.rbuild b/reactos/base/applications/network/network.rbuild index 61109ec8bd7..13b9a537328 100644 --- a/reactos/base/applications/network/network.rbuild +++ b/reactos/base/applications/network/network.rbuild @@ -40,4 +40,7 @@ + + + diff --git a/reactos/base/applications/network/wlanconf/CMakeLists.txt b/reactos/base/applications/network/wlanconf/CMakeLists.txt new file mode 100644 index 00000000000..35938d4bcd4 --- /dev/null +++ b/reactos/base/applications/network/wlanconf/CMakeLists.txt @@ -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) diff --git a/reactos/base/applications/network/wlanconf/wlanconf.c b/reactos/base/applications/network/wlanconf/wlanconf.c new file mode 100644 index 00000000000..15e351de6cd --- /dev/null +++ b/reactos/base/applications/network/wlanconf/wlanconf.c @@ -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 +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/reactos/base/applications/network/wlanconf/wlanconf.rbuild b/reactos/base/applications/network/wlanconf/wlanconf.rbuild new file mode 100644 index 00000000000..9658c2826eb --- /dev/null +++ b/reactos/base/applications/network/wlanconf/wlanconf.rbuild @@ -0,0 +1,9 @@ + + + + . + include/reactos/drivers/ndisuio + iphlpapi + wlanconf.c + wlanconf.rc + diff --git a/reactos/base/applications/network/wlanconf/wlanconf.rc b/reactos/base/applications/network/wlanconf/wlanconf.rc new file mode 100644 index 00000000000..78b2584976d --- /dev/null +++ b/reactos/base/applications/network/wlanconf/wlanconf.rc @@ -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 + + diff --git a/reactos/boot/bootdata/hivesys_i386.inf b/reactos/boot/bootdata/hivesys_i386.inf index 368733acfd9..97d40aeb7a1 100644 --- a/reactos/boot/bootdata/hivesys_i386.inf +++ b/reactos/boot/bootdata/hivesys_i386.inf @@ -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 diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index c68046d8e59..22127862008 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -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 diff --git a/reactos/drivers/network/CMakeLists.txt b/reactos/drivers/network/CMakeLists.txt index 88521cab276..abffd627bb7 100644 --- a/reactos/drivers/network/CMakeLists.txt +++ b/reactos/drivers/network/CMakeLists.txt @@ -2,5 +2,6 @@ add_subdirectory(afd) add_subdirectory(dd) add_subdirectory(ndis) +add_subdirectory(ndisuio) add_subdirectory(tcpip) add_subdirectory(tdi) diff --git a/reactos/drivers/network/directory.rbuild b/reactos/drivers/network/directory.rbuild index 2a62dbd7fbf..76df85538ab 100644 --- a/reactos/drivers/network/directory.rbuild +++ b/reactos/drivers/network/directory.rbuild @@ -10,6 +10,9 @@ + + + diff --git a/reactos/drivers/network/ndisuio/CMakeLists.txt b/reactos/drivers/network/ndisuio/CMakeLists.txt new file mode 100644 index 00000000000..3ab2f938f5e --- /dev/null +++ b/reactos/drivers/network/ndisuio/CMakeLists.txt @@ -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) diff --git a/reactos/drivers/network/ndisuio/createclose.c b/reactos/drivers/network/ndisuio/createclose.c new file mode 100644 index 00000000000..d0fe7af9fb6 --- /dev/null +++ b/reactos/drivers/network/ndisuio/createclose.c @@ -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 + +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; +} \ No newline at end of file diff --git a/reactos/drivers/network/ndisuio/ioctl.c b/reactos/drivers/network/ndisuio/ioctl.c new file mode 100644 index 00000000000..74070d60e70 --- /dev/null +++ b/reactos/drivers/network/ndisuio/ioctl.c @@ -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 + +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; + } +} diff --git a/reactos/drivers/network/ndisuio/main.c b/reactos/drivers/network/ndisuio/main.c new file mode 100644 index 00000000000..07567770240 --- /dev/null +++ b/reactos/drivers/network/ndisuio/main.c @@ -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 + +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; +} diff --git a/reactos/drivers/network/ndisuio/misc.c b/reactos/drivers/network/ndisuio/misc.c new file mode 100644 index 00000000000..43552cb9fa0 --- /dev/null +++ b/reactos/drivers/network/ndisuio/misc.c @@ -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 + +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); +} diff --git a/reactos/drivers/network/ndisuio/ndisuio.h b/reactos/drivers/network/ndisuio/ndisuio.h new file mode 100644 index 00000000000..13f6d919239 --- /dev/null +++ b/reactos/drivers/network/ndisuio/ndisuio.h @@ -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 +#include +#include + +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 */ diff --git a/reactos/drivers/network/ndisuio/ndisuio.rbuild b/reactos/drivers/network/ndisuio/ndisuio.rbuild new file mode 100644 index 00000000000..1ba528ec747 --- /dev/null +++ b/reactos/drivers/network/ndisuio/ndisuio.rbuild @@ -0,0 +1,19 @@ + + + + . + include/reactos/drivers/ndisuio + + + ndis + ntoskrnl + hal + ndisuio.h + createclose.c + ioctl.c + main.c + misc.c + protocol.c + readwrite.c + ndisuio.rc + diff --git a/reactos/drivers/network/ndisuio/ndisuio.rc b/reactos/drivers/network/ndisuio/ndisuio.rc new file mode 100644 index 00000000000..bf0e8f4c7ae --- /dev/null +++ b/reactos/drivers/network/ndisuio/ndisuio.rc @@ -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 diff --git a/reactos/drivers/network/ndisuio/protocol.c b/reactos/drivers/network/ndisuio/protocol.c new file mode 100644 index 00000000000..4b8fe31413c --- /dev/null +++ b/reactos/drivers/network/ndisuio/protocol.c @@ -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 + +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); +} + diff --git a/reactos/drivers/network/ndisuio/readwrite.c b/reactos/drivers/network/ndisuio/readwrite.c new file mode 100644 index 00000000000..ceae632c156 --- /dev/null +++ b/reactos/drivers/network/ndisuio/readwrite.c @@ -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 + +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; +} \ No newline at end of file diff --git a/reactos/include/psdk/ntddndis.h b/reactos/include/psdk/ntddndis.h index 10d62d19d4c..720eeeec86d 100644 --- a/reactos/include/psdk/ntddndis.h +++ b/reactos/include/psdk/ntddndis.h @@ -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 -#define OID_802_11_BSSID_LIST 0x0D010217 -#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A +/* 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 diff --git a/reactos/include/reactos/drivers/ndisuio/nuiouser.h b/reactos/include/reactos/drivers/ndisuio/nuiouser.h new file mode 100755 index 00000000000..36c1a9bdca7 --- /dev/null +++ b/reactos/include/reactos/drivers/ndisuio/nuiouser.h @@ -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 +