/************************************************************************ * * * ports.c -- port api's for mprapi.dll * * * * Copyright (c) 1991-1999, Microsoft Corp. All rights reserved. * * * ************************************************************************/ #include #include #include #include #include #include #include // Constants in the registry // static const WCHAR pszRegkeyNetAdapters[] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"; static const WCHAR pszRegkeyModems[] = L"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E96D-E325-11CE-BFC1-08002BE10318}"; static const WCHAR pszRegkeyMdmconfig[] = L"Clients\\Ras"; static const WCHAR pszRegvalDialinUsage[] = L"EnableForRas"; static const WCHAR pszRegvalRouterUsage[] = L"EnableForRouting"; static const WCHAR pszWanEndpoints[] = L"WanEndpoints"; // // Definitions that specify what registry key is being enumerated // #define MPRPORT_F_Adapters 1 #define MPRPORT_F_Modems 2 // // Callback definition for function that will have ras ports // enumerated to it. // typedef DWORD (* RTRUPG_PORT_ENUM_FUNC)( IN HKEY hkPort, IN HANDLE hData); // // Defines data provided to the PortGetConfigKey function // typedef struct _PORTGETCONFIGKEYDATA { DWORD dwRootId; // See PORT_REGKEY_* values RTRUPG_PORT_ENUM_FUNC pEnum; // cb provided to PortEnumPorts HANDLE hData; // data provided to PortEnumPorts } PORTGETCONFIGKEYDATA; // // Typedef for callback functions for enumerating registry sub keys. // Return NO_ERROR to continue, error code to stop. // // See PortEnumRegistrySubKeys. // typedef DWORD (*REG_KEY_ENUM_FUNC_PTR)( IN PWCHAR pszName, // sub key name IN HKEY hKey, // sub key IN HANDLE hData); // // Sends debug trace // DWORD PortTrace( IN LPSTR pszTrace, ...) { #if DBG va_list arglist; char szBuffer[1024], szTemp[1024]; va_start(arglist, pszTrace); vsprintf(szTemp, pszTrace, arglist); va_end(arglist); sprintf(szBuffer, "MprPort: %s\n", szTemp); OutputDebugStringA(szBuffer); #endif return NO_ERROR; } // // Allocation routine for port functions // PVOID PortAlloc ( IN DWORD dwSize, IN BOOL bZero) { return LocalAlloc ((bZero) ? LPTR : LMEM_FIXED, dwSize); } // // Free routine for port functions // VOID PortFree ( IN PVOID pvData) { LocalFree (pvData); } // // Enumerates all of the registry subkeys of a given key // DWORD PortEnumRegistrySubKeys( IN HKEY hkRoot, IN PWCHAR pszPath, IN REG_KEY_ENUM_FUNC_PTR pCallback, IN HANDLE hData) { DWORD dwErr = NO_ERROR, i, dwNameSize = 0, dwCurSize = 0; DWORD dwCount = 0; HKEY hkKey = NULL, hkCurKey = NULL; PWCHAR pszName = NULL; BOOL bCloseKey = FALSE; do { if (pszPath) { bCloseKey = TRUE; // Open the key to enumerate // dwErr = RegOpenKeyExW( hkRoot, pszPath, 0, KEY_ALL_ACCESS, &hkKey); if (dwErr != NO_ERROR) { break; } } else { bCloseKey = FALSE; hkKey = hkRoot; } // Find out how many sub keys there are // dwErr = RegQueryInfoKeyW( hkKey, NULL, NULL, NULL, &dwCount, &dwNameSize, NULL, NULL, NULL, NULL, NULL, NULL); if (dwErr != ERROR_SUCCESS) { return dwErr; } dwNameSize++; // Allocate the name buffer // pszName = (PWCHAR) PortAlloc(dwNameSize * sizeof(WCHAR), TRUE); if (pszName == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } // Loop through the keys // for (i = 0; i < dwCount; i++) { dwCurSize = dwNameSize; // Get the name of the current key // dwErr = RegEnumKeyExW( hkKey, i, pszName, &dwCurSize, 0, NULL, NULL, NULL); if (dwErr != ERROR_SUCCESS) { continue; } // Open the subkey // dwErr = RegOpenKeyExW( hkKey, pszName, 0, KEY_ALL_ACCESS, &hkCurKey); if (dwErr != ERROR_SUCCESS) { continue; } // Call the callback // dwErr = pCallback(pszName, hkCurKey, hData); RegCloseKey(hkCurKey); if (dwErr != NO_ERROR) { break; } } } while (FALSE); // Cleanup { if ((hkKey != NULL) && (bCloseKey)) { RegCloseKey(hkKey); } if (pszName) { PortFree(pszName); } } return dwErr; } // // Sets the usage of the given port // DWORD PortSetUsage( IN HKEY hkPort, IN HANDLE hData) { DWORD dwErr = NO_ERROR, dwOne = 1; DWORD dwUsage = *((DWORD*)hData); PWCHAR pszVal = NULL; do { // Determine which value to set // if (dwUsage & MPRFLAG_PORT_Router) { pszVal = (PWCHAR)pszRegvalRouterUsage; } else if (dwUsage & MPRFLAG_PORT_Dialin) { pszVal = (PWCHAR)pszRegvalDialinUsage; } else { dwErr = ERROR_CAN_NOT_COMPLETE; break; } PortTrace("PortSetUsage: Setting: %ls", pszVal); // Set the value // dwErr = RegSetValueExW( hkPort, pszVal, 0, REG_DWORD, (BYTE*)&dwOne, sizeof(dwOne)); if (dwErr != NO_ERROR) { break; } } while (FALSE); // Cleanup { } return dwErr; } // // Callback function for PortEnumRegistrySubKeys that finds the // key in the registry suitable to have its port usage manipulated. // DWORD PortGetConfigKey( IN PWCHAR pszName, // sub key name IN HKEY hKey, // sub key IN HANDLE hData) { PORTGETCONFIGKEYDATA* pData = (PORTGETCONFIGKEYDATA*)hData; HKEY hkChild = NULL; DWORD dwErr = NO_ERROR; PortTrace("PortGetConfigKey: Entered: %ls", pszName); switch (pData->dwRootId) { case MPRPORT_F_Adapters: { // We only want devices with WanEndPoints, otherwise // they aren't ras capable. // dwErr = RegQueryValueExW( hKey, (PWCHAR) pszWanEndpoints, NULL, NULL, NULL, NULL); if (dwErr != ERROR_SUCCESS) { dwErr = NO_ERROR; break; } // Call the callback. pData->pEnum(hKey, pData->hData); } break; case MPRPORT_F_Modems: { DWORD dwDisposition; // Open the appropriate child key // dwErr = RegCreateKeyEx( hKey, pszRegkeyMdmconfig, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkChild, &dwDisposition); if (dwErr != ERROR_SUCCESS) { dwErr = NO_ERROR; break; } // Call the callback pData->pEnum(hkChild, pData->hData); } break; } // Cleanup { if (hkChild) { RegCloseKey(hkChild); } } return dwErr; } // // Enumerates all ports // DWORD PortEnumPorts( IN RTRUPG_PORT_ENUM_FUNC pEnum, IN DWORD dwPortFlags, IN HANDLE hData) { DWORD dwErr = NO_ERROR; PORTGETCONFIGKEYDATA PortData, *pData = &PortData; PortTrace("PortEnumPorts entered"); do { // Initialize ZeroMemory(pData, sizeof(PORTGETCONFIGKEYDATA)); pData->pEnum = pEnum; pData->hData = hData; if (dwPortFlags & MPRPORT_F_Adapters) { // Set usage on the network adapters (pptp, l2tp will have // their port usages set through this) // PortTrace("PortEnumPorts: Enumerating adapters:"); pData->dwRootId = MPRPORT_F_Adapters; dwErr = PortEnumRegistrySubKeys( HKEY_LOCAL_MACHINE, (PWCHAR)pszRegkeyNetAdapters, PortGetConfigKey, (HANDLE)pData); if (dwErr != NO_ERROR) { break; } } if (dwPortFlags & MPRPORT_F_Modems) { // Set usage on modem devices // PortTrace("PortEnumPorts: Enumerating modems:"); pData->dwRootId = MPRPORT_F_Modems; dwErr = PortEnumRegistrySubKeys( HKEY_LOCAL_MACHINE, (PWCHAR)pszRegkeyModems, PortGetConfigKey, (HANDLE)pData); if (dwErr != NO_ERROR) { break; } } } while (FALSE); // Cleanup { } return dwErr; } // // Sets all ports on the machine to the given usage // DWORD APIENTRY MprPortSetUsage( IN DWORD dwUsage) { DWORD dwPortFlags = MPRPORT_F_Adapters | MPRPORT_F_Modems; if (dwUsage == MPRFLAG_PORT_NonVpnDialin) { dwPortFlags = MPRPORT_F_Modems; dwUsage = MPRFLAG_PORT_Dialin; } return PortEnumPorts(PortSetUsage, dwPortFlags, (HANDLE)&dwUsage); }