| /* | |
| * packet32.cpp | |
| * | |
| * Basilisk II (C) 1997-2008 Christian Bauer | |
| * | |
| * Windows platform specific code copyright (C) Lauri Pesonen | |
| * | |
| * This program is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License as published by | |
| * the Free Software Foundation; either version 2 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, write to the Free Software | |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| */ | |
| #include "sysdeps.h" | |
| #include "main.h" | |
| #include "util_windows.h" | |
| #include <windowsx.h> | |
| #include <winioctl.h> | |
| #include "cpu_emulation.h" | |
| // VC6 does not have this, Platform SDK has. | |
| // In case of errors, try to comment out, the needed | |
| // definitions are below (#ifndef _NTDDNDIS_) | |
| // Most people don't have the Platform SDK, so I take this one out. | |
| // #include <ntddndis.h> | |
| #include "inc/ntddpack.h" | |
| #include "ether.h" | |
| #include "ether_defs.h" | |
| #include "b2ether/multiopt.h" | |
| #include "b2ether/inc/b2ether_hl.h" | |
| #ifndef _NTDDNDIS_ | |
| #define NDIS_PACKET_TYPE_DIRECTED 0x00000001 | |
| #define NDIS_PACKET_TYPE_MULTICAST 0x00000002 | |
| #define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 | |
| #define NDIS_PACKET_TYPE_BROADCAST 0x00000008 | |
| #define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 | |
| #define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 | |
| #define OID_802_3_PERMANENT_ADDRESS 0x01010101 | |
| #define OID_802_3_CURRENT_ADDRESS 0x01010102 | |
| #define OID_802_3_MULTICAST_LIST 0x01010103 | |
| #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E | |
| #endif | |
| #define DEBUG_PACKETS 0 | |
| #define DEBUG 0 | |
| #include "debug.h" | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| #if DEBUG | |
| #pragma optimize("",off) | |
| #endif | |
| #define MAX_MULTICAST 100 | |
| #define MAX_MULTICAST_SZ (20*ETH_802_3_ADDRESS_LENGTH) | |
| static ULONG packet_filter = 0; | |
| LPADAPTER PacketOpenAdapter( LPCTSTR AdapterName, int16 mode ) | |
| { | |
| LPADAPTER lpAdapter; | |
| BOOLEAN Result = TRUE; | |
| D(bug("Packet32: PacketOpenAdapter\n")); | |
| // May fail if user is not an Administrator. | |
| StartPacketDriver( TEXT("B2ether") ); | |
| lpAdapter = (LPADAPTER)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(ADAPTER) ); | |
| if (lpAdapter==NULL) { | |
| D(bug("Packet32: PacketOpenAdapter GlobalAlloc Failed\n")); | |
| return NULL; | |
| } | |
| TCHAR device_name[256]; | |
| _sntprintf(lpAdapter->SymbolicLink, lengthof(lpAdapter->SymbolicLink), TEXT("\\\\.\\B2ether_%s"), AdapterName ); | |
| _sntprintf(device_name, lengthof(device_name), TEXT("\\Device\\B2ether_%s"), AdapterName ); | |
| // Work around one subtle NT4 bug. | |
| DefineDosDevice( | |
| DDD_REMOVE_DEFINITION, | |
| &lpAdapter->SymbolicLink[4], | |
| NULL | |
| ); | |
| DefineDosDevice( | |
| DDD_RAW_TARGET_PATH, | |
| &lpAdapter->SymbolicLink[4], | |
| device_name | |
| ); | |
| packet_filter = NDIS_PACKET_TYPE_DIRECTED | | |
| NDIS_PACKET_TYPE_MULTICAST | | |
| NDIS_PACKET_TYPE_BROADCAST; | |
| if(mode == ETHER_MULTICAST_ALL) packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; | |
| if(mode == ETHER_MULTICAST_PROMISCUOUS) packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS; | |
| if (Result) { | |
| lpAdapter->hFile = CreateFile(lpAdapter->SymbolicLink, | |
| GENERIC_WRITE | GENERIC_READ, | |
| 0, | |
| NULL, | |
| // (os == VER_PLATFORM_WIN32_NT) ? CREATE_ALWAYS : OPEN_EXISTING, | |
| OPEN_EXISTING, | |
| FILE_FLAG_OVERLAPPED, | |
| 0 | |
| ); | |
| if (lpAdapter->hFile != INVALID_HANDLE_VALUE) { | |
| if(*AdapterName && _tcscmp(AdapterName,TEXT("<None>")) != 0) { | |
| PacketSetFilter( lpAdapter, packet_filter ); | |
| } | |
| return lpAdapter; | |
| } | |
| } | |
| D(bug("Packet32: PacketOpenAdapter Could not open adapter\n")); | |
| GlobalFreePtr( lpAdapter ); | |
| return NULL; | |
| } | |
| VOID PacketCloseAdapter( LPADAPTER lpAdapter ) | |
| { | |
| D(bug("Packet32: PacketCloseAdapter\n")); | |
| if(lpAdapter) { | |
| if(lpAdapter->hFile) { | |
| CloseHandle(lpAdapter->hFile); | |
| } | |
| GlobalFreePtr(lpAdapter); | |
| } | |
| } | |
| LPPACKET PacketAllocatePacket( LPADAPTER AdapterObject, UINT Length ) | |
| { | |
| LPPACKET lpPacket; | |
| lpPacket = (LPPACKET)GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(PACKET) ); | |
| if(lpPacket==NULL) { | |
| D(bug("Packet32: PacketAllocatePacket: GlobalAlloc Failed\n")); | |
| return NULL; | |
| } | |
| lpPacket->OverLapped.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); | |
| if(!lpPacket->OverLapped.hEvent) { | |
| D(bug("Packet32: PacketAllocatePacket: CreateEvent Failed\n")); | |
| GlobalFreePtr(lpPacket); | |
| return NULL; | |
| } | |
| lpPacket->Buffer = GlobalAllocPtr(GMEM_MOVEABLE,2048); // 1514 | |
| if(!lpPacket->Buffer) { | |
| D(bug("Packet32: PacketAllocatePacket: GlobalAllocPtr Failed\n")); | |
| if(lpPacket->OverLapped.hEvent) CloseHandle(lpPacket->OverLapped.hEvent); | |
| GlobalFreePtr(lpPacket); | |
| return NULL; | |
| } | |
| lpPacket->OverLapped.Offset = 0; | |
| lpPacket->OverLapped.OffsetHigh = 0; | |
| lpPacket->Length = Length; | |
| lpPacket->BytesReceived = 0; | |
| lpPacket->bIoComplete = FALSE; | |
| lpPacket->free = TRUE; | |
| return lpPacket; | |
| } | |
| VOID PacketFreePacket( LPPACKET lpPacket ) | |
| { | |
| if(lpPacket) { | |
| if(lpPacket->Buffer) GlobalFreePtr(lpPacket->Buffer); | |
| if(lpPacket->OverLapped.hEvent) CloseHandle(lpPacket->OverLapped.hEvent); | |
| GlobalFreePtr(lpPacket); | |
| } | |
| } | |
| BOOLEAN PacketDeviceIoControl( | |
| LPADAPTER lpAdapterObject, | |
| LPPACKET lpPacket, | |
| ULONG ulIoctl, | |
| BOOLEAN bSync | |
| ) | |
| { | |
| BOOLEAN Result; | |
| lpPacket->OverLapped.Offset = 0; | |
| lpPacket->OverLapped.OffsetHigh = 0; | |
| lpPacket->BytesReceived = 0; | |
| if ( !ResetEvent( lpPacket->OverLapped.hEvent ) ) { | |
| lpPacket->bIoComplete = FALSE; | |
| D(bug( "Packet32: PacketDeviceIoControl failed to reset event\r\n", GetLastError() )); | |
| return FALSE; | |
| } | |
| Result = DeviceIoControl( | |
| lpAdapterObject->hFile, | |
| ulIoctl, | |
| lpPacket->Buffer, | |
| lpPacket->Length, | |
| lpPacket->Buffer, | |
| lpPacket->Length, | |
| &(lpPacket->BytesReceived), | |
| &(lpPacket->OverLapped) ); | |
| if( !Result && bSync ) { | |
| if (GetLastError() == ERROR_IO_PENDING) { | |
| Result = GetOverlappedResult( lpAdapterObject->hFile, | |
| &(lpPacket->OverLapped), | |
| &(lpPacket->BytesReceived), | |
| TRUE ); | |
| } else { | |
| D(bug( "Packet32: unsupported API call returned error 0x%x\r\n", GetLastError() )); | |
| } | |
| } | |
| lpPacket->bIoComplete = Result; | |
| return Result; | |
| } | |
| VOID CALLBACK PacketSendCompletionRoutine( | |
| DWORD dwErrorCode, | |
| DWORD dwNumberOfBytesTransfered, | |
| LPOVERLAPPED lpOverlapped | |
| ) | |
| { | |
| LPPACKET lpPacket = CONTAINING_RECORD(lpOverlapped,PACKET,OverLapped); | |
| #if DEBUG_PACKETS | |
| D(bug("PacketSendCompletionRoutine %d\n",dwNumberOfBytesTransfered)); | |
| #endif | |
| lpPacket->bIoComplete = TRUE; | |
| // lpPacket->free = TRUE; | |
| // PacketFreePacket(lpPacket); | |
| recycle_write_packet(lpPacket); | |
| } | |
| BOOLEAN PacketSendPacket( | |
| LPADAPTER AdapterObject, | |
| LPPACKET lpPacket, | |
| BOOLEAN Sync, | |
| BOOLEAN RecyclingAllowed | |
| ) | |
| { | |
| BOOLEAN Result; | |
| #if DEBUG_PACKETS | |
| D(bug("Packet32: PacketSendPacket bytes=%d, sync=%d\n",lpPacket->Length,Sync)); | |
| #endif | |
| lpPacket->OverLapped.Offset = 0; | |
| lpPacket->OverLapped.OffsetHigh = 0; | |
| lpPacket->bIoComplete = FALSE; | |
| if(Sync) { | |
| Result = WriteFile( | |
| AdapterObject->hFile, | |
| lpPacket->Buffer, | |
| lpPacket->Length, | |
| &lpPacket->BytesReceived, | |
| &lpPacket->OverLapped | |
| ); | |
| if(Result) { | |
| Result = GetOverlappedResult( | |
| AdapterObject->hFile, | |
| &lpPacket->OverLapped, | |
| &lpPacket->BytesReceived, | |
| TRUE | |
| ); | |
| } else { | |
| D(bug("Packet32: PacketSendPacket WriteFile failed, err=%d\n",(int)GetLastError())); | |
| } | |
| lpPacket->bIoComplete = TRUE; | |
| if(RecyclingAllowed) PacketFreePacket(lpPacket); | |
| #if DEBUG_PACKETS | |
| D(bug("Packet32: PacketSendPacket result=%d, bytes=%d\n",(int)Result,(int)lpPacket->BytesReceived)); | |
| #endif | |
| } else { | |
| // don't care about the result | |
| Result = WriteFileEx( | |
| AdapterObject->hFile, | |
| lpPacket->Buffer, | |
| lpPacket->Length, | |
| &lpPacket->OverLapped, | |
| PacketSendCompletionRoutine | |
| ); | |
| #if DEBUG_PACKETS | |
| D(bug("Packet32: PacketSendPacket result=%d\n",(int)Result)); | |
| #endif | |
| if(!Result && RecyclingAllowed) { | |
| recycle_write_packet(lpPacket); | |
| } | |
| } | |
| return Result; | |
| } | |
| BOOLEAN PacketReceivePacket( | |
| LPADAPTER AdapterObject, | |
| LPPACKET lpPacket, | |
| BOOLEAN Sync | |
| ) | |
| { | |
| BOOLEAN Result; | |
| lpPacket->OverLapped.Offset=0; | |
| lpPacket->OverLapped.OffsetHigh=0; | |
| lpPacket->bIoComplete = FALSE; | |
| #if DEBUG_PACKETS | |
| D(bug("Packet32: PacketReceivePacket\n")); | |
| #endif | |
| if (Sync) { | |
| Result = ReadFile( | |
| AdapterObject->hFile, | |
| lpPacket->Buffer, | |
| lpPacket->Length, | |
| &lpPacket->BytesReceived, | |
| &lpPacket->OverLapped | |
| ); | |
| if(Result) { | |
| Result = GetOverlappedResult( | |
| AdapterObject->hFile, | |
| &lpPacket->OverLapped, | |
| &lpPacket->BytesReceived, | |
| TRUE | |
| ); | |
| if(Result) | |
| lpPacket->bIoComplete = TRUE; | |
| else | |
| lpPacket->free = TRUE; | |
| } | |
| } else { | |
| Result = ReadFileEx( | |
| AdapterObject->hFile, | |
| lpPacket->Buffer, | |
| lpPacket->Length, | |
| &lpPacket->OverLapped, | |
| packet_read_completion | |
| ); | |
| } | |
| if(!Result) lpPacket->BytesReceived = 0; | |
| #if DEBUG_PACKETS | |
| D(bug("Packet32: PacketReceivePacket got %d bytes, result=%d\n",lpPacket->BytesReceived,(int)Result)); | |
| #endif | |
| return Result; | |
| } | |
| BOOLEAN PacketRequest( | |
| LPADAPTER lpAdapterObject, | |
| LPPACKET lpPacket, | |
| BOOLEAN bSet | |
| ) | |
| { | |
| BOOLEAN Result = FALSE; | |
| Result = PacketDeviceIoControl( | |
| lpAdapterObject, | |
| lpPacket, | |
| (ULONG) ((bSet) ? IOCTL_PROTOCOL_SET_OID : IOCTL_PROTOCOL_QUERY_OID), | |
| TRUE ); | |
| if ( lpPacket->BytesReceived == 0 ) { | |
| D(bug( "Packet32: Ndis returned error to OID\r\n")); | |
| Result = FALSE; | |
| } | |
| return Result; | |
| } | |
| LPPACKET PacketQueryOid( | |
| LPADAPTER lpAdapter, | |
| ULONG ulOid, | |
| ULONG ulLength | |
| ) | |
| { | |
| ULONG ioctl; | |
| LPPACKET lpPacket; | |
| #define pOidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) | |
| lpPacket = PacketAllocatePacket( lpAdapter, sizeof(PACKET_OID_DATA)-1+ulLength ); | |
| if( lpPacket ) { | |
| ioctl = IOCTL_PROTOCOL_QUERY_OID; | |
| pOidData->Oid = ulOid; | |
| pOidData->Length = ulLength; | |
| if (PacketRequest( lpAdapter, lpPacket, FALSE )) { | |
| return lpPacket; | |
| } | |
| PacketFreePacket( lpPacket ); | |
| } | |
| #undef pOidData | |
| return 0; | |
| } | |
| BOOLEAN PacketGetMAC( LPADAPTER AdapterObject, LPBYTE address, BOOL permanent ) | |
| { | |
| BOOLEAN Status; | |
| LPPACKET lpPacket; | |
| lpPacket = PacketQueryOid( | |
| AdapterObject, | |
| permanent ? OID_802_3_PERMANENT_ADDRESS : OID_802_3_CURRENT_ADDRESS, | |
| ETH_802_3_ADDRESS_LENGTH | |
| ); | |
| if(lpPacket) { | |
| memcpy( address, | |
| ((BYTE *)(lpPacket->Buffer)) + sizeof(PACKET_OID_DATA) - 1, | |
| ETH_802_3_ADDRESS_LENGTH ); | |
| PacketFreePacket( lpPacket ); | |
| Status = TRUE; | |
| } else { | |
| Status = FALSE; | |
| } | |
| return Status; | |
| } | |
| // There are other ways to do this. | |
| BOOLEAN PacketAddMulticast( LPADAPTER AdapterObject, LPBYTE address ) | |
| { | |
| BOOLEAN Status = FALSE; | |
| LPBYTE p; | |
| int i, count; | |
| LPPACKET lpPacket; | |
| D(bug("PacketAddMulticast\n")); | |
| /* | |
| if(packet_filter & (NDIS_PACKET_TYPE_ALL_MULTICAST|NDIS_PACKET_TYPE_PROMISCUOUS)) { | |
| D(bug("PacketAddMulticast: already listening for all multicast\n")); | |
| return TRUE; | |
| } | |
| */ | |
| lpPacket = PacketQueryOid( AdapterObject, OID_802_3_MULTICAST_LIST, MAX_MULTICAST_SZ ); | |
| #define OidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) | |
| if(lpPacket) { | |
| count = OidData->Length / ETH_802_3_ADDRESS_LENGTH; | |
| D(bug("PacketAddMulticast: %d old addresses\n",count)); | |
| p = (LPBYTE)OidData->Data; | |
| for( i=0; i<count; i++ ) { | |
| if(memcmp(p,address,ETH_802_3_ADDRESS_LENGTH) == 0) { | |
| // This multicast is already defined -- error or not? | |
| Status = TRUE; | |
| D(bug("PacketAddMulticast: address already defined\n")); | |
| break; | |
| } | |
| p += ETH_802_3_ADDRESS_LENGTH; | |
| } | |
| if(i == count) { | |
| if(i >= MAX_MULTICAST) { | |
| D(bug("PacketAddMulticast: too many addresses\n")); | |
| Status = FALSE; | |
| } else { | |
| D(bug("PacketAddMulticast: adding a new address\n")); | |
| // ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*1-1); | |
| ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*(count+1)-1); | |
| LPPACKET lpPacket2 = PacketAllocatePacket( AdapterObject, IoCtlBufferLength ); | |
| #define OidData2 ((PPACKET_OID_DATA)(lpPacket2->Buffer)) | |
| if ( lpPacket2 ) { | |
| OidData2->Oid = OID_802_3_MULTICAST_LIST; | |
| // OidData2->Length = ETH_802_3_ADDRESS_LENGTH*1; | |
| // memcpy( OidData2->Data, address, ETH_802_3_ADDRESS_LENGTH ); | |
| memcpy( OidData2->Data, OidData->Data, ETH_802_3_ADDRESS_LENGTH*count ); | |
| memcpy( OidData2->Data+ETH_802_3_ADDRESS_LENGTH*count, address, ETH_802_3_ADDRESS_LENGTH ); | |
| OidData2->Length = ETH_802_3_ADDRESS_LENGTH*(count+1); | |
| Status = PacketRequest( AdapterObject, lpPacket2, TRUE ); | |
| PacketFreePacket( lpPacket2 ); | |
| } | |
| #undef OidData2 | |
| } | |
| } | |
| PacketFreePacket( lpPacket ); | |
| } | |
| #undef OidData | |
| // return Status; | |
| return TRUE; | |
| } | |
| // It seems that the last multicast address is never deleted. Why? | |
| // Don't know the reason, but luckily this is not fatal. | |
| // Hard to examine return codes. See NE2000 sources, always returns ok. | |
| BOOLEAN PacketDelMulticast( LPADAPTER AdapterObject, LPBYTE address ) | |
| { | |
| BOOLEAN Status = FALSE; | |
| LPBYTE p; | |
| int i, count; | |
| LPPACKET lpPacket, lpPacket2; | |
| D(bug("PacketDelMulticast\n")); | |
| if(packet_filter & (NDIS_PACKET_TYPE_ALL_MULTICAST|NDIS_PACKET_TYPE_PROMISCUOUS)) { | |
| D(bug("PacketDelMulticast: already listening for all multicast\n")); | |
| return TRUE; | |
| } | |
| lpPacket = PacketQueryOid( AdapterObject, OID_802_3_MULTICAST_LIST, MAX_MULTICAST_SZ ); | |
| #define OidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) | |
| if(lpPacket) { | |
| count = OidData->Length / ETH_802_3_ADDRESS_LENGTH; | |
| D(bug("PacketDelMulticast: %d old addresses\n",count)); | |
| Status = FALSE; | |
| p = (LPBYTE)OidData->Data; | |
| for( i=0; i<count; i++ ) { | |
| int tail_len; | |
| if(memcmp(p,address,ETH_802_3_ADDRESS_LENGTH) == 0) { | |
| D(bug("PacketDelMulticast: address found, deleting\n")); | |
| ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+ETH_802_3_ADDRESS_LENGTH*(count-1)-1); | |
| lpPacket2 = PacketAllocatePacket( AdapterObject, IoCtlBufferLength ); | |
| #define OidData2 ((PPACKET_OID_DATA)(lpPacket2->Buffer)) | |
| if ( lpPacket2 ) { | |
| OidData2->Oid = OID_802_3_MULTICAST_LIST; | |
| OidData2->Length = ETH_802_3_ADDRESS_LENGTH*(count-1); | |
| tail_len = ETH_802_3_ADDRESS_LENGTH * (count-i-1); | |
| if(tail_len) memmove( p, p+ETH_802_3_ADDRESS_LENGTH, tail_len ); | |
| if(OidData2->Length) memcpy( OidData2->Data, OidData->Data, OidData2->Length ); | |
| if(count == 1) memset( OidData2->Data, 0, ETH_802_3_ADDRESS_LENGTH ); // eh... | |
| Status = PacketRequest( AdapterObject, lpPacket2, TRUE ); | |
| PacketFreePacket( lpPacket2 ); | |
| D(bug("PacketDelMulticast: PacketRequest returned status 0x%X, last error = 0x%X\n",Status,GetLastError())); | |
| } | |
| break; | |
| #undef OidData2 | |
| } | |
| p += ETH_802_3_ADDRESS_LENGTH; | |
| } | |
| if( i == count ) { | |
| D(bug("PacketDelMulticast: cannot delete, was not defined\n")); | |
| } | |
| PacketFreePacket( lpPacket ); | |
| #undef OidData | |
| } | |
| // return Status; | |
| return TRUE; | |
| } | |
| BOOLEAN PacketSetFilter( LPADAPTER AdapterObject, ULONG Filter ) | |
| { | |
| BOOLEAN Status; | |
| ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1); | |
| LPPACKET lpPacket; | |
| lpPacket = PacketAllocatePacket( AdapterObject, IoCtlBufferLength ); | |
| #define lpOidData ((PPACKET_OID_DATA)(lpPacket->Buffer)) | |
| if ( lpPacket ) { | |
| lpOidData->Oid = OID_GEN_CURRENT_PACKET_FILTER; | |
| lpOidData->Length = sizeof(ULONG); | |
| *((PULONG)lpOidData->Data) = Filter; | |
| Status = PacketRequest( AdapterObject, lpPacket, TRUE ); | |
| PacketFreePacket( lpPacket ); | |
| } else { | |
| Status = FALSE; | |
| } | |
| #undef lpOidData | |
| return Status; | |
| } | |
| BOOLEAN StartPacketDriver( LPCTSTR ServiceName ) | |
| { | |
| BOOLEAN Status = FALSE; | |
| SC_HANDLE SCManagerHandle; | |
| SC_HANDLE SCServiceHandle; | |
| SCManagerHandle = OpenSCManager( | |
| NULL, | |
| NULL, | |
| SC_MANAGER_ALL_ACCESS); | |
| if(SCManagerHandle == NULL) { | |
| D(bug("Could not open Service Control Manager\r\n")); | |
| } else { | |
| SCServiceHandle = OpenService(SCManagerHandle,ServiceName,SERVICE_START); | |
| if (SCServiceHandle == NULL) { | |
| D(bug(TEXT("Could not open service %s\r\n"),ServiceName)); | |
| } else { | |
| Status = StartService( SCServiceHandle, 0, NULL ); | |
| if(!Status) { | |
| if (GetLastError()==ERROR_SERVICE_ALREADY_RUNNING) { | |
| Status = TRUE; | |
| } | |
| } | |
| BOOL waiting = TRUE; | |
| // loop until the service is fully started. | |
| while (waiting) { | |
| SERVICE_STATUS ServiceStatus; | |
| if (QueryServiceStatus(SCServiceHandle, &ServiceStatus)) { | |
| switch(ServiceStatus.dwCurrentState) { | |
| case SERVICE_RUNNING: | |
| waiting = FALSE; | |
| Status = TRUE; | |
| break; | |
| case SERVICE_START_PENDING: | |
| Sleep(500); | |
| break; | |
| default: | |
| waiting = FALSE; | |
| break; | |
| } | |
| } else { | |
| waiting = FALSE; | |
| } | |
| } | |
| CloseServiceHandle(SCServiceHandle); | |
| } | |
| CloseServiceHandle(SCManagerHandle); | |
| } | |
| return Status; | |
| } | |
| ULONG PacketGetAdapterNames( LPADAPTER lpAdapter, LPTSTR pStr, PULONG BufferSize ) | |
| { | |
| LONG Status; | |
| HKEY hKey; | |
| DWORD RegType; | |
| Status = RegOpenKey( | |
| HKEY_LOCAL_MACHINE, | |
| TEXT("SYSTEM\\CurrentControlSet\\Services\\B2Ether\\Linkage"), | |
| &hKey | |
| ); | |
| if( Status == ERROR_SUCCESS ) { | |
| Status = RegQueryValueEx( | |
| hKey, | |
| TEXT("Export"), | |
| NULL, | |
| &RegType, | |
| (LPBYTE)pStr, | |
| BufferSize | |
| ); | |
| RegCloseKey(hKey); | |
| } | |
| return Status; | |
| } | |
| #ifdef __cplusplus | |
| } | |
| #endif | |
| #if DEBUG | |
| #pragma optimize("",on) | |
| #endif |