Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1859 lines
52 KiB

/*****************************************************************************
******************************************************************************
**
**
** RAICShelp.c
** Contains the useful public entry points to an ICS-assistance library
** created for the Salem/PCHealth Remote Assistance feature in Whistler
**
** Dates:
** 11-1-2000 created by TomFr
** 11-17-2000 re-written as a DLL, had been an object.
** 2-15-20001 Changed to a static lib, support added for dpnathlp.dll
** 5-2-2001 Support added for dpnhupnp.dll & dpnhpast.dll
**
******************************************************************************
*****************************************************************************/
#define INIT_GUID
#include <windows.h>
#include <objbase.h>
#include <initguid.h>
#include <winsock2.h>
#include <MMSystem.h>
#include <WSIPX.h>
#include <Iphlpapi.h>
#include <stdlib.h>
#include <malloc.h>
#include "ICSutils.h"
#include "icshelpapi.h"
#include <dpnathlp.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
/*****************************************************************************
** Some global variables
*****************************************************************************/
// the mark of the beast...
#define NO_ICS_HANDLE 0x666
#define ICS_HANDLE_OFFSET 0x4500
long g_waitDuration=120000;
BOOL g_boolIcsPresent = FALSE;
BOOL g_boolFwPresent = FALSE;
BOOL g_boolIcsOnThisMachine = FALSE;
BOOL g_boolIcsFound = FALSE;
BOOL g_boolInitialized = FALSE;
BOOL g_StopFlag = FALSE;
SOCKADDR_IN g_saddrLocal;
char *g_lpszWierdICSAddress = NULL;
HANDLE g_hWorkerThread = 0;
HANDLE g_hStopThreadEvent=NULL;
HANDLE g_hAlertEvent=NULL;
int g_iPort;
HMODULE g_hModDpNatHlp = NULL;
PDIRECTPLAYNATHELP g_pDPNH = NULL;
char g_szPublicAddr[45];
char *g_lpszDllName = "NULL";
char szInternal[]="internal";
//
// IP notify thread globals
//
HANDLE g_IpNotifyThread;
DWORD g_IpNotifyThreadId;
HANDLE g_IpNotifyEvent;
HANDLE g_IpNotifyHandle = NULL;
//OVERLAPPED g_IpNotifyOverlapped;
DWORD WINAPI IPHlpThread(PVOID ContextPtr);
typedef struct _MAPHANDLES {
int iMapped;
DPNHHANDLE hMapped[16];
} MAPHANDLES, *PMAPHANDLES;
int g_iPortHandles=0;
PMAPHANDLES *g_PortHandles=NULL;
int iDbgFileHandle;
DWORD gDllFlag = 0xff;
typedef struct _SUPDLLS {
char *szDllName;
BOOL bUsesUpnp; // TRUE if we ICS supports UPnP
} SUPDLLS, *PSUPDLLS;
SUPDLLS strDpHelp[] =
{
{"dpnhupnp.dll", TRUE},
{"dpnhpast.dll", FALSE},
{NULL, FALSE}
};
/******* USEFULL STUFF **********/
#ifndef ARRAYSIZE
#define ARRAYSIZE(x) sizeof(x)/sizeof(x[0])
#endif
// forward declares...
int GetTsPort(void);
DWORD CloseDpnh(HMODULE *, PDIRECTPLAYNATHELP *);
int GetAllAdapters(int *iFound, int iMax, SOCKADDR_IN *sktArray);
/****************************************************************************
**
** DumpLibHr-
** Gives us debug spew for the HRESULTS coming back from DPNATHLP.DLL
**
****************************************************************************/
void DumpLibHr(HRESULT hr)
{
char *pErr = NULL;
char scr[400];
switch (hr){
case DPNH_OK:
pErr = "DPNH_OK";
break;
case DPNHSUCCESS_ADDRESSESCHANGED:
pErr = "DPNHSUCCESS_ADDRESSESCHANGED";
break;
case DPNHERR_ALREADYINITIALIZED:
pErr = "DPNHERR_ALREADYINITIALIZED";
break;
case DPNHERR_BUFFERTOOSMALL:
pErr = "DPNHERR_BUFFERTOOSMALL";
break;
case DPNHERR_GENERIC:
pErr = "DPNHERR_GENERIC";
break;
case DPNHERR_INVALIDFLAGS:
pErr = "DPNHERR_INVALIDFLAGS";
break;
case DPNHERR_INVALIDOBJECT:
pErr = "DPNHERR_INVALIDOBJECT";
break;
case DPNHERR_INVALIDPARAM:
pErr = "DPNHERR_INVALIDPARAM";
break;
case DPNHERR_INVALIDPOINTER:
pErr = "DPNHERR_INVALIDPOINTER";
break;
case DPNHERR_NOMAPPING:
pErr = "DPNHERR_NOMAPPING";
break;
case DPNHERR_NOMAPPINGBUTPRIVATE:
pErr = "DPNHERR_NOMAPPINGBUTPRIVATE";
break;
case DPNHERR_NOTINITIALIZED:
pErr = "DPNHERR_NOTINITIALIZED";
break;
case DPNHERR_OUTOFMEMORY:
pErr = "DPNHERR_OUTOFMEMORY";
break;
case DPNHERR_PORTALREADYREGISTERED:
pErr = "DPNHERR_PORTALREADYREGISTERED";
break;
case DPNHERR_PORTUNAVAILABLE:
pErr = "DPNHERR_PORTUNAVAILABLE";
break;
case DPNHERR_SERVERNOTAVAILABLE:
pErr = "DPNHERR_SERVERNOTAVAILABLE";
break;
case DPNHERR_UPDATESERVERSTATUS:
pErr = "DPNHERR_UPDATESERVERSTATUS";
break;
default:
wsprintfA(scr, "unknown error: 0x%x", hr);
pErr = scr;
break;
};
IMPORTANT_MSG((L"DpNatHlp result=%S", pErr));
}
/****************************************************************************
**
** GetAllAdapters
**
****************************************************************************/
int GetAllAdapters(int *iFound, int iMax, SOCKADDR_IN *sktArray)
{
PIP_ADAPTER_INFO p;
PIP_ADDR_STRING ps;
DWORD dw;
ULONG ulSize = 0;
int i=0;
PIP_ADAPTER_INFO pAdpInfo = NULL;
if (!iFound || !sktArray) return 1;
*iFound = 0;
ZeroMemory(sktArray, sizeof(SOCKADDR) * iMax);
dw = GetAdaptersInfo(
pAdpInfo,
&ulSize );
if( dw == ERROR_BUFFER_OVERFLOW )
{
pAdpInfo = (IP_ADAPTER_INFO*)malloc(ulSize);
if (!pAdpInfo)
{
INTERESTING_MSG((L"GetAddr malloc failed"));
return 1;
}
dw = GetAdaptersInfo(
pAdpInfo,
&ulSize);
if (dw != ERROR_SUCCESS)
{
INTERESTING_MSG((L"GetAdaptersInfo failed"));
free(pAdpInfo);
return 1;
}
for(p=pAdpInfo; p!=NULL; p=p->Next)
{
for(ps = &(p->IpAddressList); ps; ps=ps->Next)
{
if (strcmp(ps->IpAddress.String, "0.0.0.0") != 0 && i < iMax)
{
sktArray[i].sin_family = AF_INET;
sktArray[i].sin_addr.S_un.S_addr = inet_addr(ps->IpAddress.String);
TRIVIAL_MSG((L"Found adapter #%d at [%S]", i+1, ps->IpAddress.String));
i++;
}
}
}
*iFound = i;
TRIVIAL_MSG((L"GetAllAdapters- %d found", *iFound));
free(pAdpInfo);
return 0;
}
INTERESTING_MSG((L"GetAdaptersInfo failed"));
return 1;
}
/****************************************************************************
**
** OpenPort(int port)
** if there is no ICS available, then we should just return...
**
** Of course, we save away the Port, as it goes back in the
** FetchAllAddresses call, as the formatted "port" whenever a
** different one is not specified.
**
****************************************************************************/
DWORD APIENTRY OpenPort(int Port)
{
DWORD dwRet = (int)-1;
TRIVIAL_MSG((L"OpenPort(%d)", Port ));
if (!g_boolInitialized)
{
HEINOUS_E_MSG((L"ERROR: OpenPort- library not initialized"));
return 0;
}
// save away for later retrieval
g_iPort = Port;
if (g_pDPNH && g_PortHandles)
{
HRESULT hr=0;
int i;
DPNHHANDLE *pHnd;
SOCKADDR_IN lSockAddr[16];
PMAPHANDLES hMap;
for (i=0;i<g_iPortHandles && g_PortHandles[i] != NULL; i++);
// are we running outta memory?
// then double size of array
if (i >= g_iPortHandles)
{
int new_handlecnt = g_iPortHandles*2;
PMAPHANDLES *new_PortHandles = (PMAPHANDLES *)malloc(new_handlecnt * sizeof(PMAPHANDLES));
if (new_PortHandles)
{
INTERESTING_MSG((L"Needed new handle memory: %d of %d used up, now requesting %d", i, g_iPortHandles, new_handlecnt));
ZeroMemory(new_PortHandles, new_handlecnt * sizeof(PMAPHANDLES));
CopyMemory(new_PortHandles, g_PortHandles, g_iPortHandles * sizeof(PMAPHANDLES));
free(g_PortHandles);
g_PortHandles = new_PortHandles;
i = g_iPortHandles;
g_iPortHandles = new_handlecnt;
}
else
{
// we have no more memory for mappings!
// should never hit this, unless we are leaking...
HEINOUS_E_MSG((L"Out of table space in OpenPort"));
return 0;
}
}
// now we have a pointer for our handle array
hMap = (PMAPHANDLES)malloc(sizeof(MAPHANDLES));
if (!hMap)
{
IMPORTANT_MSG((L"out of memory in OpenPort"));
dwRet = 0;
goto done;
}
g_PortHandles[i] = hMap;
dwRet = ICS_HANDLE_OFFSET + i;
// get adapters
if( GetAllAdapters(&hMap->iMapped, ARRAYSIZE(lSockAddr), &lSockAddr[0]) == 1 )
{
// an error occurred
INTERESTING_MSG((L"OpenPort@GetAllAdapters failed"));
dwRet = 0;
goto done;
}
TRIVIAL_MSG((L"GetAllAdapters found %d adapters to deal with", hMap->iMapped));
/* Now we cycle through all the found adapters and get a mapping for each
* This insures that the ICF is opened on all adapters...
*/
for (i = 0; i < hMap->iMapped; i++)
{
pHnd = &hMap->hMapped[i];
lSockAddr[i].sin_port = ntohs((unsigned)Port);
hr = IDirectPlayNATHelp_RegisterPorts(g_pDPNH,
(SOCKADDR *)&lSockAddr[i], sizeof(lSockAddr[0]), 1,
30000, pHnd, DPNHREGISTERPORTS_TCP);
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"RegisterPorts failed in OpenPort for adapter #%d, ", i ));
DumpLibHr(hr);
}
else
{
TRIVIAL_MSG((L"OpenPort Assigned: 0x%x", *pHnd));
}
}
}
else
{
dwRet = NO_ICS_HANDLE;
TRIVIAL_MSG((L"OpenPort- no ICS found"));
}
done:
TRIVIAL_MSG((L"OpenPort- returns 0x%x", dwRet ));
return dwRet;
}
/****************************************************************************
**
** Called to close a port, whenever a ticket is expired or closed.
**
****************************************************************************/
DWORD APIENTRY ClosePort(DWORD MapHandle)
{
DWORD dwRet = ERROR_SUCCESS;
DWORD dwIndex;
TRIVIAL_MSG((L"ClosePort(0x%x)", MapHandle ));
if (!g_boolInitialized)
{
HEINOUS_E_MSG((L"ERROR: ClosePort- library not initialized"));
return ERROR_INVALID_PARAMETER;
}
// if we didn't open this thru the ICS, then just return
if (!g_pDPNH && MapHandle == NO_ICS_HANDLE)
{
return ERROR_SUCCESS;
}
dwIndex = MapHandle - ICS_HANDLE_OFFSET;
if (g_pDPNH && dwIndex < (DWORD)g_iPortHandles)
{
HRESULT hr=0;
int i;
PMAPHANDLES pMap = g_PortHandles[dwIndex];
if (pMap)
{
TRIVIAL_MSG((L"closing %d port mappings", pMap->iMapped));
for (i = 0; i < pMap->iMapped; i++)
{
hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, pMap->hMapped[i], 0);
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"DeregisterPorts failed in ClosePort for handle 0x%x", pMap->hMapped[i]));
DumpLibHr(hr);
dwRet = ERROR_INVALID_ACCESS;
}
}
// remove the handle from our array
free(g_PortHandles[dwIndex]);
g_PortHandles[dwIndex] = NULL;
}
else
{
IMPORTANT_MSG((L"Port handle mapping corrupted in ClosePort!!"));
dwRet = ERROR_INVALID_PARAMETER;
}
}
else
{
IMPORTANT_MSG((L"Bad handle passed into ClosePort!!"));
dwRet = ERROR_INVALID_PARAMETER;
}
TRIVIAL_MSG((L"ClosePort returning 0x%x", dwRet ));
return(dwRet);
}
/****************************************************************************
**
** FetchAllAddresses
** Returns a string listing all the valid IP addresses for the machine
** Formatting details:
** 1. Each address is seperated with a ";" (semicolon)
** 2. Each address consists of the "1.2.3.4", and is followed by ":p"
** where the colon is followed by the port number
**
****************************************************************************/
DWORD APIENTRY FetchAllAddresses(WCHAR *lpszAddr, int iBufSize)
{
return FetchAllAddressesEx(lpszAddr, iBufSize, IPF_ADD_DNS);
}
/****************************************************************************
**
** CloseAllPorts
** Does just that- closes all port mappings that have been opened
**
****************************************************************************/
DWORD APIENTRY CloseAllOpenPorts(void)
{
DWORD dwRet = 1;
int iClosed=0;
INTERESTING_MSG((L"CloseAllOpenPorts()" ));
if (g_pDPNH)
{
HRESULT hr=0;
int i;
// call DPNATHLP to unregister the mapping
// then remove the handle from our array
for (i = 0; i < g_iPortHandles; i++)
{
if (g_PortHandles[i])
{
PMAPHANDLES pMap = g_PortHandles[i];
int j;
for (j = 0; j < pMap->iMapped; j++)
{
hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, pMap->hMapped[j], 0);
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"DeregisterPorts failed in CloseAllOpenPorts"));
DumpLibHr(hr);
}
}
iClosed++;
free(g_PortHandles[i]);
g_PortHandles[i] = 0;
}
}
}
else
{
IMPORTANT_MSG((L"IDirectPlay interface not initialized in CloseAllOpenPorts!!"));
dwRet = ERROR_INVALID_ACCESS;
}
if (iClosed) TRIVIAL_MSG((L"Closed %d open ports", iClosed));
return(dwRet);
}
/****************************************************************************
**
** The worker thread for use with the DPHATHLP.DLL.
**
** This keeps the leases updated on any open
** port assignments. Eventually, this will also check & update the sessmgr
** when the ICS comes & goes, or when the address list changes.
**
****************************************************************************/
DWORD WINAPI DpNatHlpThread(PVOID ContextPtr)
{
DWORD dwRet=1;
DWORD dwWaitResult=WAIT_TIMEOUT;
long l_waitTime = g_waitDuration;
TRIVIAL_MSG((L"+++ DpNatHlpThread()" ));
/*
* The 2 minute wait loop
*/
while(dwWaitResult == WAIT_TIMEOUT)
{
DWORD dwTime;
if (g_pDPNH)
{
HRESULT hr;
DPNHCAPS lCaps;
/* Call GetCaps to renew all open leases */
lCaps.dwSize = sizeof(lCaps);
hr = IDirectPlayNATHelp_GetCaps(g_pDPNH, &lCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
if (hr == DPNH_OK || hr == DPNHSUCCESS_ADDRESSESCHANGED)
{
if (hr == DPNHSUCCESS_ADDRESSESCHANGED)
{
TRIVIAL_MSG((L"+++ ICS address changed"));
if (g_hAlertEvent)
SetEvent(g_hAlertEvent);
}
// else
// TRIVIAL_MSG((L"+++ ICS address change not found"));
if (lCaps.dwRecommendedGetCapsInterval)
l_waitTime = min(g_waitDuration, (long)lCaps.dwRecommendedGetCapsInterval);
}
else
{
IMPORTANT_MSG((L"+++ GetCaps failed in DpNatHlpThread"));
DumpLibHr(hr);
}
}
dwWaitResult = WaitForSingleObject(g_hStopThreadEvent, l_waitTime);
}
TRIVIAL_MSG((L"+++ DpNatHlpThread shutting down"));
/*
* Then the shutdown code
* free all memory
* then close out DPNATHLP.DLL
* and return all objects
*/
CloseDpnh(&g_hModDpNatHlp, &g_pDPNH);
CloseHandle(g_hStopThreadEvent);
TRIVIAL_MSG((L"+++ DpNatHlpThread() returning 0x%x", dwRet ));
WSACleanup();
ExitThread(dwRet);
// of course we never get this far...
return(dwRet);
}
BOOL GetUnusedPort(USHORT *pPort, SOCKET *pSocket)
{
SOCKADDR sa;
SOCKET s;
ULONG icmd;
int ilen, status;
s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (s == INVALID_SOCKET)
{
INTERESTING_MSG((L"Failed to create socket: %d",WSAGetLastError()));
return FALSE;
}
//Bind the socket to a dynamically assigned port.
memset(&sa,0,sizeof(sa));
sa.sa_family=AF_INET;
status = bind(s,&sa,sizeof(sa));
if (status != NO_ERROR)
{
closesocket(s);
return FALSE;
}
ilen = sizeof(sa);
status = getsockname(s, &sa, &ilen);
if (status)
{
INTERESTING_MSG((L"getsockname failed 0x%x", status));
closesocket(s);
return FALSE;
}
else
{
*pPort = ntohs((*((SOCKADDR_IN *) &sa)).sin_port);
*pSocket = s;
INTERESTING_MSG((L"found unused port=%d", *pPort));
}
return TRUE;
}
/****************************************************************************
**
** This will close the NAT DLL
**
****************************************************************************/
DWORD CloseDpnh(HMODULE *hMod, PDIRECTPLAYNATHELP *pDirectPlayNATHelp)
{
DWORD dwRet = ERROR_SUCCESS;
if (pDirectPlayNATHelp && *pDirectPlayNATHelp)
{
HRESULT hr = IDirectPlayNATHelp_Close(*pDirectPlayNATHelp, 0);
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"IDirectPlayNATHelp_Close failed"));
DumpLibHr(hr);
}
hr = IDirectPlayNATHelp_Release(*pDirectPlayNATHelp);
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"IDirectPlayNATHelp_Release failed"));
DumpLibHr(hr);
}
*pDirectPlayNATHelp = 0;
}
if (hMod && *hMod)
{
FreeLibrary(*hMod);
*hMod = 0;
}
return dwRet;
}
/****************************************************************************
**
** This will load up each DLL and return the capabilities of it...
**
****************************************************************************/
DWORD LoadDpnh(char *szDll, HMODULE *hMod, PDIRECTPLAYNATHELP *pDPnh, DWORD *dwCaps)
{
DPNHCAPS dpnhCaps;
DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
PFN_DIRECTPLAYNATHELPCREATE pfnDirectPlayNATHelpCreate;
HRESULT hr;
TRIVIAL_MSG((L"starting LoadDpnh for %S", szDll));
/* Sanity check the params... */
if (!szDll || !hMod || !pDPnh || !dwCaps)
{
IMPORTANT_MSG((L"ERROR: bad params passed to LoadDpnh, cannot continue"));
dwRet = ERROR_INVALID_PARAMETER;
goto done;
}
/* now clear all values returned */
*hMod = 0;
*pDPnh = NULL;
*dwCaps = 0;
*hMod = LoadLibraryA(szDll);
if (!*hMod)
{
IMPORTANT_MSG((L"ERROR:%S could not be found", szDll));
dwRet = ERROR_FILE_NOT_FOUND;
goto done;
}
pfnDirectPlayNATHelpCreate = (PFN_DIRECTPLAYNATHELPCREATE) GetProcAddress(*hMod, "DirectPlayNATHelpCreate");
if (!pfnDirectPlayNATHelpCreate)
{
IMPORTANT_MSG((L"\"DirectPlayNATHelpCreate\" proc in %S could not be found", szDll));
FreeLibrary(*hMod);
*hMod = 0;
dwRet = ERROR_INVALID_FUNCTION;
goto done;
}
hr = pfnDirectPlayNATHelpCreate(&IID_IDirectPlayNATHelp,
(void**) (pDPnh));
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"DirectPlayNATHelpCreate failed in %S", szDll));
DumpLibHr(hr);
FreeLibrary(*hMod);
*hMod = 0;
dwRet = ERROR_BAD_UNIT;
goto done;
}
hr = IDirectPlayNATHelp_Initialize(*pDPnh, 0);
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"IDirectPlayNATHelp_Initialize failed in %S", szDll));
DumpLibHr(hr);
CloseDpnh( hMod , pDPnh );
// FreeLibrary(*hMod);
*hMod = 0;
dwRet = ERROR_BAD_UNIT;
goto done;
}
/* Get capabilities of NAT server */
dpnhCaps.dwSize = sizeof(dpnhCaps);
hr = IDirectPlayNATHelp_GetCaps(*pDPnh, &dpnhCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
if (hr != DPNH_OK && hr != DPNHSUCCESS_ADDRESSESCHANGED)
{
IMPORTANT_MSG((L"IDirectPlayNATHelp_GetCaps failed"));
DumpLibHr(hr);
CloseDpnh(hMod, pDPnh);
dwRet = ERROR_BAD_UNIT;
goto done;
}
*dwCaps = dpnhCaps.dwFlags;
dwRet = ERROR_SUCCESS;
done:
TRIVIAL_MSG((L"done with LoadDpnh, result=0x%x caps=0x%x for %S", dwRet, dwCaps?*dwCaps:0, szDll?szDll:"NULL"));
return dwRet;
}
DWORD GetAddr(SOCKADDR_IN *saddr)
{
PIP_ADAPTER_INFO p;
PIP_ADDR_STRING ps;
DWORD dw;
ULONG ulSize = 0;
PIP_ADAPTER_INFO pAdpInfo = NULL;
dw = GetAdaptersInfo(
pAdpInfo,
&ulSize );
if( dw == ERROR_BUFFER_OVERFLOW )
{
pAdpInfo = (IP_ADAPTER_INFO*)malloc(ulSize);
if (!pAdpInfo)
{
INTERESTING_MSG((L"GetAddr malloc failed"));
return 1;
}
dw = GetAdaptersInfo(
pAdpInfo,
&ulSize);
if (dw != ERROR_SUCCESS)
{
INTERESTING_MSG((L"GetAdaptersInfo failed"));
free(pAdpInfo);
return 1;
}
for(p=pAdpInfo; p!=NULL; p=p->Next)
{
for(ps = &(p->IpAddressList); ps; ps=ps->Next)
{
if (strcmp(ps->IpAddress.String, "0.0.0.0") != 0)
{
// blah blah blah
saddr->sin_addr.S_un.S_addr = inet_addr(ps->IpAddress.String);
TRIVIAL_MSG((L"Initializing local address to [%S]", ps->IpAddress.String));
free(pAdpInfo);
return 0;
}
}
}
INTERESTING_MSG((L"GetAddr- none found"));
free(pAdpInfo);
return 1;
}
INTERESTING_MSG((L"GetAdaptersInfo failed"));
return 1;
}
/****************************************************************************
**
** This should initialize the ICS library for use with the DirectPlay
** ICS/NAT helper DLL.
**
****************************************************************************/
DWORD StartDpNatHlp(void)
{
DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
DWORD dwUPNP = ERROR_CALL_NOT_IMPLEMENTED, dwPAST = ERROR_CALL_NOT_IMPLEMENTED, dwCapsUPNP=0, dwCapsPAST=0;
HRESULT hr;
HMODULE hModUPNP=0, hModPAST=0;
PFN_DIRECTPLAYNATHELPCREATE pfnDirectPlayNATHelpCreate;
PDIRECTPLAYNATHELP pDirectPlayNATHelpUPNP=NULL, pDirectPlayNATHelpPAST=NULL;
// start out with no public address
g_szPublicAddr[0] = 0;
/* load up both DLLs so that we can compare capabilities */
if (gDllFlag & 1) dwUPNP = LoadDpnh("dpnhupnp.dll", &hModUPNP, &pDirectPlayNATHelpUPNP, &dwCapsUPNP);
if (gDllFlag & 2) dwPAST = LoadDpnh("dpnhpast.dll", &hModPAST, &pDirectPlayNATHelpPAST, &dwCapsPAST);
if (dwUPNP != ERROR_SUCCESS && dwPAST != ERROR_SUCCESS)
{
IMPORTANT_MSG((L"ERROR: could not load either NAT dll"));
if (!gDllFlag)
dwRet = ERROR_SUCCESS;
goto done;
}
#if 0 // fix for #418776
/* If no NAT is found, then close both and go away */
if (!(dwCapsUPNP & (DPNHCAPSFLAG_GATEWAYPRESENT | DPNHCAPSFLAG_LOCALFIREWALLPRESENT)) &&
!(dwCapsPAST & (DPNHCAPSFLAG_GATEWAYPRESENT | DPNHCAPSFLAG_LOCALFIREWALLPRESENT)))
{
CloseDpnh(&hModUPNP, &pDirectPlayNATHelpUPNP);
CloseDpnh(&hModPAST, &pDirectPlayNATHelpPAST);
dwRet = ERROR_BAD_UNIT;
TRIVIAL_MSG((L"No NAT or firewall device found"));
goto done;
}
#endif
/*
* Now we must compare the capabilities of the two NAT interfaces and select the most
* "capable" one. If it is a tie, then we should choose the UPNP form, as that will
* be more stable.
*/
if ((dwCapsPAST & DPNHCAPSFLAG_GATEWAYPRESENT) &&
!(dwCapsUPNP & DPNHCAPSFLAG_GATEWAYPRESENT))
{
// there must be a WinME ICS box out there- we better use PAST
g_boolIcsPresent = TRUE;
TRIVIAL_MSG((L"WinME ICS discovered, using PAST"));
if (dwCapsPAST & DPNHCAPSFLAG_LOCALFIREWALLPRESENT)
{
TRIVIAL_MSG((L"local firewall found"));
g_boolFwPresent = TRUE;
}
g_pDPNH = pDirectPlayNATHelpPAST;
g_hModDpNatHlp = hModPAST;
g_lpszDllName = "dpnhpast.dll";
CloseDpnh(&hModUPNP, &pDirectPlayNATHelpUPNP);
}
else if ((dwCapsPAST & DPNHCAPSFLAG_PUBLICADDRESSAVAILABLE) &&
!(dwCapsUPNP & DPNHCAPSFLAG_PUBLICADDRESSAVAILABLE))
{
// that blasted UPNP is hung again- we better use PAST
g_boolIcsPresent = TRUE;
TRIVIAL_MSG((L"Hung UPnP discovered, using PAST"));
if (dwCapsPAST & DPNHCAPSFLAG_LOCALFIREWALLPRESENT)
{
TRIVIAL_MSG((L"local firewall found"));
g_boolFwPresent = TRUE;
}
g_pDPNH = pDirectPlayNATHelpPAST;
g_hModDpNatHlp = hModPAST;
g_lpszDllName = "dpnhpast.dll";
CloseDpnh(&hModUPNP, &pDirectPlayNATHelpUPNP);
}
else
{
// default to UPNP
if (dwCapsUPNP & DPNHCAPSFLAG_GATEWAYPRESENT)
{
TRIVIAL_MSG((L"UPnP NAT gateway found"));
g_boolIcsPresent = TRUE;
}
if (dwCapsUPNP & DPNHCAPSFLAG_LOCALFIREWALLPRESENT)
{
TRIVIAL_MSG((L"local firewall found"));
g_boolFwPresent = TRUE;
}
if (dwCapsUPNP & DPNHCAPSFLAG_GATEWAYISLOCAL)
g_boolIcsOnThisMachine = TRUE;
g_lpszDllName = "dpnhupnp.dll";
g_pDPNH = pDirectPlayNATHelpUPNP;
g_hModDpNatHlp = hModUPNP;
CloseDpnh(&hModPAST, &pDirectPlayNATHelpPAST);
}
dwRet = ERROR_SUCCESS;
if (g_boolIcsPresent)
{
// PIP_ADAPTER_INFO pAdpInfo = NULL;
SOCKADDR_IN saddrOurLAN;
PMIB_IPADDRTABLE pmib=NULL;
ULONG ulSize = 0;
DWORD dw;
DPNHHANDLE dpHnd;
USHORT port;
SOCKET s;
dwRet = ERROR_SUCCESS;
ZeroMemory(&saddrOurLAN, sizeof(saddrOurLAN));
saddrOurLAN.sin_family = AF_INET;
saddrOurLAN.sin_addr.S_un.S_addr = INADDR_ANY;
memcpy(&g_saddrLocal, &saddrOurLAN, sizeof(saddrOurLAN));
GetAddr(&g_saddrLocal);
// Does the ICS have a public address?
// then we must discover the public address
if (!GetUnusedPort(&port, &s))
{
dwRet = ERROR_OUTOFMEMORY;
goto done;
}
saddrOurLAN.sin_port = port;
/* first we ask for a new mapping */
hr = IDirectPlayNATHelp_RegisterPorts(g_pDPNH,
(SOCKADDR *)&saddrOurLAN, sizeof(saddrOurLAN), 1,
30000, &dpHnd, DPNHREGISTERPORTS_TCP);
closesocket(s);
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"IDirectPlayNATHelp_RegisterPorts failed in StartDpNatHlp"));
DumpLibHr(hr);
}
else
{
/* we succeeded, so query for the address */
SOCKADDR_IN lsi;
DWORD dwSize, dwTypes;
TRIVIAL_MSG((L"IDirectPlayNATHelp_RegisterPorts Assigned: 0x%x", dpHnd));
dwSize = sizeof(lsi);
ZeroMemory(&lsi, dwSize);
hr = IDirectPlayNATHelp_GetRegisteredAddresses(g_pDPNH, dpHnd, (SOCKADDR *)&lsi,
&dwSize, &dwTypes, NULL, 0);
if (hr == DPNH_OK && dwSize)
{
wsprintfA(g_szPublicAddr, "%d.%d.%d.%d",
lsi.sin_addr.S_un.S_un_b.s_b1,
lsi.sin_addr.S_un.S_un_b.s_b2,
lsi.sin_addr.S_un.S_un_b.s_b3,
lsi.sin_addr.S_un.S_un_b.s_b4);
TRIVIAL_MSG((L"Public Address=[%S]", g_szPublicAddr ));
}
else
{
IMPORTANT_MSG((L"GetRegisteredAddresses[0x%x] failed, size=0x%x", dpHnd, dwSize));
DumpLibHr(hr);
}
/* close out the temp port we got */
hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, dpHnd, 0);
if (hr != DPNH_OK)
{
IMPORTANT_MSG((L"DeregisterPorts failed in StartDpNatHlp"));
DumpLibHr(hr);
dwRet = ERROR_INVALID_ACCESS;
}
}
}
done:
TRIVIAL_MSG((L"done with StartDpNatHlp, result=0x%x", dwRet));
return dwRet;
};
/****************************************************************************
**
** The first call to be made into this library. It is responsible for
** starting up all worker threads, initializing all memory and libs,
** and starting up the DPHLPAPI.DLL function (if found).
**
****************************************************************************/
DWORD APIENTRY StartICSLib(void)
{
WSADATA WsaData;
DWORD dwThreadId;
HANDLE hEvent, hThread;
HKEY hKey;
int sktRet = ERROR_SUCCESS;
// open reg key first, to get ALL the spew...
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\ICSHelper", 0, KEY_READ, &hKey))
{
DWORD dwSize;
dwSize = sizeof(gDbgFlag);
RegQueryValueEx(hKey, L"DebugSpew", NULL, NULL, (LPBYTE)&gDbgFlag, &dwSize);
dwSize = sizeof(gDllFlag);
RegQueryValueEx(hKey, L"ProtocolLimits", NULL, NULL, (LPBYTE)&gDllFlag, &dwSize);
dwSize = 0;
if (g_lpszWierdICSAddress)
{
free(g_lpszWierdICSAddress);
g_lpszWierdICSAddress= NULL;
}
RegQueryValueEx(hKey, L"NonStandardICSAddress", NULL, NULL, (LPBYTE)g_lpszWierdICSAddress, &dwSize);
if (dwSize)
{
g_lpszWierdICSAddress = malloc((dwSize+1) * sizeof(*g_lpszWierdICSAddress));
if( g_lpszWierdICSAddress == NULL )
{
RegCloseKey(hKey);
sktRet = ERROR_NOT_ENOUGH_MEMORY;
goto hard_clean_up;
}
RegQueryValueEx(hKey, L"NonStandardICSAddress", NULL, NULL, (LPBYTE)g_lpszWierdICSAddress, &dwSize);
}
g_waitDuration = 0;
dwSize = sizeof(g_waitDuration);
RegQueryValueEx(hKey, L"RetryTimeout", NULL, NULL, (LPBYTE)&g_waitDuration, &dwSize);
if (g_waitDuration)
g_waitDuration *= 1000;
else
g_waitDuration = 120000;
RegCloseKey(hKey);
}
// should we create a debug log file?
if (gDbgFlag & DBG_MSG_DEST_FILE)
{
WCHAR *szLogfileName=NULL;
WCHAR *szLogname=L"\\SalemICSHelper.log";
int iChars;
iChars = GetSystemDirectory(szLogfileName, 0);
iChars += lstrlen(szLogname);
iChars += 4;
szLogfileName = (WCHAR *)malloc(iChars * sizeof(WCHAR));
if (szLogfileName)
{
ZeroMemory(szLogfileName, iChars * sizeof(WCHAR));
GetSystemDirectory(szLogfileName, iChars);
lstrcat(szLogfileName, szLogname);
iDbgFileHandle = _wopen(szLogfileName, _O_APPEND | _O_BINARY | _O_RDWR, 0);
if (-1 != iDbgFileHandle)
{
OutputDebugStringA("opened debug log file\n");
}
else
{
unsigned char UniCode[2] = {0xff, 0xfe};
// we must create the file
OutputDebugStringA("must create debug log file");
iDbgFileHandle = _wopen(szLogfileName, _O_BINARY | _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE);
if (-1 != iDbgFileHandle)
_write(iDbgFileHandle, &UniCode, sizeof(UniCode));
else
{
OutputDebugStringA("ERROR: failed to create debug log file");
iDbgFileHandle = 0;
}
}
free(szLogfileName);
}
}
g_iPort = GetTsPort();
g_iPortHandles = 256;
g_PortHandles = (PMAPHANDLES *)malloc(g_iPortHandles * sizeof(PMAPHANDLES));
if( g_PortHandles == NULL )
{
g_iPortHandles = 0;
sktRet = ERROR_NOT_ENOUGH_MEMORY;
goto hard_clean_up;
}
ZeroMemory(g_PortHandles, g_iPortHandles * sizeof(PMAPHANDLES));
TRIVIAL_MSG((L"StartICSLib(), using %d PortHandles", g_iPortHandles));
if (g_boolInitialized)
{
HEINOUS_E_MSG((L"ERROR: StartICSLib called twice"));
sktRet = ERROR_ALREADY_INITIALIZED;
goto hard_clean_up;
}
else
g_boolInitialized = TRUE;
// create an event for later use by the daemon thread
hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!hEvent)
{
IMPORTANT_MSG((L"Could not create an event for RSIP worker thread, err=0x%x", GetLastError()));
sktRet = GetLastError();
goto hard_clean_up;
}
g_hStopThreadEvent = hEvent;
if (0 != WSAStartup(MAKEWORD(2,2), &WsaData))
{
if (0 != (sktRet = WSAStartup(MAKEWORD(2,0), &WsaData)))
{
IMPORTANT_MSG((L"WSAStartup failed:"));
goto hard_clean_up;
}
}
if (ERROR_SUCCESS == StartDpNatHlp())
{
// start RSIP daemon process, which will do all the work
hThread = CreateThread( NULL, // SD- not needed
0, // Stack Size
(LPTHREAD_START_ROUTINE)DpNatHlpThread,
NULL,
0,
&dwThreadId );
if (!hThread)
{
IMPORTANT_MSG((L"Could not create RSIP worker thread, err=0x%x", GetLastError()));
sktRet = GetLastError();
goto hard_clean_up;
}
// save this for later, as we may need it in the close function
g_hWorkerThread = hThread;
}
TRIVIAL_MSG((L"StartICSLib() returning ERROR_SUCCESS"));
return(ERROR_SUCCESS);
hard_clean_up:
//
// free up all memory we created
// set all counters to zero
// make sure no threads are started
// return proper error
// act like stopics
if( g_hWorkerThread != NULL && g_hStopThreadEvent != NULL )
{
SetEvent( g_hStopThreadEvent );
WaitForSingleObject( g_hWorkerThread , 1000 );
CloseHandle( g_hWorkerThread );
g_hWorkerThread = NULL;
}
if( g_hStopThreadEvent != NULL )
{
CloseHandle( g_hStopThreadEvent );
g_hStopThreadEvent = NULL;
}
if( g_lpszWierdICSAddress != NULL )
{
free( g_lpszWierdICSAddress );
g_lpszWierdICSAddress = NULL;
}
if( g_PortHandles != NULL )
{
free( g_PortHandles );
g_PortHandles = NULL;
}
if( iDbgFileHandle != 0 )
{
_close( iDbgFileHandle );
iDbgFileHandle = 0;
}
return( sktRet );
}
/****************************************************************************
**
** The last call to be made into this library. Do not call any other
** function in this library after you call this!
**
****************************************************************************/
DWORD APIENTRY StopICSLib(void)
{
DWORD dwRet = ERROR_SUCCESS;
DWORD dwTmp;
TRIVIAL_MSG((L"StopICSLib()" ));
if (!g_boolInitialized)
{
HEINOUS_E_MSG((L"ERROR: StopICSLib- library not initialized"));
return ERROR_INVALID_PARAMETER;
}
// signal the worker threads, so that they will shut down
// kill the IP address change thread
g_StopFlag = TRUE;
if (g_IpNotifyHandle)
CancelIo(g_IpNotifyHandle);
// then stop the ICS lease-renewal thread.
if (g_hStopThreadEvent && g_hWorkerThread)
{
SetEvent(g_hStopThreadEvent);
// then wait for it to shutdown.
dwTmp = WaitForSingleObject(g_hWorkerThread, 15000);
if (dwTmp == WAIT_OBJECT_0)
TRIVIAL_MSG((L"ICS worker thread closed down normally"));
else if (dwTmp == WAIT_ABANDONED)
IMPORTANT_MSG((L"ICS worker thread did not complete in 15 seconds"));
else
IMPORTANT_MSG((L"WaitForWorkerThread failed"));
CloseHandle(g_hWorkerThread);
g_hWorkerThread = NULL;
}
else
WSACleanup();
TRIVIAL_MSG((L"StopICSLib() returning 0x%x", dwRet ));
if (iDbgFileHandle)
_close(iDbgFileHandle);
iDbgFileHandle = 0;
if (g_lpszWierdICSAddress)
free(g_lpszWierdICSAddress);
g_lpszWierdICSAddress = NULL;
if (g_PortHandles) free(g_PortHandles);
g_PortHandles = NULL;
g_boolInitialized = FALSE;
return(dwRet);
}
/****************************************************************************
**
** FetchAllAddressesEx
** Returns a string listing all the valid IP addresses for the machine
** controlled by a set of "flags". These are as follows:
** IPflags=
** IPF_ADD_DNS adds the DNS name to the IP list
** IPF_COMPRESS compresses the IP address list (exclusive w/ IPF_ADD_DNS)
** IPF_NO_SORT do not sort adapter IP list
**
** Formatting details:
** 1. Each address is seperated with a ";" (semicolon)
** 2. Each address consists of the "1.2.3.4", and is followed by ":p"
** where the colon is followed by the port number
**
****************************************************************************/
#define WCHAR_CNT 4096
DWORD APIENTRY FetchAllAddressesEx(WCHAR *lpszAddr, int iBufSize, int IPflags)
{
DWORD dwRet = 1;
WCHAR *AddressLst;
int iAddrLen;
BOOL bSort=FALSE;
int bufSizeLeft;
AddressLst = (WCHAR *) malloc(WCHAR_CNT * sizeof(WCHAR));
if (!AddressLst)
{
HEINOUS_E_MSG((L"Fatal error: malloc failed in FetchAllAddressesEx"));
return 0;
}
*AddressLst = 0;
INTERESTING_MSG((L"FetchAllAddressesEx()" ));
bufSizeLeft = WCHAR_CNT;
if (g_boolIcsPresent && g_pDPNH)
{
int i;
// gotta cycle through the g_PortHandles list...
for (i=0;i<g_iPortHandles; i++)
{
if (g_PortHandles[i])
{
HRESULT hr = E_FAIL;
SOCKADDR_IN lsi;
DWORD dwSize, dwTypes;
DPNHCAPS lCaps;
int j;
PMAPHANDLES pMap = g_PortHandles[i];
/*
* Call GetCaps so that we get an updated address list .
* Not sure why we would want any other kind...
*/
lCaps.dwSize = sizeof(lCaps);
hr = IDirectPlayNATHelp_GetCaps(g_pDPNH, &lCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
for (j=0; j < pMap->iMapped; j++)
{
dwSize = sizeof(lsi);
ZeroMemory(&lsi, dwSize);
hr = IDirectPlayNATHelp_GetRegisteredAddresses(g_pDPNH, pMap->hMapped[j], (SOCKADDR *)&lsi,
&dwSize, &dwTypes, NULL, 0);
if (hr == DPNH_OK && dwSize)
{
WCHAR scratch[32];
_snwprintf(scratch , 32 , L"%d.%d.%d.%d:%d;",
lsi.sin_addr.S_un.S_un_b.s_b1,
lsi.sin_addr.S_un.S_un_b.s_b2,
lsi.sin_addr.S_un.S_un_b.s_b3,
lsi.sin_addr.S_un.S_un_b.s_b4,
ntohs( lsi.sin_port ));
scratch[31] = 0;
bufSizeLeft -= wcslen( scratch );
if( bufSizeLeft > 0 )
{
wcscat(AddressLst, scratch);
AddressLst[ WCHAR_CNT - bufSizeLeft] = 0;
}
TRIVIAL_MSG((L"GetRegisteredAddresses(0x%x)=[%s]", g_PortHandles[i], scratch ));
}
else
{
IMPORTANT_MSG((L"GetRegisteredAddresses[0x%x] failed, size=0x%x", g_PortHandles[i], dwSize));
DumpLibHr(hr);
}
}
goto got_address;
}
}
}
else if (g_lpszWierdICSAddress)
{
_snwprintf( AddressLst , WCHAR_CNT , L"%s;", g_lpszWierdICSAddress);
AddressLst[ WCHAR_CNT - 1 ] = 0;
}
got_address:
iAddrLen = wcslen(AddressLst);
GetIPAddress(AddressLst+iAddrLen, WCHAR_CNT-iAddrLen, g_iPort);
//
// GetIPAddress could have taken some of our buffer space
// reduce bufSizeLeft appropriately
//
bufSizeLeft = WCHAR_CNT - wcslen(AddressLst);
if (IPflags & IPF_ADD_DNS)
{
WCHAR *DnsName=NULL;
DWORD dwNameSz=0;
GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, NULL, &dwNameSz);
dwNameSz++;
DnsName = (WCHAR *)malloc(dwNameSz * sizeof(WCHAR));
if (DnsName)
{
*DnsName = 0;
if (GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, DnsName, &dwNameSz))
{
//if ((dwNameSz + iAddrLen) < WCHAR_CNT-4)
if( ( ( int )dwNameSz ) < bufSizeLeft )
{
bufSizeLeft -= dwNameSz;
wcsncat( AddressLst, DnsName , dwNameSz );
AddressLst[ WCHAR_CNT - bufSizeLeft ] = 0;
}
if (g_iPort)
{
WCHAR scr[16];
_snwprintf(scr, 16 , L":%d", g_iPort);
scr[15] = 0;
bufSizeLeft -= wcslen( scr );
if( bufSizeLeft > 0 )
{
wcscat(AddressLst, scr);
AddressLst[ WCHAR_CNT - bufSizeLeft ] = 0;
}
}
}
free(DnsName);
}
}
if (!(IPflags & IPF_NO_SORT) && bSort)
{
WCHAR *lpStart;
WCHAR szLast[36];
int i=0;
TRIVIAL_MSG((L"Sorting address list : %s", AddressLst));
lpStart = AddressLst+iAddrLen;
while (*(lpStart+i) && *(lpStart+i) != L';')
{
szLast[i] = *(lpStart+i);
i++;
}
szLast[i++]=0;
wcscpy(lpStart, lpStart+i);
TRIVIAL_MSG((L"inter sort: %s, %s", AddressLst, szLast));
bufSizeLeft -= wcslen( szLast ) + 1; // 1 is for ';'
if( bufSizeLeft > 0 )
{
wcscat(AddressLst, L";");
wcscat(AddressLst, szLast);
AddressLst[ WCHAR_CNT - bufSizeLeft ] = 0;
}
TRIVIAL_MSG((L"sort done"));
}
dwRet = 1 + wcslen(AddressLst);
if (lpszAddr && iBufSize >= (int)dwRet)
memcpy(lpszAddr, AddressLst, dwRet*(sizeof(AddressLst[0])));
INTERESTING_MSG((L"Fetched all Ex-addresses:cnt=%d, sz=[%s]", dwRet, AddressLst));
free(AddressLst);
return dwRet;
}
// it is hard to imagine a machine with this many simultaneous connections, but it is possible, I suppose
#define RAS_CONNS 6
DWORD GetConnections()
{
DWORD dwRet;
RASCONN *lpRasConn, *lpFree;
DWORD lpcb, lpcConnections;
int i;
TRIVIAL_MSG((L"entered GetConnections"));
lpFree = NULL;
lpcb = RAS_CONNS * sizeof(RASCONN);
lpRasConn = (LPRASCONN) malloc(lpcb);
if (!lpRasConn) return 0;
lpFree = lpRasConn;
lpRasConn->dwSize = sizeof(RASCONN);
lpcConnections = RAS_CONNS;
dwRet = RasEnumConnections(lpRasConn, &lpcb, &lpcConnections);
if (dwRet != 0)
{
IMPORTANT_MSG((L"RasEnumConnections failed: Error = %d", dwRet));
free(lpFree);
return 0;
}
dwRet = 0;
TRIVIAL_MSG((L"Found %d connections", lpcConnections));
if (lpcConnections)
{
for (i = 0; i < (int)lpcConnections; i++)
{
TRIVIAL_MSG((L"Entry name: %s, type=%s", lpRasConn->szEntryName, lpRasConn->szDeviceType));
if (!_wcsicmp(lpRasConn->szDeviceType, RASDT_Modem ))
{
TRIVIAL_MSG((L"Found a modem (%s)", lpRasConn->szDeviceName));
dwRet |= 1;
}
else if (!_wcsicmp(lpRasConn->szDeviceType, RASDT_Vpn))
{
TRIVIAL_MSG((L"Found a VPN (%s)", lpRasConn->szDeviceName));
dwRet |= 2;
}
else
{
// probably ISDN, or something like that...
TRIVIAL_MSG((L"Found something else, (%s)", lpRasConn->szDeviceType));
dwRet |= 4;
}
lpRasConn++;
}
}
if (lpFree)
free(lpFree);
TRIVIAL_MSG((L"GetConnections returning 0x%x", dwRet));
return dwRet;
}
#undef RAS_CONNS
/****************************************************************************
**
** GetIcsStatus(PICSSTAT pStat)
** Returns a structure detailing much of what is going on inside this
** library. The dwSize entry must be filled in before calling this
** function. Use "sizeof(ICSSTAT))" to populate this.
**
****************************************************************************/
DWORD APIENTRY GetIcsStatus(PICSSTAT pStat)
{
DWORD dwSz;
if (!pStat || pStat->dwSize != sizeof( ICSSTAT ) )
{
HEINOUS_E_MSG((L"ERROR:Bad pointer or size passed in to GetIcsStatus"));
return ERROR_INVALID_PARAMETER;
}
// clear out the struct
dwSz = pStat->dwSize;
ZeroMemory(pStat, dwSz);
pStat->dwSize = dwSz;
pStat->bIcsFound = g_boolIcsPresent;
pStat->bFwFound = g_boolFwPresent;
pStat->bIcsServer = g_boolIcsOnThisMachine;
if (g_boolIcsPresent)
{
dwSz = sizeof( pStat->wszPubAddr ) / sizeof( WCHAR );
_snwprintf( pStat->wszPubAddr , dwSz , L"%S", g_szPublicAddr );
pStat->wszPubAddr[ dwSz - 1 ] = L'\0';
dwSz = sizeof( pStat->wszLocAddr ) / sizeof( WCHAR );
_snwprintf( pStat->wszLocAddr , dwSz , L"%d.%d.%d.%d",
g_saddrLocal.sin_addr.S_un.S_un_b.s_b1,
g_saddrLocal.sin_addr.S_un.S_un_b.s_b2,
g_saddrLocal.sin_addr.S_un.S_un_b.s_b3,
g_saddrLocal.sin_addr.S_un.S_un_b.s_b4);
pStat->wszLocAddr[ dwSz - 1 ] = L'\0';
dwSz = sizeof( pStat->wszDllName ) / sizeof( WCHAR );
_snwprintf( pStat->wszDllName , dwSz , L"%S", g_lpszDllName);
pStat->wszDllName[ dwSz - 1 ] = L'\0';
}
else
{
if( g_lpszWierdICSAddress != NULL )
{
dwSz = sizeof( pStat->wszPubAddr ) / sizeof( WCHAR );
_snwprintf( pStat->wszPubAddr , dwSz , L"%S", g_lpszWierdICSAddress);
pStat->wszPubAddr[ dwSz - 1 ] = L'\0';
}
// this is ok wszDllName is 32 characters long
wsprintf(pStat->wszDllName, L"none");
}
dwSz = GetConnections();
if (dwSz & 1)
pStat->bModemPresent = TRUE;
if (dwSz & 2)
pStat->bVpnPresent = TRUE;
return ERROR_SUCCESS;
}
#if 0 // bug id 547112 removing dead code
/****************************************************************************
**
** SetAlertEvent
** Pass in an event handle. Then, whenever the ICS changes state, I
** will signal that event.
**
****************************************************************************/
DWORD APIENTRY SetAlertEvent(HANDLE hEvent)
{
TRIVIAL_MSG((L"SetAlertEvent(0x%x)", hEvent));
if (!g_hAlertEvent && hEvent)
{
/* Our first entry here, so we should start up all our IO CompletionPort hooie... */
#if 0
//
// create event for overlapped I/O
//
g_IpNotifyEvent = CreateEvent(
NULL, // no security descriptor
TRUE, // manual reset event
FALSE, // start not signalled
L"g_IpNotifyEvent");
if ( !g_IpNotifyEvent )
{
DWORD status = GetLastError();
IMPORTANT_MSG((L"FAILED to create IP notify event = %d", status));
}
#endif
g_IpNotifyThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) IPHlpThread,
NULL,
0,
& g_IpNotifyThreadId
);
if ( !g_IpNotifyThread )
{
DWORD status = GetLastError();
IMPORTANT_MSG((L"FAILED to create IP notify thread = %d", status));
}
}
g_hAlertEvent = hEvent;
return ERROR_SUCCESS;
}
#endif
/*************************************************************************************
**
**
*************************************************************************************/
int GetTsPort(void)
{
DWORD dwRet = 3389;
HKEY hKey;
// open reg key first, to get ALL the spew...HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp", 0, KEY_READ, &hKey))
{
DWORD dwSize;
dwSize = sizeof(dwRet);
RegQueryValueEx(hKey, L"PortNumber", NULL, NULL, (LPBYTE)&dwRet, &dwSize);
RegCloseKey(hKey);
}
return dwRet;
}
#if 0
/*************************************************************************************
**
**
*************************************************************************************/
DWORD WINAPI IPHlpThread(PVOID ContextPtr)
{
DWORD status=0;
DWORD bytesRecvd;
BOOL fstartedNotify=FALSE;
BOOL fhaveIpChange = FALSE;
BOOL fsleep = FALSE;
HANDLE notifyHandle=0;
OVERLAPPED IpNotifyOverlapped;
TRIVIAL_MSG((L"*** IPHlpThread begins"));
g_IpNotifyHandle = NULL;
/*
* Then the wait loop
*/
while ( !g_StopFlag )
{
//
// spin protect
// - if error in previous NotifyAddrChange or
// GetOverlappedResult do short sleep to avoid
// chance of hard spin
//
if ( fsleep )
{
/* if signalled, it means quittin' time */
if (WAIT_TIMEOUT != WaitForSingleObject(g_hStopThreadEvent, 60000 ))
goto Done;
fsleep = FALSE;
}
if ( g_StopFlag )
{
goto Done;
}
if (notifyHandle)
{
// CloseHandle(notifyHandle);
notifyHandle = 0;
}
RtlZeroMemory(&IpNotifyOverlapped, sizeof(IpNotifyOverlapped) );
fstartedNotify = FALSE;
status = NotifyAddrChange(
& notifyHandle,
& IpNotifyOverlapped );
if ( status == ERROR_IO_PENDING )
{
TRIVIAL_MSG((L"*** NotifyAddrChange succeeded"));
g_IpNotifyHandle = notifyHandle;
fstartedNotify = TRUE;
}
else
{
IMPORTANT_MSG((L"*** NotifyAddrChange() FAILED\n\tstatus = %d\n\thandle = %d\n\toverlapped event = %d\n",status,notifyHandle,IpNotifyOverlapped.hEvent ));
fsleep = TRUE;
}
if ( fhaveIpChange )
{
INTERESTING_MSG((L"*** IP change detected"));
SetEvent(g_hAlertEvent);
fhaveIpChange = FALSE;
}
//
// anti-spin protection
// - 15 second sleep between any notifications
//
if (WAIT_TIMEOUT != WaitForSingleObject(g_hStopThreadEvent, 15000 ))
goto Done;
//
// wait on notification
// - save notification result
// - sleep on error, but never if notification
//
if ( fstartedNotify )
{
fhaveIpChange = GetOverlappedResult(
g_IpNotifyHandle,
& IpNotifyOverlapped,
& bytesRecvd,
TRUE // wait
);
if ( !fhaveIpChange )
{
status = GetLastError();
fsleep = TRUE;
IMPORTANT_MSG((L"*** GetOverlappedResult() status = 0x%x",status ));
}
else
{
TRIVIAL_MSG((L"*** GetOverlappedResult() found change"));
}
}
}
Done:
TRIVIAL_MSG((L"*** Stop IP Notify thread shutdown" ));
if ( g_IpNotifyHandle )
{
CloseHandle(g_IpNotifyHandle);
g_IpNotifyHandle = NULL;
}
return( status );
}
#endif