471 lines
11 KiB
C
471 lines
11 KiB
C
/************************************************************************
|
|
* *
|
|
* ports.c -- port api's for mprapi.dll *
|
|
* *
|
|
* Copyright (c) 1991-1999, Microsoft Corp. All rights reserved. *
|
|
* *
|
|
************************************************************************/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <mprapi.h>
|
|
#include <mprapip.h>
|
|
#include <stdio.h>
|
|
|
|
// 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);
|
|
}
|
|
|
|
|
|
|