Source code of Windows XP (NT5)
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.

2158 lines
54 KiB

  1. /*****************************************************************************
  2. ******************************************************************************
  3. **
  4. **
  5. ** RAICShelp.c
  6. ** Contains the useful public entry points to an ICS-assistance library
  7. ** created for the Salem/PCHealth Remote Assistance feature in Whistler
  8. **
  9. ** Dates:
  10. ** 11-1-2000 created by TomFr
  11. ** 11-17-2000 re-written as a DLL, had been an object.
  12. ** 2-15-20001 Changed to a static lib, support added for dpnathlp.dll
  13. ** 5-2-2001 Support added for dpnhupnp.dll & dpnhpast.dll
  14. **
  15. ******************************************************************************
  16. *****************************************************************************/
  17. #define INIT_GUID
  18. #include <windows.h>
  19. #include <objbase.h>
  20. #include <initguid.h>
  21. #include <winsock2.h>
  22. #include <MMSystem.h>
  23. #include <WSIPX.h>
  24. #include <Iphlpapi.h>
  25. #include <stdlib.h>
  26. #include <malloc.h>
  27. #include "ICSutils.h"
  28. #include "rsip.h"
  29. #include "icshelpapi.h"
  30. #include <dpnathlp.h>
  31. #include <io.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <fcntl.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. /*****************************************************************************
  38. ** Some global variables
  39. *****************************************************************************/
  40. // the mark of the beast...
  41. #define NO_ICS_HANDLE 0x666
  42. long g_waitDuration=120000;
  43. BOOL g_boolIcsPresent = FALSE;
  44. BOOL g_boolIcsOnThisMachine = FALSE;
  45. BOOL g_boolIcsFound = FALSE;
  46. BOOL g_boolUsingNatHelp = FALSE;
  47. BOOL g_boolUsingNatPAST = FALSE;
  48. BOOL g_boolInitialized = FALSE;
  49. SOCKADDR_IN g_saddrLocal;
  50. HANDLE g_hWorkerThread = 0;
  51. HMODULE g_hModDpNatHlp = NULL;
  52. PDIRECTPLAYNATHELP g_pDPNH = NULL;
  53. char g_szPublicAddr[45];
  54. char *g_lpszDllName = "NULL";
  55. char szInternal[]="internal";
  56. typedef struct _MAPHANDLES {
  57. int iMapped;
  58. DPNHHANDLE hMapped[16];
  59. } MAPHANDLES, *PMAPHANDLES;
  60. #define DP_NAT_HANDLES 256
  61. PMAPHANDLES g_PortHandles[DP_NAT_HANDLES];
  62. int iDbgFileHandle;
  63. typedef struct _SUPDLLS {
  64. char *szDllName;
  65. BOOL bUsesUpnp; // TRUE if we ICS supports UPnP
  66. } SUPDLLS, *PSUPDLLS;
  67. SUPDLLS strDpHelp[] =
  68. {
  69. {"dpnhupnp.dll", TRUE},
  70. {"dpnhpast.dll", FALSE},
  71. {NULL, FALSE}
  72. };
  73. /******* USEFULL STUFF **********/
  74. #ifndef ARRAYSIZE
  75. #define ARRAYSIZE(x) sizeof(x)/sizeof(x[0])
  76. #endif
  77. // forward declares...
  78. int GetTsPort(void);
  79. /****************************************************************************
  80. **
  81. ** DumpLibHr-
  82. ** Gives us debug spew for the HRESULTS coming back from DPNATHLP.DLL
  83. **
  84. ****************************************************************************/
  85. void DumpLibHr(HRESULT hr)
  86. {
  87. char *pErr = NULL;
  88. char scr[400];
  89. switch (hr){
  90. case DPNH_OK:
  91. pErr = "DPNH_OK";
  92. break;
  93. case DPNHSUCCESS_ADDRESSESCHANGED:
  94. pErr = "DPNHSUCCESS_ADDRESSESCHANGED";
  95. break;
  96. case DPNHERR_ALREADYINITIALIZED:
  97. pErr = "DPNHERR_ALREADYINITIALIZED";
  98. break;
  99. case DPNHERR_BUFFERTOOSMALL:
  100. pErr = "DPNHERR_BUFFERTOOSMALL";
  101. break;
  102. case DPNHERR_GENERIC:
  103. pErr = "DPNHERR_GENERIC";
  104. break;
  105. case DPNHERR_INVALIDFLAGS:
  106. pErr = "DPNHERR_INVALIDFLAGS";
  107. break;
  108. case DPNHERR_INVALIDOBJECT:
  109. pErr = "DPNHERR_INVALIDOBJECT";
  110. break;
  111. case DPNHERR_INVALIDPARAM:
  112. pErr = "DPNHERR_INVALIDPARAM";
  113. break;
  114. case DPNHERR_INVALIDPOINTER:
  115. pErr = "DPNHERR_INVALIDPOINTER";
  116. break;
  117. case DPNHERR_NOMAPPING:
  118. pErr = "DPNHERR_NOMAPPING";
  119. break;
  120. case DPNHERR_NOMAPPINGBUTPRIVATE:
  121. pErr = "DPNHERR_NOMAPPINGBUTPRIVATE";
  122. break;
  123. case DPNHERR_NOTINITIALIZED:
  124. pErr = "DPNHERR_NOTINITIALIZED";
  125. break;
  126. case DPNHERR_OUTOFMEMORY:
  127. pErr = "DPNHERR_OUTOFMEMORY";
  128. break;
  129. case DPNHERR_PORTALREADYREGISTERED:
  130. pErr = "DPNHERR_PORTALREADYREGISTERED";
  131. break;
  132. case DPNHERR_PORTUNAVAILABLE:
  133. pErr = "DPNHERR_PORTUNAVAILABLE";
  134. break;
  135. case DPNHERR_SERVERNOTAVAILABLE:
  136. pErr = "DPNHERR_SERVERNOTAVAILABLE";
  137. break;
  138. case DPNHERR_UPDATESERVERSTATUS:
  139. pErr = "DPNHERR_UPDATESERVERSTATUS";
  140. break;
  141. default:
  142. wsprintfA(scr, "unknown error: 0x%x", hr);
  143. pErr = scr;
  144. break;
  145. };
  146. IMPORTANT_MSG((L"DpNatHlp result=%S", pErr));
  147. }
  148. /****************************************************************************
  149. **
  150. ** GetAllAdapters
  151. **
  152. ****************************************************************************/
  153. int GetAllAdapters(int *iFound, int iMax, SOCKADDR_IN *sktArray)
  154. {
  155. PIP_ADAPTER_INFO p;
  156. PIP_ADDR_STRING ps;
  157. DWORD dw;
  158. ULONG ulSize = 0;
  159. int i=0;
  160. PIP_ADAPTER_INFO pAdpInfo = NULL;
  161. if (!iFound || !sktArray) return 1;
  162. *iFound = 0;
  163. ZeroMemory(sktArray, sizeof(SOCKADDR) * iMax);
  164. dw = GetAdaptersInfo(
  165. pAdpInfo,
  166. &ulSize );
  167. pAdpInfo = (IP_ADAPTER_INFO*)malloc(ulSize);
  168. if (!pAdpInfo)
  169. {
  170. INTERESTING_MSG((L"GetAddr malloc failed"));
  171. return 1;
  172. }
  173. dw = GetAdaptersInfo(
  174. pAdpInfo,
  175. &ulSize);
  176. if (dw != ERROR_SUCCESS)
  177. {
  178. INTERESTING_MSG((L"GetAdaptersInfo failed"));
  179. free(pAdpInfo);
  180. return 1;
  181. }
  182. for(p=pAdpInfo; p!=NULL; p=p->Next)
  183. {
  184. for(ps = &(p->IpAddressList); ps; ps=ps->Next)
  185. {
  186. if (strcmp(ps->IpAddress.String, "0.0.0.0") != 0 && i < iMax)
  187. {
  188. sktArray[i].sin_family = AF_INET;
  189. sktArray[i].sin_addr.S_un.S_addr = inet_addr(ps->IpAddress.String);
  190. TRIVIAL_MSG((L"Found adapter #%d at [%S]", i+1, ps->IpAddress.String));
  191. i++;
  192. }
  193. }
  194. }
  195. *iFound = i;
  196. TRIVIAL_MSG((L"GetAllAdapters- %d found", *iFound));
  197. free(pAdpInfo);
  198. return 0;
  199. }
  200. /****************************************************************************
  201. **
  202. ** OpenPort(int port)
  203. ** if there is no ICS available, then we should just return...
  204. **
  205. ** Of course, we save away the Port, as it goes back in the
  206. ** FetchAllAddresses call, asthe formatted "port" whenever a
  207. ** different one is not specified.
  208. **
  209. ****************************************************************************/
  210. DWORD APIENTRY OpenPort(int Port)
  211. {
  212. DWORD dwRet = (int)-1;
  213. TRIVIAL_MSG((L"OpenPort(%d)", Port ));
  214. if (!g_boolInitialized)
  215. {
  216. HEINOUS_E_MSG((L"ERROR: OpenPort- library not initialized"));
  217. return 0;
  218. }
  219. // save away for later retrieval
  220. g_iPort = Port;
  221. if (g_boolIcsPresent && g_pDPNH)
  222. {
  223. HRESULT hr=0;
  224. int i;
  225. DPNHHANDLE *pHnd;
  226. SOCKADDR_IN lSockAddr[16];
  227. PMAPHANDLES hMap;
  228. for (i=0;g_PortHandles[i] != NULL; i++);
  229. if (i >= ARRAYSIZE(g_PortHandles))
  230. {
  231. // we have no more memory for mappings!
  232. // should never hit this, unless we are leaking...
  233. HEINOUS_E_MSG((L"Out of table space in OpenPort"));
  234. return 0;
  235. }
  236. // now we have a pointer for our handle array
  237. hMap = (PMAPHANDLES)malloc(sizeof(MAPHANDLES));
  238. g_PortHandles[i] = hMap;
  239. dwRet = 0x8000000 + i;
  240. // get adapters
  241. GetAllAdapters(&hMap->iMapped, ARRAYSIZE(lSockAddr), &lSockAddr[0]);
  242. TRIVIAL_MSG((L"GetAllAdapters found %d adapters to deal with", hMap->iMapped));
  243. /* Now we cycle through all the found adapters and get a mapping for each
  244. * This insures that the ICF is opened on all adapters...
  245. */
  246. for (i = 0; i < hMap->iMapped; i++)
  247. {
  248. pHnd = &hMap->hMapped[i];
  249. lSockAddr[i].sin_port = ntohs((unsigned)Port);
  250. hr = IDirectPlayNATHelp_RegisterPorts(g_pDPNH,
  251. (SOCKADDR *)&lSockAddr[i], sizeof(lSockAddr[0]), 1,
  252. 30000, pHnd, DPNHREGISTERPORTS_TCP);
  253. if (hr != DPNH_OK)
  254. {
  255. IMPORTANT_MSG((L"RegisterPorts failed in OpenPort for adapter #%d, ", i ));
  256. DumpLibHr(hr);
  257. }
  258. else
  259. {
  260. TRIVIAL_MSG((L"OpenPort Assigned: 0x%x", *pHnd));
  261. }
  262. }
  263. }
  264. else
  265. {
  266. dwRet = NO_ICS_HANDLE;
  267. TRIVIAL_MSG((L"OpenPort- no ICS found"));
  268. }
  269. TRIVIAL_MSG((L"OpenPort- returns 0x%x", dwRet ));
  270. return dwRet;
  271. }
  272. /****************************************************************************
  273. **
  274. ** Called to close a port, whenever a ticket is expired or closed.
  275. **
  276. ****************************************************************************/
  277. DWORD APIENTRY ClosePort(DWORD MapHandle)
  278. {
  279. DWORD dwRet = ERROR_SUCCESS;
  280. DWORD dwIndex;
  281. TRIVIAL_MSG((L"ClosePort(0x%x)", MapHandle ));
  282. if (!g_boolInitialized)
  283. {
  284. HEINOUS_E_MSG((L"ERROR: ClosePort- library not initialized"));
  285. return ERROR_INVALID_PARAMETER;
  286. }
  287. // if we didn't open this thru the ICS, then just return
  288. if (!g_boolIcsPresent && MapHandle == NO_ICS_HANDLE)
  289. return ERROR_SUCCESS;
  290. dwIndex = MapHandle - 0x8000000;
  291. if (g_boolIcsPresent && g_pDPNH && dwIndex < ARRAYSIZE(g_PortHandles))
  292. {
  293. HRESULT hr=0;
  294. int i;
  295. PMAPHANDLES pMap = g_PortHandles[dwIndex];
  296. if (pMap)
  297. {
  298. TRIVIAL_MSG((L"closing %d port mappings", pMap->iMapped));
  299. for (i = 0; i < pMap->iMapped; i++)
  300. {
  301. hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, pMap->hMapped[i], 0);
  302. if (hr != DPNH_OK)
  303. {
  304. IMPORTANT_MSG((L"DeregisterPorts failed in ClosePort for handle 0x%x", pMap->hMapped[i]));
  305. DumpLibHr(hr);
  306. dwRet = ERROR_INVALID_ACCESS;
  307. }
  308. }
  309. // remove the handle from our array
  310. free(g_PortHandles[dwIndex]);
  311. g_PortHandles[dwIndex] = NULL;
  312. }
  313. }
  314. else
  315. IMPORTANT_MSG((L"Bad handle passed into ClosePort!!"));
  316. TRIVIAL_MSG((L"ClosePort returning 0x%x", dwRet ));
  317. return(dwRet);
  318. }
  319. /****************************************************************************
  320. **
  321. ** FetchAllAddresses
  322. ** Returns a string listing all the valid IP addresses for the machine
  323. ** Formatting details:
  324. ** 1. Each address is seperated with a ";" (semicolon)
  325. ** 2. Each address consists of the "1.2.3.4", and is followed by ":p"
  326. ** where the colon is followed by the port number
  327. **
  328. ****************************************************************************/
  329. DWORD APIENTRY FetchAllAddresses(WCHAR *lpszAddr, int iBufSize)
  330. {
  331. return FetchAllAddressesEx(lpszAddr, iBufSize, IPF_ADD_DNS);
  332. }
  333. /****************************************************************************
  334. **
  335. ** CloseAllPorts
  336. ** Does just that- closes all port mappings that have been opened
  337. **
  338. ****************************************************************************/
  339. DWORD APIENTRY CloseAllOpenPorts(void)
  340. {
  341. DWORD dwRet = 1;
  342. INTERESTING_MSG((L"CloseAllOpenPorts()" ));
  343. if (g_boolIcsPresent && g_pDPNH)
  344. {
  345. HRESULT hr=0;
  346. int i;
  347. // call DPNATHLP to unregister the mapping
  348. // then remove the handle from our array
  349. for (i = 0; i < ARRAYSIZE(g_PortHandles); i++)
  350. {
  351. if (g_PortHandles[i])
  352. {
  353. PMAPHANDLES pMap = g_PortHandles[i];
  354. int j;
  355. for (j = 0; j < pMap->iMapped; j++)
  356. {
  357. hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, pMap->hMapped[j], 0);
  358. if (hr != DPNH_OK)
  359. {
  360. IMPORTANT_MSG((L"DeregisterPorts failed in CloseAllOpenPorts"));
  361. DumpLibHr(hr);
  362. }
  363. }
  364. free(g_PortHandles[i]);
  365. g_PortHandles[i] = 0;
  366. }
  367. }
  368. }
  369. return(dwRet);
  370. }
  371. /****************************************************************************
  372. **
  373. ** The worker thread for use with the DPHATHLP.DLL.
  374. **
  375. ** This keeps the leases updated on any open
  376. ** port assignments. Eventually, this will also check & update the sessmgr
  377. ** when the ICS comes & goes, or when the address list changes.
  378. **
  379. ****************************************************************************/
  380. DWORD WINAPI DpNatHlpThread(PVOID ContextPtr)
  381. {
  382. DWORD dwRet=1;
  383. DWORD dwWaitResult=WAIT_TIMEOUT;
  384. ULONG ulCurIpTblSz, ulLastIpTblSz;
  385. long l_waitTime = g_waitDuration;
  386. PMIB_IPADDRTABLE pCurIpTbl=NULL, pLastIpTbl=NULL;
  387. TRIVIAL_MSG((L"DpNatHlpThread()" ));
  388. /*
  389. * Initialize the IP tables that we keep
  390. * Get 1 copy from IP Helper, then make a
  391. * second local copy for later comparison.
  392. */
  393. ulLastIpTblSz=0;
  394. GetIpAddrTable(NULL, &ulLastIpTblSz, FALSE);
  395. pLastIpTbl = (PMIB_IPADDRTABLE)malloc(ulLastIpTblSz);
  396. if (!pLastIpTbl)
  397. goto shutdown;
  398. if (NO_ERROR != GetIpAddrTable(pLastIpTbl, &ulLastIpTblSz, FALSE))
  399. IMPORTANT_MSG((L"Failed to get initial IpAddrTable in DpNatHlpThread; err=0x%x", GetLastError()));
  400. TRIVIAL_MSG((L"Initial IPtblSz = %d", ulLastIpTblSz));
  401. ulCurIpTblSz=ulLastIpTblSz;
  402. pCurIpTbl = (PMIB_IPADDRTABLE)malloc(ulCurIpTblSz);
  403. if (!pCurIpTbl)
  404. {
  405. goto shutdown;
  406. }
  407. memcpy(pCurIpTbl, pLastIpTbl, ulCurIpTblSz);
  408. /*
  409. * Then the 2 minute wait loop
  410. */
  411. while(dwWaitResult == WAIT_TIMEOUT)
  412. {
  413. DWORD dwTime;
  414. BOOL bAddrChanged;
  415. if (dwWaitResult != WAIT_TIMEOUT)
  416. {
  417. IMPORTANT_MSG((L"error: got bad wait return in DpNatHlpThread() val=0x%x", dwWaitResult));
  418. goto shutdown;
  419. }
  420. // our default is NO CHANGE
  421. bAddrChanged = FALSE;
  422. if (NO_ERROR != GetIpAddrTable(pCurIpTbl, &ulCurIpTblSz, FALSE))
  423. {
  424. /*
  425. * If we couldn't get the tables, it would be because the table grew
  426. * in size beyind the old one. Hmm- that must mean that the table changed
  427. */
  428. bAddrChanged=TRUE;
  429. TRIVIAL_MSG((L"IpAddrTable GREW in DpNatHlpThread"));
  430. }
  431. else
  432. {
  433. /*
  434. * If the table shrunk, then it must have changed
  435. */
  436. if (ulCurIpTblSz != ulLastIpTblSz)
  437. {
  438. bAddrChanged = TRUE;
  439. TRIVIAL_MSG((L"IpAddrTable SHRUNK in DpNatHlpThread"));
  440. }
  441. /*
  442. * Maybe one of the addresses in the table changed?
  443. */
  444. if (0 != memcmp(pCurIpTbl, pLastIpTbl, ulCurIpTblSz))
  445. {
  446. bAddrChanged=TRUE;
  447. TRIVIAL_MSG((L"IpAddrTable CHANGED in DpNatHlpThread"));
  448. }
  449. }
  450. if (bAddrChanged)
  451. {
  452. TRIVIAL_MSG((L"DpNatHlpThread: IP Tables changed; cur=%d, last=%d", ulCurIpTblSz, ulLastIpTblSz));
  453. /* free the old tables */
  454. if (pCurIpTbl) free(pCurIpTbl);
  455. if (pLastIpTbl) free(pLastIpTbl);
  456. /* then get new tables */
  457. ulLastIpTblSz=0;
  458. GetIpAddrTable(NULL, &ulLastIpTblSz, FALSE);
  459. pLastIpTbl = (PMIB_IPADDRTABLE)malloc(ulLastIpTblSz);
  460. if(pLastIpTbl)
  461. {
  462. if (NO_ERROR != GetIpAddrTable(pLastIpTbl, &ulLastIpTblSz, FALSE))
  463. IMPORTANT_MSG((L"Failed to update IpAddrTable in DpNatHlpThread; err=0x%x", GetLastError()));
  464. ulCurIpTblSz=ulLastIpTblSz;
  465. pCurIpTbl = (PMIB_IPADDRTABLE)malloc(ulCurIpTblSz);
  466. memcpy(pCurIpTbl, pLastIpTbl, ulCurIpTblSz);
  467. }
  468. else
  469. {
  470. /* we got here because the machine ran out of memory
  471. * so we will try again later to allocate the tables
  472. * maybe more memory will be free then.
  473. */
  474. pCurIpTbl = NULL;
  475. pLastIpTbl = NULL;
  476. ulLastIpTblSz=0;
  477. ulCurIpTblSz=1;
  478. IMPORTANT_MSG((L"Failed to get memory for IP tables in DpNatHlpThread; err=0x%x", GetLastError()));
  479. }
  480. }
  481. if (g_pDPNH)
  482. {
  483. HRESULT hr;
  484. DPNHCAPS lCaps;
  485. /* Call GetCaps to renew all open leases */
  486. lCaps.dwSize = sizeof(lCaps);
  487. hr = IDirectPlayNATHelp_GetCaps(g_pDPNH, &lCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
  488. if (hr == DPNH_OK)
  489. {
  490. if (lCaps.dwMinLeaseTimeRemaining)
  491. l_waitTime = min(g_waitDuration, (long)lCaps.dwMinLeaseTimeRemaining);
  492. }
  493. else if (hr == DPNHSUCCESS_ADDRESSESCHANGED)
  494. bAddrChanged = TRUE;
  495. else
  496. {
  497. IMPORTANT_MSG((L"GetCaps failed in NatHlpDaemon"));
  498. DumpLibHr(hr);
  499. }
  500. }
  501. if (bAddrChanged && g_hAlertEvent)
  502. {
  503. SetEvent(g_hAlertEvent);
  504. }
  505. dwWaitResult = WaitForSingleObject(g_hThreadEvent, l_waitTime);
  506. }
  507. shutdown:
  508. TRIVIAL_MSG((L"DpNatHlpThread shutting down"));
  509. /*
  510. * Then the shutdown code
  511. * free all memory
  512. * then close out DPNATHLP.DLL
  513. * and return all objects
  514. */
  515. if (pCurIpTbl) free(pCurIpTbl);
  516. if (pLastIpTbl) free(pLastIpTbl);
  517. if (g_pDPNH)
  518. {
  519. IDirectPlayNATHelp_Close(g_pDPNH, 0);
  520. IDirectPlayNATHelp_Release(g_pDPNH);
  521. }
  522. g_pDPNH = NULL;
  523. if (g_hModDpNatHlp)
  524. FreeLibrary(g_hModDpNatHlp);
  525. g_hModDpNatHlp = 0;
  526. DeleteCriticalSection( &g_CritSec );
  527. CloseHandle(g_hThreadEvent);
  528. TRIVIAL_MSG((L"DpNatHlpThread() returning 0x%x", dwRet ));
  529. WSACleanup();
  530. ExitThread(dwRet);
  531. // of course we never get this far...
  532. return(dwRet);
  533. }
  534. /****************************************************************************
  535. **
  536. ** The actual worker thread. This keeps the leases updated on any open
  537. ** port assignments. This will also check & update the sessmgr
  538. ** when the ICS comes & goes, or when the address list changes.
  539. **
  540. ****************************************************************************/
  541. DWORD WINAPI RsipDaemonThread(PVOID ContextPtr)
  542. {
  543. DWORD dwRet=1;
  544. DWORD dwWaitResult=WAIT_TIMEOUT;
  545. ULONG ulCurIpTblSz, ulLastIpTblSz;
  546. PMIB_IPADDRTABLE pCurIpTbl=NULL, pLastIpTbl=NULL;
  547. TRIVIAL_MSG((L"RsipDaemonThread()" ));
  548. /*
  549. * Initialize the IP tables that we keep
  550. * Get 1 copy from IP Helper, then make a
  551. * second local copy for later comparison.
  552. */
  553. ulLastIpTblSz=0;
  554. GetIpAddrTable(NULL, &ulLastIpTblSz, FALSE);
  555. pLastIpTbl = (PMIB_IPADDRTABLE)malloc(ulLastIpTblSz);
  556. if (NO_ERROR != GetIpAddrTable(pLastIpTbl, &ulLastIpTblSz, FALSE))
  557. IMPORTANT_MSG((L"Failed to get initial IpAddrTable in RsipDaemonThread; err=0x%x", GetLastError()));
  558. TRIVIAL_MSG((L"Initial IPtblSz = %d", ulLastIpTblSz));
  559. ulCurIpTblSz=ulLastIpTblSz;
  560. pCurIpTbl = (PMIB_IPADDRTABLE)malloc(ulCurIpTblSz);
  561. if (!pCurIpTbl)
  562. goto shutdown;
  563. memcpy(pCurIpTbl, pLastIpTbl, ulCurIpTblSz);
  564. /*
  565. * Then the 2 minute wait loop
  566. */
  567. while(dwWaitResult == WAIT_TIMEOUT)
  568. {
  569. DWORD dwTime;
  570. BOOL bAddrChanged;
  571. if (dwWaitResult != WAIT_TIMEOUT)
  572. {
  573. IMPORTANT_MSG((L"error: got bad wait return in RsipDaemonThread() val=0x%x", dwWaitResult));
  574. goto shutdown;
  575. }
  576. // our default is NO CHANGE
  577. bAddrChanged = FALSE;
  578. if (NO_ERROR != GetIpAddrTable(pCurIpTbl, &ulCurIpTblSz, FALSE))
  579. {
  580. /*
  581. * If we couldn't get the tables, it would be because the table grew
  582. * in size beyind the old one. Hmm- that must mean that the table changed
  583. */
  584. bAddrChanged=TRUE;
  585. TRIVIAL_MSG((L"IpAddrTable GREW in RsipDaemonThread"));
  586. }
  587. else
  588. {
  589. /*
  590. * If the table shrunk, then it must have changed
  591. */
  592. if (ulCurIpTblSz != ulLastIpTblSz)
  593. {
  594. bAddrChanged = TRUE;
  595. TRIVIAL_MSG((L"IpAddrTable SHRUNK in RsipDaemonThread"));
  596. }
  597. /*
  598. * Maybe one of the addresses in the table changed?
  599. */
  600. if (0 != memcmp(pCurIpTbl, pLastIpTbl, ulCurIpTblSz))
  601. {
  602. bAddrChanged=TRUE;
  603. TRIVIAL_MSG((L"IpAddrTable CHANGED in RsipDaemonThread"));
  604. }
  605. }
  606. if (bAddrChanged)
  607. {
  608. TRIVIAL_MSG((L"RsipDaemonThread: IP Tables changed; cur=%d, last=%d", ulCurIpTblSz, ulLastIpTblSz));
  609. /* free the old tables */
  610. if (pCurIpTbl) free(pCurIpTbl);
  611. if (pLastIpTbl) free(pLastIpTbl);
  612. /* then get new tables */
  613. ulLastIpTblSz=0;
  614. GetIpAddrTable(NULL, &ulLastIpTblSz, FALSE);
  615. pLastIpTbl = (PMIB_IPADDRTABLE)malloc(ulLastIpTblSz);
  616. if(pLastIpTbl)
  617. {
  618. if (NO_ERROR != GetIpAddrTable(pLastIpTbl, &ulLastIpTblSz, FALSE))
  619. IMPORTANT_MSG((L"Failed to update IpAddrTable in RsipDaemonThread; err=0x%x", GetLastError()));
  620. ulCurIpTblSz=ulLastIpTblSz;
  621. pCurIpTbl = (PMIB_IPADDRTABLE)malloc(ulCurIpTblSz);
  622. memcpy(pCurIpTbl, pLastIpTbl, ulCurIpTblSz);
  623. }
  624. else
  625. {
  626. /* we got here because the machine ran out of memory
  627. * so we will try again later to allocate the tables
  628. * maybe more memory will be free then.
  629. */
  630. pCurIpTbl = NULL;
  631. pLastIpTbl = NULL;
  632. ulLastIpTblSz=0;
  633. ulCurIpTblSz=1;
  634. IMPORTANT_MSG((L"Failed to get memory for IP tables in RsipDaemonThread; err=0x%x", GetLastError()));
  635. }
  636. }
  637. if (g_boolIcsPresent)
  638. {
  639. PRSIP_LEASE_RECORD pLeaseRecord;
  640. // update the leases
  641. dwTime = timeGetTime();
  642. if (!PortExtend( dwTime ) && g_hAlertEvent)
  643. {
  644. // If we cannot extend the lease, then we must notify the user
  645. TRIVIAL_MSG((L"Sending RSIP alert event from RsipDaemonThread"));
  646. bAddrChanged = TRUE;
  647. }
  648. CacheClear( dwTime );
  649. if (g_iPort && (pLeaseRecord = FindLease( TRUE, htons((WORD)g_iPort) )))
  650. {
  651. /* .
  652. * We got here because there are open leases. That means we must
  653. * periodically check to see if the public address has changed.
  654. * This would happen if the ICS's modem got disconnected or
  655. * reconnected. In the first case, we no longer have a valid public
  656. * address, in the second case we have a new public address.
  657. */
  658. SOCKADDR_IN saddrPublic, saddrNew;
  659. DWORD dwBindId = 0;
  660. DWORD dwSpewSave;
  661. saddrPublic.sin_family = AF_INET;
  662. saddrPublic.sin_addr.s_addr = pLeaseRecord->addrV4;
  663. saddrPublic.sin_port = pLeaseRecord->rport;
  664. dwSpewSave = gDbgFlag;
  665. gDbgFlag |= 3;
  666. /*
  667. * The basic algorithm for this is to ask for a new port mapping
  668. * and compare the address to what we already have. I chose to ask
  669. * for a port that will never be mapped onto a MS PC- the Sun
  670. * RPC port. This should always be available to us, as no
  671. * smart gamer will use this port.
  672. * It should not cause us any security problems, as the OS never
  673. * has any sockets open & listening on that port. Besides, the
  674. * port mapping is only valid for ~500 mSec- not long enough to cause
  675. * any real mischief.
  676. * BTW, this algorithm workd on WinME ICS servers as well.
  677. */
  678. if (S_OK == AssignPort( TRUE, htons(111), (SOCKADDR *)&saddrNew, &dwBindId ))
  679. {
  680. // free the port mapping, as all we care about is the public address
  681. FreePort(dwBindId);
  682. gDbgFlag = dwSpewSave;
  683. // check for invalid address (modem probably disconnected)
  684. if (!saddrNew.sin_addr.s_addr)
  685. {
  686. TRIVIAL_MSG((L"Public address all zeros- no longer on Internet"));
  687. /*
  688. * How should this be handled?
  689. * Well, if we notify Salem, then they will try to update the ticket.
  690. * but that may cause more trouble, as that would cause a reconnect
  691. * which would then cause another address change, which would cause
  692. * a second ticket update.
  693. *
  694. * We certainly should try to maintain the current leases, in case
  695. * the connection returns.
  696. */
  697. // bAddrChanged=TRUE;
  698. }
  699. else if (saddrNew.sin_addr.s_addr != saddrPublic.sin_addr.s_addr)
  700. {
  701. // change the public address in all the leases...
  702. RSIP_LEASE_RECORD *pLeaseWalker;
  703. RSIP_LEASE_RECORD *pNextLease;
  704. TRIVIAL_MSG((L"==> public address changed: OLD, then NEW address <=="));
  705. DumpSocketAddress( 8, (SOCKADDR *)&saddrPublic, AF_INET );
  706. DumpSocketAddress( 8, (SOCKADDR *)&saddrNew, AF_INET );
  707. pLeaseWalker = g_pRsipLeaseRecords;
  708. while( pLeaseWalker )
  709. {
  710. pNextLease = pLeaseWalker->pNext;
  711. // copy the address
  712. pLeaseWalker->addrV4 = saddrNew.sin_addr.s_addr;
  713. pLeaseWalker=pNextLease;
  714. }
  715. bAddrChanged=TRUE;
  716. }
  717. }
  718. else
  719. {
  720. gDbgFlag = dwSpewSave;
  721. IMPORTANT_MSG((L"AssignPort failed in daemon thread"));
  722. // Hmmm- we can't get to the ICS server any longer
  723. bAddrChanged=TRUE;
  724. // delete all open mappings
  725. CloseAllOpenPorts();
  726. }
  727. }
  728. }
  729. if (bAddrChanged && g_hAlertEvent)
  730. {
  731. SetEvent(g_hAlertEvent);
  732. }
  733. dwWaitResult = WaitForSingleObject(g_hThreadEvent, g_waitDuration);
  734. }
  735. shutdown:
  736. TRIVIAL_MSG((L"RsipDaemonThread shutting down"));
  737. /*
  738. * Then the shutdown code
  739. * release any open ports
  740. */
  741. if (pCurIpTbl) free(pCurIpTbl);
  742. if (pLastIpTbl) free(pLastIpTbl);
  743. Deinitialize();
  744. DeleteCriticalSection( &g_CritSec );
  745. CloseHandle(g_hThreadEvent);
  746. TRIVIAL_MSG((L"RsipDaemonThread() returning 0x%x", dwRet ));
  747. WSACleanup();
  748. ExitThread(dwRet);
  749. // of course we never get this far...
  750. return(dwRet);
  751. }
  752. /****************************************************************************
  753. **
  754. ** This should initialize the ICS library for use with the DirectPlay
  755. ** ICS/NAT helper DLL.
  756. ** All will happen in this order:
  757. ** 1. Call DirectPlayNATHelpCreate()
  758. ** 2. Call IDirectPlayNATHelp::Initialize to prepare the object
  759. **
  760. ****************************************************************************/
  761. DWORD StartDpNatHlp(void)
  762. {
  763. DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
  764. HRESULT hr;
  765. HMODULE hMod;
  766. PFN_DIRECTPLAYNATHELPCREATE pfnDirectPlayNATHelpCreate;
  767. PDIRECTPLAYNATHELP pDirectPlayNATHelp = NULL;
  768. DPNHCAPS dpnhCaps;
  769. PSUPDLLS pDll = &strDpHelp[0];
  770. try_again:
  771. TRIVIAL_MSG((L"starting StartDpNatHlp for %S (%S)", pDll->szDllName, pDll->bUsesUpnp?"UPnP":"PAST"));
  772. // start out with no public address
  773. g_szPublicAddr[0] = 0;
  774. hMod = LoadLibraryA(pDll->szDllName);
  775. if (!hMod)
  776. {
  777. IMPORTANT_MSG((L"ERROR:%S could not be found", pDll->szDllName));
  778. pDll++;
  779. if (!pDll->szDllName)
  780. {
  781. dwRet = ERROR_FILE_NOT_FOUND;
  782. goto done;
  783. }
  784. goto try_again;
  785. }
  786. pfnDirectPlayNATHelpCreate = (PFN_DIRECTPLAYNATHELPCREATE) GetProcAddress(hMod, "DirectPlayNATHelpCreate");
  787. if (!pfnDirectPlayNATHelpCreate)
  788. {
  789. IMPORTANT_MSG((L"\"DirectPlayNATHelpCreate\" proc in %S could not be found", pDll->szDllName));
  790. dwRet = ERROR_INVALID_FUNCTION;
  791. goto done;
  792. }
  793. hr = pfnDirectPlayNATHelpCreate(&IID_IDirectPlayNATHelp,
  794. (void**) (&pDirectPlayNATHelp));
  795. if (hr != DPNH_OK)
  796. {
  797. IMPORTANT_MSG((L"DirectPlayNATHelpCreate failed in %S", pDll->szDllName));
  798. DumpLibHr(hr);
  799. dwRet = ERROR_BAD_UNIT;
  800. goto done;
  801. }
  802. hr = IDirectPlayNATHelp_Initialize(pDirectPlayNATHelp, 0);
  803. if (hr != DPNH_OK)
  804. {
  805. IMPORTANT_MSG((L"IDirectPlayNATHelp_Initialize failed in %S", pDll->szDllName));
  806. DumpLibHr(hr);
  807. dwRet = ERROR_BAD_UNIT;
  808. goto done;
  809. }
  810. /* Get capabilities of NAT/RSIP/PAST server */
  811. dpnhCaps.dwSize = sizeof(dpnhCaps);
  812. hr = IDirectPlayNATHelp_GetCaps(pDirectPlayNATHelp, &dpnhCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
  813. if (hr != DPNH_OK && hr != DPNHSUCCESS_ADDRESSESCHANGED)
  814. {
  815. IMPORTANT_MSG((L"IDirectPlayNATHelp_GetCaps failed"));
  816. DumpLibHr(hr);
  817. dwRet = ERROR_BAD_UNIT;
  818. goto done;
  819. }
  820. if (dpnhCaps.dwFlags & (DPNHCAPSFLAG_LOCALFIREWALLPRESENT | DPNHCAPSFLAG_GATEWAYPRESENT))
  821. {
  822. PIP_ADAPTER_INFO pAdpInfo = NULL;
  823. SOCKADDR_IN saddrOurLAN;
  824. PMIB_IPADDRTABLE pmib=NULL;
  825. ULONG ulSize = 0;
  826. DWORD dw;
  827. g_boolIcsPresent = TRUE;
  828. TRIVIAL_MSG((L"ICS server found using %S", pDll->szDllName));
  829. g_lpszDllName = pDll->szDllName;
  830. // copy this pointer where it will do us some good
  831. g_pDPNH = pDirectPlayNATHelp;
  832. g_boolUsingNatHelp = TRUE;
  833. g_boolUsingNatPAST = pDll->bUsesUpnp;
  834. dwRet = ERROR_SUCCESS;
  835. // is this machine an ICS host?
  836. if (dpnhCaps.dwFlags & (DPNHCAPSFLAG_LOCALFIREWALLPRESENT | DPNHCAPSFLAG_GATEWAYISLOCAL))
  837. g_boolIcsOnThisMachine = TRUE;
  838. ZeroMemory(&saddrOurLAN, sizeof(saddrOurLAN));
  839. saddrOurLAN.sin_family = AF_INET;
  840. dw = GetAdaptersInfo(
  841. pAdpInfo,
  842. &ulSize );
  843. if (dw == ERROR_BUFFER_OVERFLOW && ulSize)
  844. {
  845. pAdpInfo = (IP_ADAPTER_INFO*)malloc(ulSize);
  846. if (!pAdpInfo)
  847. goto done;
  848. dw = GetAdaptersInfo(
  849. pAdpInfo,
  850. &ulSize);
  851. if (dw == ERROR_SUCCESS)
  852. {
  853. PIP_ADAPTER_INFO p;
  854. PIP_ADDR_STRING ps;
  855. for(p=pAdpInfo; p!=NULL; p=p->Next)
  856. {
  857. for(ps = &(p->IpAddressList); ps; ps=ps->Next)
  858. {
  859. if (strcmp(ps->IpAddress.String, "0.0.0.0") != 0)
  860. {
  861. // blah blah blah
  862. saddrOurLAN.sin_addr.S_un.S_addr = inet_addr(ps->IpAddress.String);
  863. TRIVIAL_MSG((L"Initializing RSIP to LAN adapter at [%S]", ps->IpAddress.String));
  864. goto doit;
  865. }
  866. }
  867. }
  868. }
  869. }
  870. doit:
  871. memcpy(&g_saddrLocal, &saddrOurLAN, sizeof(saddrOurLAN));
  872. // Does the ICS have a public address?
  873. if ( 1 )
  874. {
  875. /* then we will discover the public address */
  876. DPNHHANDLE dpHnd;
  877. saddrOurLAN.sin_port = ntohs(3389);
  878. /* first we ask for a new mapping */
  879. hr = IDirectPlayNATHelp_RegisterPorts(g_pDPNH,
  880. (SOCKADDR *)&saddrOurLAN, sizeof(saddrOurLAN), 1,
  881. 30000, &dpHnd, DPNHREGISTERPORTS_TCP);
  882. if (hr != DPNH_OK)
  883. {
  884. IMPORTANT_MSG((L"IDirectPlayNATHelp_RegisterPorts failed in StartDpNatHlp"));
  885. DumpLibHr(hr);
  886. }
  887. else
  888. {
  889. /* we succeeded, so query for the address */
  890. SOCKADDR_IN lsi;
  891. DWORD dwSize, dwTypes;
  892. TRIVIAL_MSG((L"IDirectPlayNATHelp_RegisterPorts Assigned: 0x%x", dpHnd));
  893. dwSize = sizeof(lsi);
  894. ZeroMemory(&lsi, dwSize);
  895. hr = IDirectPlayNATHelp_GetRegisteredAddresses(g_pDPNH, dpHnd, (SOCKADDR *)&lsi,
  896. &dwSize, &dwTypes, NULL, 0, );
  897. if (hr == DPNH_OK && dwSize)
  898. {
  899. wsprintfA(g_szPublicAddr, "%d.%d.%d.%d",
  900. lsi.sin_addr.S_un.S_un_b.s_b1,
  901. lsi.sin_addr.S_un.S_un_b.s_b2,
  902. lsi.sin_addr.S_un.S_un_b.s_b3,
  903. lsi.sin_addr.S_un.S_un_b.s_b4);
  904. TRIVIAL_MSG((L"Public Address=[%S]", g_szPublicAddr ));
  905. }
  906. else
  907. {
  908. IMPORTANT_MSG((L"GetRegisteredAddresses[0x%x] failed, size=0x%x", dpHnd, dwSize));
  909. DumpLibHr(hr);
  910. }
  911. /* close out the temp port we got */
  912. hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, dpHnd, 0);
  913. if (hr != DPNH_OK)
  914. {
  915. IMPORTANT_MSG((L"DeregisterPorts failed in ClosePort"));
  916. DumpLibHr(hr);
  917. dwRet = ERROR_INVALID_ACCESS;
  918. }
  919. }
  920. }
  921. }
  922. else
  923. {
  924. hr = IDirectPlayNATHelp_Close(pDirectPlayNATHelp, 0);
  925. if (hr != DPNH_OK)
  926. {
  927. IMPORTANT_MSG((L"IDirectPlayNATHelp_Close failed"));
  928. DumpLibHr(hr);
  929. }
  930. hr = IDirectPlayNATHelp_Release(pDirectPlayNATHelp);
  931. if (hr != DPNH_OK)
  932. {
  933. IMPORTANT_MSG((L"IDirectPlayNATHelp_Release failed"));
  934. DumpLibHr(hr);
  935. }
  936. pDll++;
  937. if (pDll->szDllName)
  938. {
  939. if (hMod) FreeLibrary(hMod);
  940. hMod = 0;
  941. goto try_again;
  942. }
  943. g_pDPNH = NULL;
  944. g_boolUsingNatHelp = FALSE;
  945. dwRet = ERROR_BAD_UNIT;
  946. }
  947. done:
  948. if (dwRet != ERROR_SUCCESS)
  949. {
  950. if (hMod)
  951. FreeLibrary(hMod);
  952. hMod = 0;
  953. }
  954. TRIVIAL_MSG((L"done with StartDpNatHlp, result=0x%x", dwRet));
  955. // save hMod so we can close it out in StopICSLibrary
  956. g_hModDpNatHlp = hMod;
  957. return dwRet;
  958. };
  959. /****************************************************************************
  960. **
  961. ** The first call to be made into this library. It is responsible for
  962. ** starting up all worker threads, initializing all memory and libs,
  963. ** and starting up the DPHLPAPI.DLL function (if found).
  964. **
  965. ****************************************************************************/
  966. DWORD APIENTRY StartICSLib(void)
  967. {
  968. WSADATA WsaData;
  969. DWORD dwThreadId;
  970. HANDLE hEvent, hThread;
  971. HKEY hKey;
  972. int sktRet;
  973. // open reg key first, to get ALL the spew...
  974. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\ICSHelper", 0, KEY_READ, &hKey))
  975. {
  976. DWORD dwSize;
  977. dwSize = sizeof(gDbgFlag);
  978. RegQueryValueEx(hKey, L"DebugSpew", NULL, NULL, (LPBYTE)&gDbgFlag, &dwSize);
  979. g_waitDuration = 0;
  980. dwSize = sizeof(g_waitDuration);
  981. RegQueryValueEx(hKey, L"RetryTimeout", NULL, NULL, (LPBYTE)&g_waitDuration, &dwSize);
  982. if (g_waitDuration)
  983. g_waitDuration *= 1000;
  984. else
  985. g_waitDuration = 120000;
  986. RegCloseKey(hKey);
  987. }
  988. // should we create a debug log file?
  989. if (gDbgFlag & DBG_MSG_DEST_FILE)
  990. {
  991. WCHAR szLogfileName[MAX_PATH];
  992. GetSystemDirectory(szLogfileName, sizeof(szLogfileName)/sizeof(szLogfileName[0]));
  993. lstrcat(szLogfileName, L"\\SalemICSHelper.log");
  994. iDbgFileHandle = _wopen(szLogfileName, _O_APPEND | _O_BINARY | _O_RDWR, 0);
  995. if (-1 != iDbgFileHandle)
  996. {
  997. OutputDebugStringA("opened debug log file\n");
  998. }
  999. else
  1000. {
  1001. unsigned char UniCode[2] = {0xff, 0xfe};
  1002. // we must create the file
  1003. OutputDebugStringA("must create debug log file");
  1004. iDbgFileHandle = _wopen(szLogfileName, _O_BINARY | _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE);
  1005. if (-1 != iDbgFileHandle)
  1006. _write(iDbgFileHandle, &UniCode, sizeof(UniCode));
  1007. else
  1008. {
  1009. OutputDebugStringA("ERROR: failed to create debug log file");
  1010. iDbgFileHandle = 0;
  1011. }
  1012. }
  1013. }
  1014. g_iPort = GetTsPort();
  1015. TRIVIAL_MSG((L"StartICSLib()" ));
  1016. ZeroMemory(g_PortHandles, sizeof(g_PortHandles));
  1017. if (g_boolInitialized)
  1018. {
  1019. HEINOUS_E_MSG((L"ERROR: StartICSLib called twice"));
  1020. return ERROR_INVALID_PARAMETER;
  1021. }
  1022. else
  1023. g_boolInitialized = TRUE;
  1024. // of course, this must be done...
  1025. InitializeCriticalSection(&g_CritSec);
  1026. // create an event for later use by the daemon thread
  1027. hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  1028. if (!hEvent)
  1029. {
  1030. IMPORTANT_MSG((L"Could not create an event for RSIP worker thread, err=0x%x", GetLastError()));
  1031. return GetLastError();
  1032. }
  1033. g_hThreadEvent = hEvent;
  1034. if (0 != WSAStartup(MAKEWORD(2,2), &WsaData))
  1035. {
  1036. if (0 != (sktRet = WSAStartup(MAKEWORD(2,0), &WsaData)))
  1037. {
  1038. IMPORTANT_MSG((L"WSAStartup failed:"));
  1039. return sktRet;
  1040. }
  1041. }
  1042. if (ERROR_SUCCESS == StartDpNatHlp())
  1043. {
  1044. // start RSIP daemon process, which will do all the work
  1045. hThread = CreateThread( NULL, // SD- not needed
  1046. 0, // Stack Size
  1047. (LPTHREAD_START_ROUTINE)DpNatHlpThread,
  1048. NULL,
  1049. 0,
  1050. &dwThreadId );
  1051. }
  1052. else
  1053. {
  1054. // start up RSIP lib
  1055. g_szPublicAddr[0]=0;
  1056. if (RsipIsRunningOnThisMachine( &g_saddrPublic ))
  1057. {
  1058. // makes casting easier
  1059. SOCKADDR_IN *pPubAddr = (SOCKADDR_IN*)( &g_saddrPublic );
  1060. g_boolIcsPresent = g_boolIcsOnThisMachine = TRUE;
  1061. // save the public side address so that we can filter it out
  1062. // of the address list we return
  1063. wsprintfA(g_szPublicAddr, "%d.%d.%d.%d",
  1064. pPubAddr->sin_addr.S_un.S_un_b.s_b1,
  1065. pPubAddr->sin_addr.S_un.S_un_b.s_b2,
  1066. pPubAddr->sin_addr.S_un.S_un_b.s_b3,
  1067. pPubAddr->sin_addr.S_un.S_un_b.s_b4);
  1068. INTERESTING_MSG((L"PAST Host is local- public address is [%S]", &g_szPublicAddr));
  1069. }
  1070. else
  1071. {
  1072. SOCKADDR_IN saddrOurLAN;
  1073. PMIB_IPADDRTABLE pmib=NULL;
  1074. ULONG ulSize = 0;
  1075. DWORD dw;
  1076. PIP_ADAPTER_INFO pAdpInfo = NULL;
  1077. ZeroMemory(&saddrOurLAN, sizeof(saddrOurLAN));
  1078. saddrOurLAN.sin_family = AF_INET;
  1079. dw = GetAdaptersInfo(
  1080. pAdpInfo,
  1081. &ulSize );
  1082. if (dw == ERROR_BUFFER_OVERFLOW && ulSize)
  1083. {
  1084. pAdpInfo = (IP_ADAPTER_INFO*)malloc(ulSize);
  1085. if (!pAdpInfo)
  1086. goto done;
  1087. dw = GetAdaptersInfo(
  1088. pAdpInfo,
  1089. &ulSize);
  1090. if (dw == ERROR_SUCCESS)
  1091. {
  1092. PIP_ADAPTER_INFO p;
  1093. PIP_ADDR_STRING ps;
  1094. for(p=pAdpInfo; p!=NULL; p=p->Next)
  1095. {
  1096. for(ps = &(p->IpAddressList); ps; ps=ps->Next)
  1097. {
  1098. if (strcmp(ps->IpAddress.String, "0.0.0.0") != 0)
  1099. {
  1100. // blah blah blah
  1101. saddrOurLAN.sin_addr.S_un.S_addr = inet_addr(ps->IpAddress.String);
  1102. TRIVIAL_MSG((L"Initializing RSIP to LAN adapter at [%S]", ps->IpAddress.String));
  1103. goto doit;
  1104. }
  1105. }
  1106. }
  1107. }
  1108. }
  1109. doit:
  1110. g_boolIcsPresent = Initialize((SOCKADDR *)&saddrOurLAN, FALSE);
  1111. if (g_boolIcsPresent)
  1112. {
  1113. DWORD dwBindID=0;
  1114. SOCKADDR saddrAssigned;
  1115. if (S_OK == AssignPort( FALSE, 6969, &saddrAssigned, &dwBindID ))
  1116. {
  1117. // free the port, since we just wanted the public IP address
  1118. FreePort( dwBindID );
  1119. wsprintfA(g_szPublicAddr, "%d.%d.%d.%d",
  1120. (UCHAR)saddrAssigned.sa_data[2],
  1121. (UCHAR)saddrAssigned.sa_data[3],
  1122. (UCHAR)saddrAssigned.sa_data[4],
  1123. (UCHAR)saddrAssigned.sa_data[5]);
  1124. INTERESTING_MSG((L"PAST Host is NOT local- public address is [%S]", &g_szPublicAddr));
  1125. }
  1126. else
  1127. {
  1128. IMPORTANT_MSG((L"Failed to assign port when attempting to determine public network address!" ));
  1129. }
  1130. }
  1131. }
  1132. done:
  1133. g_lpszDllName = szInternal;
  1134. // start RSIP daemon process, which will do all the work
  1135. hThread = CreateThread( NULL, // SD- not needed
  1136. 0, // Stack Size
  1137. (LPTHREAD_START_ROUTINE)RsipDaemonThread,
  1138. NULL,
  1139. 0,
  1140. &dwThreadId );
  1141. }
  1142. if (!hThread)
  1143. {
  1144. IMPORTANT_MSG((L"Could not create RSIP worker thread, err=0x%x", GetLastError()));
  1145. return GetLastError();
  1146. }
  1147. // save this for later, as we need it in the close function
  1148. g_hWorkerThread = hThread;
  1149. TRIVIAL_MSG((L"StartICSLib() returning ERROR_SUCCESS"));
  1150. return(ERROR_SUCCESS);
  1151. }
  1152. /****************************************************************************
  1153. **
  1154. ** The last call to be made into this library. Do not call any other
  1155. ** functiopn in this library after you call this!
  1156. **
  1157. ****************************************************************************/
  1158. DWORD APIENTRY StopICSLib(void)
  1159. {
  1160. DWORD dwRet = ERROR_SUCCESS;
  1161. DWORD dwTmp;
  1162. TRIVIAL_MSG((L"StopICSLib()" ));
  1163. // signal the worker thread, so that it will do a shutdown
  1164. SetEvent(g_hThreadEvent);
  1165. // then wait for it to shutdown.
  1166. dwTmp = WaitForSingleObject(g_hWorkerThread, 15000);
  1167. if (dwTmp == WAIT_OBJECT_0)
  1168. TRIVIAL_MSG((L"ICS worker thread closed down normally"));
  1169. else if (dwTmp == WAIT_ABANDONED)
  1170. IMPORTANT_MSG((L"ICS worker thread did not complete in 15 seconds"));
  1171. else
  1172. IMPORTANT_MSG((L"WaitForWorkerThread failed"));
  1173. CloseHandle(g_hWorkerThread);
  1174. TRIVIAL_MSG((L"StopICSLib() returning 0x%x", dwRet ));
  1175. _close(iDbgFileHandle);
  1176. g_boolInitialized = FALSE;
  1177. return(dwRet);
  1178. }
  1179. /****************************************************************************
  1180. **
  1181. ** SetAlertEvent
  1182. ** Pass in an event handle. Then, whenever the ICS changes state, I
  1183. ** will signal that event.
  1184. **
  1185. ****************************************************************************/
  1186. DWORD APIENTRY SetAlertEvent(HANDLE hEvent)
  1187. {
  1188. TRIVIAL_MSG((L"SetAlertEvent(0x%x)", hEvent));
  1189. g_hAlertEvent = hEvent;
  1190. return 1;
  1191. }
  1192. /****************************************************************************
  1193. **
  1194. ** Address String Compression routines
  1195. **
  1196. *****************************************************************************
  1197. **
  1198. ** The following is a group of routines designed to compress and expand
  1199. ** IPV4 addresses into the absolute minimum size possible. This is to
  1200. ** provide a compressed ASCII string that can be parsed using standard
  1201. ** shell routines for command line parsing.
  1202. ** The compressed string has the following restrictions:
  1203. ** -> Must not expand to more characters if UTF8 encoded.
  1204. ** -> Must not contain the NULL character so that string libs work.
  1205. ** -> Cannot contain double quote character, the shell needs that.
  1206. ** -> Does not have to be human readable.
  1207. **
  1208. ** Data Types:
  1209. ** There are three data types used here:
  1210. ** szAddr The orginal IPV4 string address ("X.X.X.X:port")
  1211. ** blobAddr Six byte struct with 4 bytes of address, and 2 bytes of port
  1212. ** szComp Eight byte ascii string of compressed IPV4 address
  1213. **
  1214. ****************************************************************************/
  1215. #define COMP_OFFSET '#'
  1216. #define COMP_SEPERATOR '!'
  1217. #pragma pack(push,1)
  1218. typedef struct _BLOB_ADDR {
  1219. UCHAR addr_d; // highest order address byte
  1220. UCHAR addr_c;
  1221. UCHAR addr_b;
  1222. UCHAR addr_a; // lowest order byte (last in IP string address)
  1223. WORD port;
  1224. } BLOB_ADDR, *PBLOB_ADDR;
  1225. #pragma pack(pop)
  1226. WCHAR b64Char[64]={
  1227. 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
  1228. 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
  1229. '0','1','2','3','4','5','6','7','8','9','+','/'
  1230. };
  1231. void DumpBlob(PBLOB_ADDR pba)
  1232. {
  1233. UCHAR *lpa;
  1234. lpa = (UCHAR *)pba;
  1235. TRIVIAL_MSG((L"blob (hex): %x,%x,%x,%x,%x,%x", *lpa, *(lpa+1), *(lpa+2), *(lpa+3), *(lpa+4), *(lpa+5)));
  1236. TRIVIAL_MSG((L" (struct): %x,%x,%x,%x:%x", pba->addr_d, pba->addr_c, pba->addr_b, pba->addr_a, pba->port));
  1237. TRIVIAL_MSG((L" (IP): %d.%d.%d.%d:%d", pba->addr_d, pba->addr_c, pba->addr_b, pba->addr_a, pba->port));
  1238. }
  1239. /****************************************************************************
  1240. ** char * atob(char *szVal, UCHAR *result)
  1241. ****************************************************************************/
  1242. WCHAR *atob(WCHAR *szVal, UCHAR *result)
  1243. {
  1244. WCHAR *lptr;
  1245. WCHAR ucb;
  1246. UCHAR foo;
  1247. if (!result || !szVal)
  1248. {
  1249. IMPORTANT_MSG((L"ERROR: NULL ptr passed in atob"));
  1250. return NULL;
  1251. }
  1252. // start ptr at the beginning of string
  1253. lptr = szVal;
  1254. foo = 0;
  1255. ucb = *lptr++ - '0';
  1256. while (ucb >= 0 && ucb <= 9)
  1257. {
  1258. foo *= 10;
  1259. foo += ucb;
  1260. ucb = (*lptr++)-'0';
  1261. }
  1262. *result = (UCHAR)foo;
  1263. return lptr;
  1264. }
  1265. /****************************************************************************
  1266. **
  1267. ** CompressAddr(pszAddr, pblobAddr);
  1268. ** Takes an ascii IP address (X.X.X.X:port) and converts it to a
  1269. ** 6 byte binary blob.
  1270. **
  1271. ** returns TRUE for success, FALSE for failure.
  1272. **
  1273. ****************************************************************************/
  1274. BOOL CompressAddr(WCHAR *pszAddr, PBLOB_ADDR pblobAddr)
  1275. {
  1276. BLOB_ADDR lblob;
  1277. WCHAR *lpsz;
  1278. if (!pszAddr || !pblobAddr)
  1279. {
  1280. IMPORTANT_MSG((L"ERROR: NULL ptr passed in CompressAddr"));
  1281. return FALSE;
  1282. }
  1283. lpsz = pszAddr;
  1284. lpsz = atob(lpsz, &lblob.addr_d);
  1285. if (*(lpsz-1) != '.')
  1286. {
  1287. IMPORTANT_MSG((L"ERROR: bad address[0] passed in CompressAddr for %s", pszAddr));
  1288. return FALSE;
  1289. }
  1290. lpsz = atob(lpsz, &lblob.addr_c);
  1291. if (*(lpsz-1) != '.')
  1292. {
  1293. IMPORTANT_MSG((L"ERROR: bad address[1] passed in CompressAddr"));
  1294. return FALSE;
  1295. }
  1296. lpsz = atob(lpsz, &lblob.addr_b);
  1297. if (*(lpsz-1) != '.')
  1298. {
  1299. IMPORTANT_MSG((L"ERROR: bad address[2] passed in CompressAddr"));
  1300. return FALSE;
  1301. }
  1302. lpsz = atob(lpsz, &lblob.addr_a);
  1303. // is there a port number here?
  1304. if (*(lpsz-1) == ':')
  1305. lblob.port = (WORD)_wtoi(lpsz);
  1306. else
  1307. lblob.port = 0;
  1308. // copy back the result
  1309. memcpy(pblobAddr, &lblob, sizeof(*pblobAddr));
  1310. return TRUE;
  1311. }
  1312. /****************************************************************************
  1313. **
  1314. ** ExpandAddr(pszAddr, pblobAddr);
  1315. ** Takes 6 byte binary blob and converts it into an ascii IP
  1316. ** address (X.X.X.X:port)
  1317. **
  1318. ** returns TRUE for success, FALSE for failure.
  1319. **
  1320. ****************************************************************************/
  1321. BOOL ExpandAddr(WCHAR *pszAddr, PBLOB_ADDR pba)
  1322. {
  1323. if (!pszAddr || !pba)
  1324. {
  1325. IMPORTANT_MSG((L"ERROR: NULL ptr passed in ExpandAddr"));
  1326. return FALSE;
  1327. }
  1328. wsprintf(pszAddr, L"%d.%d.%d.%d", pba->addr_d, pba->addr_c,
  1329. pba->addr_b, pba->addr_a);
  1330. if (pba->port)
  1331. {
  1332. WCHAR scratch[8];
  1333. wsprintf(scratch, L":%d", pba->port);
  1334. wcscat(pszAddr, scratch);
  1335. }
  1336. return TRUE;
  1337. }
  1338. /****************************************************************************
  1339. **
  1340. ** AsciifyAddr(pszAddr, pblobAddr);
  1341. ** Takes 6 byte binary blob and converts it into compressed ascii
  1342. ** will return either 6 or 8 bytes of string
  1343. **
  1344. ** returns TRUE for success, FALSE for failure.
  1345. **
  1346. ****************************************************************************/
  1347. BOOL AsciifyAddr(WCHAR *pszAddr, PBLOB_ADDR pba)
  1348. {
  1349. UCHAR tmp;
  1350. DWORDLONG dwl;
  1351. int i, iCnt;
  1352. if (!pszAddr || !pba)
  1353. {
  1354. IMPORTANT_MSG((L"ERROR: NULL ptr passed in AsciifyAddr"));
  1355. return FALSE;
  1356. }
  1357. iCnt = 6;
  1358. if (pba->port)
  1359. iCnt = 8;
  1360. dwl = 0;
  1361. memcpy(&dwl, pba, sizeof(*pba));
  1362. for (i = 0; i < iCnt; i++)
  1363. {
  1364. // get 6 bits of data
  1365. tmp = (UCHAR)(dwl & 0x3f);
  1366. // add the offset to asciify this
  1367. // offset must be bigger the double-quote char.
  1368. pszAddr[i] = b64Char[tmp]; // (WCHAR)(tmp + COMP_OFFSET);
  1369. // Shift right 6 bits
  1370. dwl = Int64ShrlMod32(dwl, 6);
  1371. }
  1372. // terminating NULL
  1373. pszAddr[iCnt] = 0;
  1374. return TRUE;
  1375. }
  1376. /****************************************************************************
  1377. **
  1378. ** DeAsciifyAddr(pszAddr, pblobAddr);
  1379. ** Takes a compressed ascii string and converts it into a
  1380. ** 6 or 8 byte binary blob
  1381. **
  1382. ** returns TRUE for success, FALSE for failure.
  1383. **
  1384. ****************************************************************************/
  1385. BOOL DeAsciifyAddr(WCHAR *pszAddr, PBLOB_ADDR pba)
  1386. {
  1387. UCHAR tmp;
  1388. WCHAR wtmp;
  1389. DWORDLONG dwl;
  1390. int i;
  1391. int iCnt;
  1392. if (!pszAddr || !pba)
  1393. {
  1394. IMPORTANT_MSG((L"ERROR: NULL ptr passed in DeAsciifyAddr"));
  1395. return FALSE;
  1396. }
  1397. /* how long is this string?
  1398. * if it is 6 bytes, then there is no port
  1399. * else it should be 8 bytes
  1400. */
  1401. i = wcslen(pszAddr);
  1402. if (i == 6 || i == 8)
  1403. iCnt = i;
  1404. else
  1405. {
  1406. iCnt = 8;
  1407. IMPORTANT_MSG((L"Strlen (%d) is wrong in DeAsciifyAddr", i));
  1408. }
  1409. dwl = 0;
  1410. for (i = iCnt-1; i >= 0; i--)
  1411. {
  1412. wtmp = pszAddr[i];
  1413. if (wtmp >= L'A' && wtmp <= L'Z')
  1414. tmp = wtmp - L'A';
  1415. else if (wtmp >= L'a' && wtmp <= L'z')
  1416. tmp = wtmp - L'a' + 26;
  1417. else if (wtmp >= L'0' && wtmp <= L'9')
  1418. tmp = wtmp - L'0' + 52;
  1419. else if (wtmp == L'+')
  1420. tmp = 62;
  1421. else if (wtmp == L'/')
  1422. tmp = 63;
  1423. else
  1424. {
  1425. tmp = 0;
  1426. HEINOUS_E_MSG((L"ERROR:found invalid character in decode stream"));
  1427. }
  1428. // tmp = (UCHAR)(pszAddr[i] - COMP_OFFSET);
  1429. if (tmp > 63)
  1430. {
  1431. tmp = 0;
  1432. HEINOUS_E_MSG((L"ERROR:screwup in DeAsciify"));
  1433. }
  1434. dwl = Int64ShllMod32(dwl, 6);
  1435. dwl |= tmp;
  1436. }
  1437. memcpy(pba, &dwl, sizeof(*pba));
  1438. return TRUE;
  1439. }
  1440. /****************************************************************************
  1441. **
  1442. ** SquishAddress(char *szIp, char *szCompIp)
  1443. ** Takes one IP address and compresses it to minimum size
  1444. **
  1445. ****************************************************************************/
  1446. DWORD APIENTRY SquishAddress(WCHAR *szIp, WCHAR *szCompIp)
  1447. {
  1448. WCHAR *thisAddr, *nextAddr;
  1449. BLOB_ADDR ba;
  1450. if (!szIp || !szCompIp)
  1451. {
  1452. HEINOUS_E_MSG((L"SquishAddress called with NULL ptr"));
  1453. return ERROR_INVALID_PARAMETER;
  1454. }
  1455. // TRIVIAL_MSG((L"SquishAddress(%s)", szIp));
  1456. thisAddr = szIp;
  1457. szCompIp[0] = 0;
  1458. while (thisAddr)
  1459. {
  1460. WCHAR scr[10];
  1461. nextAddr = wcschr(thisAddr, L';');
  1462. if (nextAddr && *(nextAddr+1))
  1463. {
  1464. *nextAddr = 0;
  1465. }
  1466. else
  1467. nextAddr=0;
  1468. CompressAddr(thisAddr, &ba);
  1469. // DumpBlob(&ba);
  1470. AsciifyAddr(scr, &ba);
  1471. wcscat(szCompIp, scr);
  1472. if (nextAddr)
  1473. {
  1474. // restore seperator found earlier
  1475. *nextAddr = ';';
  1476. nextAddr++;
  1477. wcscat(szCompIp, L"!" /* COMP_SEPERATOR */);
  1478. }
  1479. thisAddr = nextAddr;
  1480. }
  1481. // TRIVIAL_MSG((L"SquishAddress returns [%s]", szCompIp));
  1482. return ERROR_SUCCESS;
  1483. }
  1484. /****************************************************************************
  1485. **
  1486. ** ExpandAddress(char *szIp, char *szCompIp)
  1487. ** Takes a compressed IP address and returns it to
  1488. ** "normal"
  1489. **
  1490. ****************************************************************************/
  1491. DWORD APIENTRY ExpandAddress(WCHAR *szIp, WCHAR *szCompIp)
  1492. {
  1493. BLOB_ADDR ba;
  1494. WCHAR *thisAddr, *nextAddr;
  1495. if (!szIp || !szCompIp)
  1496. {
  1497. HEINOUS_E_MSG((L"ExpandAddress called with NULL ptr"));
  1498. return ERROR_INVALID_PARAMETER;
  1499. }
  1500. // TRIVIAL_MSG((L"ExpandAddress(%s)", szCompIp));
  1501. thisAddr = szCompIp;
  1502. szIp[0] = 0;
  1503. while (thisAddr)
  1504. {
  1505. WCHAR scr[32];
  1506. nextAddr = wcschr(thisAddr, COMP_SEPERATOR);
  1507. if (nextAddr) *nextAddr = 0;
  1508. DeAsciifyAddr(thisAddr, &ba);
  1509. // DumpBlob(&ba);
  1510. ExpandAddr(scr, &ba);
  1511. wcscat(szIp, scr);
  1512. if (nextAddr)
  1513. {
  1514. // restore seperator found earlier
  1515. *nextAddr = COMP_SEPERATOR;
  1516. nextAddr++;
  1517. wcscat(szIp, L";");
  1518. }
  1519. thisAddr = nextAddr;
  1520. }
  1521. // TRIVIAL_MSG((L"ExpandAddress returns [%s]", szIp));
  1522. return ERROR_SUCCESS;
  1523. }
  1524. /****************************************************************************
  1525. **
  1526. ** FetchAllAddressesEx
  1527. ** Returns a string listing all the valid IP addresses for the machine
  1528. ** controlled by a set of "flags". These are as follows:
  1529. ** IPflags=
  1530. ** IPF_ADD_DNS adds the DNS name to the IP list
  1531. ** IPF_COMPRESS compresses the IP address list (exclusive w/ IPF_ADD_DNS)
  1532. ** IPF_NO_SORT do not sort adapter IP list
  1533. **
  1534. ** Formatting details:
  1535. ** 1. Each address is seperated with a ";" (semicolon)
  1536. ** 2. Each address consists of the "1.2.3.4", and is followed by ":p"
  1537. ** where the colon is followed by the port number
  1538. **
  1539. ****************************************************************************/
  1540. #define WCHAR_CNT 4096
  1541. DWORD APIENTRY FetchAllAddressesEx(WCHAR *lpszAddr, int iBufSize, int IPflags)
  1542. {
  1543. DWORD dwRet = 1;
  1544. WCHAR *AddressLst;
  1545. int iAddrLen;
  1546. BOOL bSort=FALSE;
  1547. AddressLst = (WCHAR *) malloc(WCHAR_CNT * sizeof(WCHAR));
  1548. if (!AddressLst)
  1549. {
  1550. HEINOUS_E_MSG((L"Fatal error: malloc failed in FetchAllAddressesEx"));
  1551. return 0;
  1552. }
  1553. *AddressLst = 0;
  1554. INTERESTING_MSG((L"FetchAllAddressesEx()" ));
  1555. // sanity check the flags
  1556. if ((IPflags & IPF_COMPRESS) && IPflags != IPF_COMPRESS+IPF_NO_SORT)
  1557. {
  1558. IMPORTANT_MSG((L"Illegal IPflags value (0x%x) in FetchAllAddressesEx, forcing to IPF_COMPRESS+IPF_NO_SORT", IPflags));
  1559. IPflags = IPF_COMPRESS+IPF_NO_SORT;
  1560. }
  1561. if (g_boolIcsPresent && g_pDPNH)
  1562. {
  1563. if (g_boolUsingNatHelp)
  1564. {
  1565. int i;
  1566. // gotta cycle through the g_PortHandles list...
  1567. for (i=0;i<ARRAYSIZE(g_PortHandles); i++)
  1568. {
  1569. if (g_PortHandles[i])
  1570. {
  1571. HRESULT hr = E_FAIL;
  1572. SOCKADDR_IN lsi;
  1573. DWORD dwSize, dwTypes;
  1574. DPNHCAPS lCaps;
  1575. int j;
  1576. PMAPHANDLES pMap = g_PortHandles[i];
  1577. /*
  1578. * Call GetCaps so that we get an updated address list .
  1579. * Not sure why we would want any other kind...
  1580. */
  1581. lCaps.dwSize = sizeof(lCaps);
  1582. hr = IDirectPlayNATHelp_GetCaps(g_pDPNH, &lCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
  1583. for (j=0; j < pMap->iMapped; j++)
  1584. {
  1585. dwSize = sizeof(lsi);
  1586. ZeroMemory(&lsi, dwSize);
  1587. hr = IDirectPlayNATHelp_GetRegisteredAddresses(g_pDPNH, pMap->hMapped[j], (SOCKADDR *)&lsi,
  1588. &dwSize, &dwTypes, NULL, 0, );
  1589. if (hr == DPNH_OK && dwSize)
  1590. {
  1591. WCHAR scratch[32];
  1592. wsprintf(scratch, L"%d.%d.%d.%d:%d;",
  1593. lsi.sin_addr.S_un.S_un_b.s_b1,
  1594. lsi.sin_addr.S_un.S_un_b.s_b2,
  1595. lsi.sin_addr.S_un.S_un_b.s_b3,
  1596. lsi.sin_addr.S_un.S_un_b.s_b4,
  1597. ntohs( lsi.sin_port ));
  1598. wcscat(AddressLst, scratch);
  1599. TRIVIAL_MSG((L"GetRegisteredAddresses(0x%x)=[%s]", g_PortHandles[i], scratch ));
  1600. }
  1601. else
  1602. {
  1603. IMPORTANT_MSG((L"GetRegisteredAddresses[0x%x] failed, size=0x%x", g_PortHandles[i], dwSize));
  1604. DumpLibHr(hr);
  1605. }
  1606. }
  1607. goto got_addresses;
  1608. }
  1609. }
  1610. }
  1611. else
  1612. {
  1613. union AddrV4 {
  1614. DWORD d;
  1615. BYTE b[4];
  1616. };
  1617. WCHAR scratch[32];
  1618. union AddrV4 a;
  1619. RSIP_LEASE_RECORD *pLeaseWalker;
  1620. RSIP_LEASE_RECORD *pNextLease;
  1621. pLeaseWalker = g_pRsipLeaseRecords;
  1622. while( pLeaseWalker )
  1623. {
  1624. bSort=TRUE;
  1625. pNextLease = pLeaseWalker->pNext;
  1626. a.d = pLeaseWalker->addrV4;
  1627. wsprintf(scratch, L"%d.%d.%d.%d:%d;",
  1628. a.b[0],
  1629. a.b[1],
  1630. a.b[2],
  1631. a.b[3],
  1632. ntohs(pLeaseWalker->rport));
  1633. wcscat(AddressLst, scratch);
  1634. pLeaseWalker=pNextLease;
  1635. }
  1636. }
  1637. }
  1638. got_addresses:
  1639. iAddrLen = wcslen(AddressLst);
  1640. GetIPAddress(AddressLst+iAddrLen, WCHAR_CNT-iAddrLen, g_iPort);
  1641. if (IPflags & IPF_ADD_DNS)
  1642. {
  1643. WCHAR *DnsName=NULL;
  1644. DWORD dwNameSz=0;
  1645. GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, NULL, &dwNameSz);
  1646. dwNameSz++;
  1647. DnsName = (WCHAR *)malloc(dwNameSz * sizeof(WCHAR));
  1648. if (DnsName)
  1649. {
  1650. *DnsName = 0;
  1651. if (GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, DnsName, &dwNameSz))
  1652. {
  1653. if ((dwNameSz + iAddrLen) < WCHAR_CNT-4)
  1654. wcscat(AddressLst, DnsName);
  1655. if (g_iPort)
  1656. {
  1657. WCHAR scr[16];
  1658. wsprintf(scr, L":%d", g_iPort);
  1659. wcscat(AddressLst, scr);
  1660. }
  1661. }
  1662. free(DnsName);
  1663. }
  1664. }
  1665. if (!(IPflags & IPF_NO_SORT) && bSort)
  1666. {
  1667. WCHAR *lpStart;
  1668. WCHAR szLast[36];
  1669. int i=0;
  1670. TRIVIAL_MSG((L"Sorting address list : %s", AddressLst));
  1671. lpStart = AddressLst+iAddrLen;
  1672. while (*(lpStart+i) && *(lpStart+i) != L';')
  1673. {
  1674. szLast[i] = *(lpStart+i);
  1675. i++;
  1676. }
  1677. szLast[i++]=0;
  1678. wcscpy(lpStart, lpStart+i);
  1679. TRIVIAL_MSG((L"inter sort: %s, %s", AddressLst, szLast));
  1680. wcscat(AddressLst, L";");
  1681. wcscat(AddressLst, szLast);
  1682. TRIVIAL_MSG((L"sort done"));
  1683. }
  1684. if (IPflags & IPF_COMPRESS)
  1685. {
  1686. WCHAR compBfr[1000];
  1687. compBfr[0]=0;
  1688. SquishAddress(AddressLst, compBfr);
  1689. TRIVIAL_MSG((L"inner comp: %s, %s", AddressLst, compBfr));
  1690. wcscpy(AddressLst, compBfr);
  1691. }
  1692. dwRet = 1 + wcslen(AddressLst);
  1693. if (lpszAddr && iBufSize >= (int)dwRet)
  1694. memcpy(lpszAddr, AddressLst, dwRet*(sizeof(AddressLst[0])));
  1695. INTERESTING_MSG((L"Fetched all Ex-addresses:cnt=%d, sz=[%s]", dwRet, AddressLst));
  1696. free(AddressLst);
  1697. return dwRet;
  1698. }
  1699. // it is hard to imagine a machine with this many simultaneous connections, but it is possible, I suppose
  1700. #define RAS_CONNS 6
  1701. DWORD GetConnections()
  1702. {
  1703. DWORD dwRet;
  1704. RASCONN *lpRasConn, *lpFree;
  1705. DWORD lpcb, lpcConnections;
  1706. int i;
  1707. TRIVIAL_MSG((L"entered GetConnections"));
  1708. lpFree = NULL;
  1709. lpcb = RAS_CONNS * sizeof(RASCONN);
  1710. lpRasConn = (LPRASCONN) malloc(lpcb);
  1711. if (!lpRasConn) return 0;
  1712. lpFree = lpRasConn;
  1713. lpRasConn->dwSize = sizeof(RASCONN);
  1714. lpcConnections = RAS_CONNS;
  1715. dwRet = RasEnumConnections(lpRasConn, &lpcb, &lpcConnections);
  1716. if (dwRet != 0)
  1717. {
  1718. IMPORTANT_MSG((L"RasEnumConnections failed: Error = %d", dwRet));
  1719. free(lpFree);
  1720. return 0;
  1721. }
  1722. dwRet = 0;
  1723. TRIVIAL_MSG((L"Found %d connections", lpcConnections));
  1724. if (lpcConnections)
  1725. {
  1726. for (i = 0; i < (int)lpcConnections; i++)
  1727. {
  1728. TRIVIAL_MSG((L"Entry name: %s, type=%s\n", lpRasConn->szEntryName, lpRasConn->szDeviceType));
  1729. if (!_wcsicmp(lpRasConn->szDeviceType, RASDT_Modem ))
  1730. {
  1731. TRIVIAL_MSG((L"Found a modem (%s)", lpRasConn->szDeviceName));
  1732. dwRet |= 1;
  1733. }
  1734. else if (!_wcsicmp(lpRasConn->szDeviceType, RASDT_Vpn))
  1735. {
  1736. TRIVIAL_MSG((L"Found a VPN (%s)", lpRasConn->szDeviceName));
  1737. dwRet |= 2;
  1738. }
  1739. else
  1740. {
  1741. // probably ISDN, or something like that...
  1742. TRIVIAL_MSG((L"Found something else, (%s)", lpRasConn->szDeviceType));
  1743. dwRet |= 4;
  1744. }
  1745. lpRasConn++;
  1746. }
  1747. }
  1748. if (lpFree)
  1749. free(lpFree);
  1750. TRIVIAL_MSG((L"GetConnections returning 0x%x", dwRet));
  1751. return dwRet;
  1752. }
  1753. #undef RAS_CONNS
  1754. /****************************************************************************
  1755. **
  1756. ** GetIcsStatus(PICSSTAT pStat)
  1757. ** Returns a structure detailing much of what is going on inside this
  1758. ** library. The dwSize entry must be filled in before calling this
  1759. ** function. Use "sizeof(ICSSTAT))" to populate this.
  1760. **
  1761. ****************************************************************************/
  1762. DWORD APIENTRY GetIcsStatus(PICSSTAT pStat)
  1763. {
  1764. DWORD dwSz;
  1765. if (!pStat || pStat->dwSize > sizeof(ICSSTAT))
  1766. {
  1767. HEINOUS_E_MSG((L"ERROR:Bad pointer or size passed in to GetIcsStatus"));
  1768. return ERROR_INVALID_PARAMETER;
  1769. }
  1770. // clear out the struct
  1771. dwSz = pStat->dwSize;
  1772. ZeroMemory(pStat, dwSz);
  1773. pStat->dwSize = dwSz;
  1774. pStat->bIcsFound = g_boolIcsPresent;
  1775. pStat->bIcsServer = g_boolIcsOnThisMachine;
  1776. pStat->bUsingDP = g_boolUsingNatHelp;
  1777. if (g_boolUsingNatHelp)
  1778. pStat->bUsingUpnp = !g_boolUsingNatPAST;
  1779. if (g_boolIcsPresent)
  1780. {
  1781. wsprintf(pStat->wszPubAddr, L"%S", g_szPublicAddr);
  1782. wsprintf(pStat->wszLocAddr, L"%d.%d.%d.%d",
  1783. g_saddrLocal.sin_addr.S_un.S_un_b.s_b1,
  1784. g_saddrLocal.sin_addr.S_un.S_un_b.s_b2,
  1785. g_saddrLocal.sin_addr.S_un.S_un_b.s_b3,
  1786. g_saddrLocal.sin_addr.S_un.S_un_b.s_b4);
  1787. wsprintf(pStat->wszDllName, L"%S", g_lpszDllName);
  1788. }
  1789. else
  1790. wsprintf(pStat->wszDllName, L"none");
  1791. dwSz = GetConnections();
  1792. if (dwSz & 1)
  1793. pStat->bModemPresent = TRUE;
  1794. if (dwSz & 2)
  1795. pStat->bVpnPresent = TRUE;
  1796. return ERROR_SUCCESS;
  1797. }
  1798. /*************************************************************************************
  1799. **
  1800. **
  1801. *************************************************************************************/
  1802. int GetTsPort(void)
  1803. {
  1804. DWORD dwRet = 3389;
  1805. HKEY hKey;
  1806. // open reg key first, to get ALL the spew...HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp
  1807. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp", 0, KEY_READ, &hKey))
  1808. {
  1809. DWORD dwSize;
  1810. dwSize = sizeof(dwRet);
  1811. RegQueryValueEx(hKey, L"PortNumber", NULL, NULL, (LPBYTE)&dwRet, &dwSize);
  1812. RegCloseKey(hKey);
  1813. }
  1814. return dwRet;
  1815. }