/********************************************************************/ /** Copyright(c) 1995 Microsoft Corporation. **/ /********************************************************************/ //*** // // Filename: adminapi.c // // Description: Contains code to respond to DDM admin. requests. // // History: May 11,1995 NarenG Created original version. // #include "ddm.h" #include #include "objects.h" #include "handlers.h" #include "rasapiif.h" #include "routerif.h" #include "util.h" #include // Generated by MIDL #include #include #include //** // // Call: DDMAdminInterfaceConnect // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminInterfaceConnect( IN HANDLE hDimInterface, IN HANDLE hEvent, IN BOOL fBlocking, IN DWORD dwCallersProcessId ) { HANDLE hClientProcess = NULL; DWORD dwRetCode = NO_ERROR; ROUTER_INTERFACE_OBJECT* pIfObject = NULL; HANDLE hEventToBeDuplicated = NULL; DWORD fReturn = FALSE; EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) ); do { if ( ( pIfObject = IfObjectGetPointer((HANDLE)hDimInterface) ) == NULL ) { dwRetCode = ERROR_INVALID_HANDLE; break; } if ( pIfObject->State == RISTATE_CONNECTED ) { dwRetCode = NO_ERROR; fReturn = TRUE; break; } if ( pIfObject->State == RISTATE_CONNECTING ) { dwRetCode = ERROR_ALREADY_CONNECTING; fReturn = TRUE; break; } if ( ( hEvent == NULL ) && ( fBlocking ) ) { // // This call is to be synchrnonous, create an event and block on // it. // hEventToBeDuplicated = CreateEvent( NULL, FALSE, FALSE, NULL ); if ( hEventToBeDuplicated == NULL ) { dwRetCode = GetLastError(); break; } dwCallersProcessId = GetCurrentProcessId(); } else { hEventToBeDuplicated = hEvent; } if ( hEventToBeDuplicated != NULL ) { // // // Get process handle of the caller of this API // hClientProcess = OpenProcess( STANDARD_RIGHTS_REQUIRED | SPECIFIC_RIGHTS_ALL, FALSE, dwCallersProcessId); if ( hClientProcess == NULL ) { dwRetCode = GetLastError(); break; } // // Duplicate the handle to the event // if ( !DuplicateHandle( hClientProcess, hEventToBeDuplicated, GetCurrentProcess(), &(pIfObject->hEventNotifyCaller), 0, FALSE, DUPLICATE_SAME_ACCESS ) ) { CloseHandle( hClientProcess ); dwRetCode = GetLastError(); break; } CloseHandle( hClientProcess ); } else { pIfObject->hEventNotifyCaller = INVALID_HANDLE_VALUE; } // // Initiate a connection // dwRetCode = RasConnectionInitiate( pIfObject, FALSE ); if ( dwRetCode != NO_ERROR ) { CloseHandle( pIfObject->hEventNotifyCaller ); pIfObject->hEventNotifyCaller = INVALID_HANDLE_VALUE; } else { dwRetCode = PENDING; } DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RasConnectionInitiate: To %ws dwRetCode=%d", pIfObject->lpwsInterfaceName, dwRetCode ); } while( FALSE ); LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); // // If we are or already connecting or connected then simply return // if ( fReturn ) { return( dwRetCode ); } // // This is a synchronous call, we need to wait till compeletion // if ( ( hEvent == NULL ) && ( fBlocking ) ) { if ( dwRetCode == PENDING ) { if ( WaitForSingleObject( hEventToBeDuplicated, INFINITE ) == WAIT_FAILED ) { CloseHandle( hEventToBeDuplicated ); return( GetLastError() ); } EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) ); if ( ( pIfObject = IfObjectGetPointer((HANDLE)hDimInterface) ) == NULL ) { dwRetCode = ERROR_INVALID_HANDLE; } else { dwRetCode = pIfObject->dwLastError; } LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); } if ( hEventToBeDuplicated != NULL ) { CloseHandle( hEventToBeDuplicated ); } } return( dwRetCode ); } //** // // Call: DDMAdminInterfaceDisconnect // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminInterfaceDisconnect( IN HANDLE hDimInterface ) { DWORD dwRetCode = NO_ERROR; DWORD dwTransportIndex = -1; if ( gblDDMConfigInfo.dwNumRouterManagers > 0 ) { for ( dwTransportIndex = 0; dwTransportIndex < gblDDMConfigInfo.dwNumRouterManagers; dwTransportIndex++ ) { dwRetCode = DDMDisconnectInterface( hDimInterface, gblRouterManagers[dwTransportIndex].DdmRouterIf.dwProtocolId ); if ( dwRetCode != NO_ERROR ) { return( dwRetCode ); } } } else { // // [old comment] If no router managers are installed then we are a AMB // or NBF only client connection, simply call disconnect interface // // [new comment] // // AMB and NBF have been removed from the project but this path is // being kept since logically, you should be able to disconnect an // interface regardless of whether any router managers exist. // // This philosphy is in spirit with the work we'll do // to merge rasman, dim, and ddm. Then it will be possible for // code paths like this to execute without any router managers being // loaded. // dwRetCode = DDMDisconnectInterface( hDimInterface, -1 ); } return( dwRetCode ); } //** // // Call: DDMAdminServerGetInfo // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminServerGetInfo( IN OUT PVOID pServerInfo, IN DWORD dwLevel ) { MPR_SERVER_0* pServerInfo0; if ( dwLevel == 0 ) { pServerInfo0 = (MPR_SERVER_0*)pServerInfo; pServerInfo0->fLanOnlyMode = FALSE; } else { return( ERROR_NOT_SUPPORTED ); } EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); // // Copy server info // pServerInfo0->dwTotalPorts = gblDeviceTable.NumDeviceNodes; pServerInfo0->dwPortsInUse = gblDeviceTable.NumDevicesInUse; LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( NO_ERROR ); } //** // // Call: DDMAdminConnectionEnum // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminConnectionEnum( IN OUT PDIM_INFORMATION_CONTAINER pInfoStruct, IN DWORD dwLevel, IN DWORD dwPreferedMaximumLength, IN LPDWORD lpdwEntriesRead, IN LPDWORD lpdwTotalEntries, IN OUT LPDWORD lpdwResumeHandle OPTIONAL ) { PRASI_CONNECTION_0 pRasConnection0 = NULL; PRASI_CONNECTION_1 pRasConnection1 = NULL; PRASI_CONNECTION_2 pRasConnection2 = NULL; PCONNECTION_OBJECT pConnObj = NULL; DWORD dwBucketIndex = 0; DWORD dwConnObjIndex = 0; DWORD dwConnInfoSize = 0; DWORD dwStartIndex = ( lpdwResumeHandle == NULL ) ? 0 : *lpdwResumeHandle; // Calculate the connection info size switch (dwLevel) { case 0: dwConnInfoSize = sizeof( RASI_CONNECTION_0 ); break; case 1: dwConnInfoSize = sizeof( RASI_CONNECTION_1 ); break; case 2: dwConnInfoSize = sizeof( RASI_CONNECTION_2 ); break; default: return ERROR_NOT_SUPPORTED; } EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); if ( gblDeviceTable.NumConnectionNodes < dwStartIndex ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_NO_MORE_ITEMS ); } *lpdwTotalEntries = gblDeviceTable.NumConnectionNodes - dwStartIndex; if ( dwPreferedMaximumLength != -1 ) { *lpdwEntriesRead = dwPreferedMaximumLength / dwConnInfoSize; if ( *lpdwEntriesRead > *lpdwTotalEntries ) { *lpdwEntriesRead = *lpdwTotalEntries; } } else { *lpdwEntriesRead = *lpdwTotalEntries; } pInfoStruct->dwBufferSize = *lpdwEntriesRead * dwConnInfoSize; pInfoStruct->pBuffer = MIDL_user_allocate( pInfoStruct->dwBufferSize ); if ( pInfoStruct->pBuffer == NULL ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); pInfoStruct->dwBufferSize = 0; return( ERROR_NOT_ENOUGH_MEMORY ); } if (dwLevel == 0) pRasConnection0 = (PRASI_CONNECTION_0)pInfoStruct->pBuffer; else if (dwLevel == 1) pRasConnection1 = (PRASI_CONNECTION_1)pInfoStruct->pBuffer; else pRasConnection2 = (PRASI_CONNECTION_2)pInfoStruct->pBuffer; for ( dwBucketIndex = 0; dwBucketIndex < gblDeviceTable.NumDeviceBuckets; dwBucketIndex++ ) { for( pConnObj = gblDeviceTable.ConnectionBucket[dwBucketIndex]; pConnObj != (CONNECTION_OBJECT *)NULL; pConnObj = pConnObj->pNext ) { // // Check if this connection object is within the range we need to // copy from. // if ( ( dwConnObjIndex >= dwStartIndex ) && ( dwConnObjIndex < (dwStartIndex+*lpdwEntriesRead))) { // // Copy the info // if (dwLevel == 0) { GetRasiConnection0Data( pConnObj, pRasConnection0 ); pRasConnection0++; } else if (dwLevel == 1) { GetRasiConnection1Data( pConnObj, pRasConnection1 ); pRasConnection1++; } else { GetRasiConnection2Data( pConnObj, pRasConnection2 ); pRasConnection2++; } } else if (dwConnObjIndex>=(dwStartIndex+*lpdwEntriesRead)) { // // Beyond the range so exit // if ( lpdwResumeHandle != NULL ) { *lpdwResumeHandle = dwConnObjIndex; } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_MORE_DATA ); } dwConnObjIndex++; } } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( NO_ERROR ); } //** // // Call: DDMAdminConnectionGetInfo // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminConnectionGetInfo( IN HANDLE hConnection, IN OUT PDIM_INFORMATION_CONTAINER pInfoStruct, IN DWORD dwLevel ) { DWORD dwRetCode = NO_ERROR; ROUTER_INTERFACE_OBJECT * pIfObject; CONNECTION_OBJECT * pConnObj; if ( dwLevel > 2 ) { return( ERROR_NOT_SUPPORTED ); } EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); switch( dwLevel ) { case 0: pInfoStruct->dwBufferSize = sizeof( RASI_CONNECTION_0 ); break; case 1: pInfoStruct->dwBufferSize = sizeof( RASI_CONNECTION_1 ); break; case 2: pInfoStruct->dwBufferSize = sizeof( RASI_CONNECTION_2 ); break; } pInfoStruct->pBuffer = MIDL_user_allocate( pInfoStruct->dwBufferSize ); if ( pInfoStruct->pBuffer == NULL ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_NOT_ENOUGH_MEMORY ); } // // Copy Connection info // do { pConnObj = ConnObjGetPointer( (HCONN)hConnection ); if ( pConnObj == (CONNECTION_OBJECT *)NULL ) { dwRetCode = ERROR_INTERFACE_NOT_CONNECTED; break; } switch( dwLevel ) { case 0: dwRetCode = GetRasiConnection0Data( pConnObj, (PRASI_CONNECTION_0)pInfoStruct->pBuffer ); break; case 1: dwRetCode = GetRasiConnection1Data( pConnObj, (PRASI_CONNECTION_1)pInfoStruct->pBuffer ); break; case 2: dwRetCode = GetRasiConnection2Data( pConnObj, (PRASI_CONNECTION_2)pInfoStruct->pBuffer ); break; } }while( FALSE ); if ( dwRetCode != NO_ERROR ) { MIDL_user_free( pInfoStruct->pBuffer ); pInfoStruct->pBuffer = NULL; pInfoStruct->dwBufferSize = 0; } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( dwRetCode ); } //** // // Call: DDMAdminConnectionClearStats // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminConnectionClearStats( IN HANDLE hConnection ) { return( RasBundleClearStatisticsEx(NULL, (HCONN)hConnection ) ); } //** // // Call: DDMAdminPortEnum // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminPortEnum( IN OUT PDIM_INFORMATION_CONTAINER pInfoStruct, IN HANDLE hConnection, IN DWORD dwLevel, IN DWORD dwPreferedMaximumLength, IN LPDWORD lpdwEntriesRead, IN LPDWORD lpdwTotalEntries, IN OUT LPDWORD lpdwResumeHandle OPTIONAL ) { PRASI_PORT_0 pRasPort0 = NULL; PDEVICE_OBJECT pDevObj = NULL; PCONNECTION_OBJECT pConnObj = NULL; DWORD dwIndex = 0; DWORD dwBucketIndex = 0; DWORD dwDevObjIndex = 0; DWORD dwStartIndex = ( lpdwResumeHandle == NULL ) ? 0 : *lpdwResumeHandle; if ( dwLevel != 0 ) { return( ERROR_NOT_SUPPORTED ); } EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); if ( hConnection != INVALID_HANDLE_VALUE ) { if ( ( pConnObj = ConnObjGetPointer( (HCONN)hConnection ) ) == NULL ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_INVALID_HANDLE ); } if ( pConnObj->cActiveDevices < dwStartIndex ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_NO_MORE_ITEMS ); } *lpdwTotalEntries = pConnObj->cActiveDevices - dwStartIndex; } else { if ( gblDeviceTable.NumDeviceNodes < dwStartIndex ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_NO_MORE_ITEMS ); } *lpdwTotalEntries = gblDeviceTable.NumDeviceNodes - dwStartIndex; } if ( dwPreferedMaximumLength != -1 ) { *lpdwEntriesRead = dwPreferedMaximumLength / sizeof( RAS_PORT_0 ); if ( *lpdwEntriesRead > *lpdwTotalEntries ) { *lpdwEntriesRead = *lpdwTotalEntries; } } else { *lpdwEntriesRead = *lpdwTotalEntries; } pInfoStruct->dwBufferSize = *lpdwEntriesRead * sizeof( RASI_PORT_0 ); pInfoStruct->pBuffer = MIDL_user_allocate( pInfoStruct->dwBufferSize ); if ( pInfoStruct->pBuffer == NULL ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); pInfoStruct->dwBufferSize = 0; return( ERROR_NOT_ENOUGH_MEMORY ); } pRasPort0 = (PRASI_PORT_0)pInfoStruct->pBuffer; if ( hConnection == INVALID_HANDLE_VALUE ) { for ( dwBucketIndex = 0; dwBucketIndex < gblDeviceTable.NumDeviceBuckets; dwBucketIndex++ ) { for( pDevObj = gblDeviceTable.DeviceBucket[dwBucketIndex]; pDevObj != (DEVICE_OBJECT *)NULL; pDevObj = pDevObj->pNext ) { // // Check if this port is within the range we need to copy // from. // if ( ( dwDevObjIndex >= dwStartIndex ) && ( dwDevObjIndex < (dwStartIndex+*lpdwEntriesRead))) { // // Copy the info // GetRasiPort0Data( pDevObj, pRasPort0 ); pRasPort0++; } else if (dwDevObjIndex>=(dwStartIndex+*lpdwEntriesRead)) { // // Beyond the range so exit // if ( lpdwResumeHandle != NULL ) { *lpdwResumeHandle = dwDevObjIndex; } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_MORE_DATA ); } dwDevObjIndex++; } } } else { for ( dwIndex = 0; dwIndex < pConnObj->cDeviceListSize; dwIndex++ ) { if ( pConnObj->pDeviceList[dwIndex] != NULL ) { // // Check if this port is within the range we need to copy // from. // if ( ( dwDevObjIndex >= dwStartIndex ) && ( dwDevObjIndex < (dwStartIndex+*lpdwEntriesRead))) { // // Copy the info // GetRasiPort0Data(pConnObj->pDeviceList[dwIndex], pRasPort0); pRasPort0++; } else if (dwDevObjIndex>=(dwStartIndex+*lpdwEntriesRead)) { // // Beyond the range so exit // if ( lpdwResumeHandle != NULL ) { *lpdwResumeHandle = dwDevObjIndex; } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( NO_ERROR ); } dwDevObjIndex++; } } } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( NO_ERROR ); } //** // // Call: DDMAdminPortGetInfo // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminPortGetInfo( IN HANDLE hPort, IN OUT PDIM_INFORMATION_CONTAINER pInfoStruct, IN DWORD dwLevel ) { DEVICE_OBJECT * pDevObj; DWORD dwRetCode; if ( dwLevel > 1 ) { return( ERROR_NOT_SUPPORTED ); } EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); pInfoStruct->dwBufferSize = ( dwLevel == 0 ) ? sizeof( RAS_PORT_0 ) : sizeof( RAS_PORT_1 ); pInfoStruct->pBuffer = MIDL_user_allocate( pInfoStruct->dwBufferSize ); if ( pInfoStruct->pBuffer == NULL ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_NOT_ENOUGH_MEMORY ); } // // Copy port info // do { pDevObj = DeviceObjGetPointer( (HPORT)hPort ); if ( pDevObj == (HPORT)NULL ) { dwRetCode = ERROR_INVALID_PORT_HANDLE; break; } if ( dwLevel == 0 ) { dwRetCode = GetRasiPort0Data( pDevObj, (PRASI_PORT_0)pInfoStruct->pBuffer ); } else { dwRetCode = GetRasiPort1Data( pDevObj, (PRASI_PORT_1)pInfoStruct->pBuffer ); } } while( FALSE ); if ( dwRetCode != NO_ERROR ) { MIDL_user_free( pInfoStruct->pBuffer ); pInfoStruct->pBuffer = NULL; pInfoStruct->dwBufferSize = 0; } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( dwRetCode ); } //** // // Call: DDMAdminPortClearStats // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminPortClearStats( IN HANDLE hPort ) { PDEVICE_OBJECT pDevObj = NULL; EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); if ( ( pDevObj = DeviceObjGetPointer( (HPORT)hPort ) ) == NULL ) { LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( ERROR_INVALID_HANDLE ); } LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( RasPortClearStatistics(NULL, (HPORT)hPort ) ); } //** // // Call: DDMAdminPortReset // // Returns: NO_ERROR - Success // // Description: // DWORD DDMAdminPortReset( IN HANDLE hPort ) { return( NO_ERROR ); } //** // // Call: DDMAdminPortDisconnect // // Returns: NO_ERROR - Success // // Description: Disconnect the client port. // DWORD DDMAdminPortDisconnect( IN HANDLE hPort ) { DEVICE_OBJECT * pDevObj; DWORD dwRetCode = NO_ERROR; EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); do { if ( ( pDevObj = DeviceObjGetPointer( (HPORT)hPort ) ) == NULL ) { dwRetCode = ERROR_INVALID_HANDLE; break; } if ( pDevObj->fFlags & DEV_OBJ_OPENED_FOR_DIALOUT ) { RasApiCleanUpPort( pDevObj ); } else { if ( pDevObj->fFlags & DEV_OBJ_PPP_IS_ACTIVE ) { PppDdmStop( (HPORT)pDevObj->hPort, NO_ERROR ); } else { DevStartClosing( pDevObj ); } } } while( FALSE ); LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return( dwRetCode ); } //** // // Call: DDMRegisterConnectionNotification // // Returns: NO_ERROR - Success // Non-zero returns - Failure // // Description: Will insert or remove and event from the notification list // DWORD DDMRegisterConnectionNotification( IN BOOL fRegister, IN HANDLE hEventClient, IN HANDLE hEventRouter ) { DWORD dwRetCode = NO_ERROR; NOTIFICATION_EVENT * pNotificationEvent = NULL; EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) ); if ( fRegister ) { // // Insert event in notification list // pNotificationEvent = (NOTIFICATION_EVENT *) LOCAL_ALLOC( LPTR, sizeof(NOTIFICATION_EVENT) ); if ( pNotificationEvent == NULL ) { dwRetCode = GetLastError(); } else { pNotificationEvent->hEventClient = hEventClient; pNotificationEvent->hEventRouter = hEventRouter; InsertHeadList( (LIST_ENTRY *)&(gblDDMConfigInfo.NotificationEventListHead), (LIST_ENTRY*)pNotificationEvent ); } } else { // // Remove event from notification list // for( pNotificationEvent = (NOTIFICATION_EVENT *) (gblDDMConfigInfo.NotificationEventListHead.Flink); pNotificationEvent != (NOTIFICATION_EVENT *) &(gblDDMConfigInfo.NotificationEventListHead); pNotificationEvent = (NOTIFICATION_EVENT *) (pNotificationEvent->ListEntry.Flink) ) { if ( pNotificationEvent->hEventClient == hEventClient ) { RemoveEntryList( (LIST_ENTRY *)pNotificationEvent ); CloseHandle( pNotificationEvent->hEventClient ); CloseHandle( pNotificationEvent->hEventRouter ); LOCAL_FREE( pNotificationEvent ); break; } } } LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); return( dwRetCode ); } //** // // Call: DDMSendUserMessage // // Returns: NO_ERROR - Success // // Description: // DWORD DDMSendUserMessage( IN HANDLE hConnection, IN LPWSTR lpwszMessage ) { PCONNECTION_OBJECT pConnObj = NULL; DWORD dwRetCode = NO_ERROR; EnterCriticalSection( &(gblDeviceTable.CriticalSection) ); do { pConnObj = ConnObjGetPointer( (HCONN)hConnection ); if ( pConnObj == (CONNECTION_OBJECT *)NULL ) { dwRetCode = ERROR_INTERFACE_NOT_CONNECTED; break; } if ( pConnObj->fFlags & CONN_OBJ_MESSENGER_PRESENT ) { WCHAR wszRemoteComputer[CNLEN+1]; MultiByteToWideChar( CP_ACP, 0, pConnObj->bComputerName, -1, wszRemoteComputer, CNLEN+1 ); dwRetCode = NetMessageBufferSend( NULL, wszRemoteComputer, NULL, (BYTE*)lpwszMessage, (wcslen(lpwszMessage)+1) * sizeof(WCHAR)); } } while( FALSE ); LeaveCriticalSection( &(gblDeviceTable.CriticalSection) ); return(dwRetCode); }