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

  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 "icshelpapi.h"
  29. #include <dpnathlp.h>
  30. #include <io.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <fcntl.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. /*****************************************************************************
  37. ** Some global variables
  38. *****************************************************************************/
  39. // the mark of the beast...
  40. #define NO_ICS_HANDLE 0x666
  41. #define ICS_HANDLE_OFFSET 0x4500
  42. long g_waitDuration=120000;
  43. BOOL g_boolIcsPresent = FALSE;
  44. BOOL g_boolFwPresent = FALSE;
  45. BOOL g_boolIcsOnThisMachine = FALSE;
  46. BOOL g_boolIcsFound = FALSE;
  47. BOOL g_boolInitialized = FALSE;
  48. BOOL g_StopFlag = FALSE;
  49. SOCKADDR_IN g_saddrLocal;
  50. char *g_lpszWierdICSAddress = NULL;
  51. HANDLE g_hWorkerThread = 0;
  52. HANDLE g_hStopThreadEvent=NULL;
  53. HANDLE g_hAlertEvent=NULL;
  54. int g_iPort;
  55. HMODULE g_hModDpNatHlp = NULL;
  56. PDIRECTPLAYNATHELP g_pDPNH = NULL;
  57. char g_szPublicAddr[45];
  58. char *g_lpszDllName = "NULL";
  59. char szInternal[]="internal";
  60. //
  61. // IP notify thread globals
  62. //
  63. HANDLE g_IpNotifyThread;
  64. DWORD g_IpNotifyThreadId;
  65. HANDLE g_IpNotifyEvent;
  66. HANDLE g_IpNotifyHandle = NULL;
  67. //OVERLAPPED g_IpNotifyOverlapped;
  68. DWORD WINAPI IPHlpThread(PVOID ContextPtr);
  69. typedef struct _MAPHANDLES {
  70. int iMapped;
  71. DPNHHANDLE hMapped[16];
  72. } MAPHANDLES, *PMAPHANDLES;
  73. int g_iPortHandles=0;
  74. PMAPHANDLES *g_PortHandles=NULL;
  75. int iDbgFileHandle;
  76. DWORD gDllFlag = 0xff;
  77. typedef struct _SUPDLLS {
  78. char *szDllName;
  79. BOOL bUsesUpnp; // TRUE if we ICS supports UPnP
  80. } SUPDLLS, *PSUPDLLS;
  81. SUPDLLS strDpHelp[] =
  82. {
  83. {"dpnhupnp.dll", TRUE},
  84. {"dpnhpast.dll", FALSE},
  85. {NULL, FALSE}
  86. };
  87. /******* USEFULL STUFF **********/
  88. #ifndef ARRAYSIZE
  89. #define ARRAYSIZE(x) sizeof(x)/sizeof(x[0])
  90. #endif
  91. // forward declares...
  92. int GetTsPort(void);
  93. DWORD CloseDpnh(HMODULE *, PDIRECTPLAYNATHELP *);
  94. int GetAllAdapters(int *iFound, int iMax, SOCKADDR_IN *sktArray);
  95. /****************************************************************************
  96. **
  97. ** DumpLibHr-
  98. ** Gives us debug spew for the HRESULTS coming back from DPNATHLP.DLL
  99. **
  100. ****************************************************************************/
  101. void DumpLibHr(HRESULT hr)
  102. {
  103. char *pErr = NULL;
  104. char scr[400];
  105. switch (hr){
  106. case DPNH_OK:
  107. pErr = "DPNH_OK";
  108. break;
  109. case DPNHSUCCESS_ADDRESSESCHANGED:
  110. pErr = "DPNHSUCCESS_ADDRESSESCHANGED";
  111. break;
  112. case DPNHERR_ALREADYINITIALIZED:
  113. pErr = "DPNHERR_ALREADYINITIALIZED";
  114. break;
  115. case DPNHERR_BUFFERTOOSMALL:
  116. pErr = "DPNHERR_BUFFERTOOSMALL";
  117. break;
  118. case DPNHERR_GENERIC:
  119. pErr = "DPNHERR_GENERIC";
  120. break;
  121. case DPNHERR_INVALIDFLAGS:
  122. pErr = "DPNHERR_INVALIDFLAGS";
  123. break;
  124. case DPNHERR_INVALIDOBJECT:
  125. pErr = "DPNHERR_INVALIDOBJECT";
  126. break;
  127. case DPNHERR_INVALIDPARAM:
  128. pErr = "DPNHERR_INVALIDPARAM";
  129. break;
  130. case DPNHERR_INVALIDPOINTER:
  131. pErr = "DPNHERR_INVALIDPOINTER";
  132. break;
  133. case DPNHERR_NOMAPPING:
  134. pErr = "DPNHERR_NOMAPPING";
  135. break;
  136. case DPNHERR_NOMAPPINGBUTPRIVATE:
  137. pErr = "DPNHERR_NOMAPPINGBUTPRIVATE";
  138. break;
  139. case DPNHERR_NOTINITIALIZED:
  140. pErr = "DPNHERR_NOTINITIALIZED";
  141. break;
  142. case DPNHERR_OUTOFMEMORY:
  143. pErr = "DPNHERR_OUTOFMEMORY";
  144. break;
  145. case DPNHERR_PORTALREADYREGISTERED:
  146. pErr = "DPNHERR_PORTALREADYREGISTERED";
  147. break;
  148. case DPNHERR_PORTUNAVAILABLE:
  149. pErr = "DPNHERR_PORTUNAVAILABLE";
  150. break;
  151. case DPNHERR_SERVERNOTAVAILABLE:
  152. pErr = "DPNHERR_SERVERNOTAVAILABLE";
  153. break;
  154. case DPNHERR_UPDATESERVERSTATUS:
  155. pErr = "DPNHERR_UPDATESERVERSTATUS";
  156. break;
  157. default:
  158. wsprintfA(scr, "unknown error: 0x%x", hr);
  159. pErr = scr;
  160. break;
  161. };
  162. IMPORTANT_MSG((L"DpNatHlp result=%S", pErr));
  163. }
  164. /****************************************************************************
  165. **
  166. ** GetAllAdapters
  167. **
  168. ****************************************************************************/
  169. int GetAllAdapters(int *iFound, int iMax, SOCKADDR_IN *sktArray)
  170. {
  171. PIP_ADAPTER_INFO p;
  172. PIP_ADDR_STRING ps;
  173. DWORD dw;
  174. ULONG ulSize = 0;
  175. int i=0;
  176. PIP_ADAPTER_INFO pAdpInfo = NULL;
  177. if (!iFound || !sktArray) return 1;
  178. *iFound = 0;
  179. ZeroMemory(sktArray, sizeof(SOCKADDR) * iMax);
  180. dw = GetAdaptersInfo(
  181. pAdpInfo,
  182. &ulSize );
  183. if( dw == ERROR_BUFFER_OVERFLOW )
  184. {
  185. pAdpInfo = (IP_ADAPTER_INFO*)malloc(ulSize);
  186. if (!pAdpInfo)
  187. {
  188. INTERESTING_MSG((L"GetAddr malloc failed"));
  189. return 1;
  190. }
  191. dw = GetAdaptersInfo(
  192. pAdpInfo,
  193. &ulSize);
  194. if (dw != ERROR_SUCCESS)
  195. {
  196. INTERESTING_MSG((L"GetAdaptersInfo failed"));
  197. free(pAdpInfo);
  198. return 1;
  199. }
  200. for(p=pAdpInfo; p!=NULL; p=p->Next)
  201. {
  202. for(ps = &(p->IpAddressList); ps; ps=ps->Next)
  203. {
  204. if (strcmp(ps->IpAddress.String, "0.0.0.0") != 0 && i < iMax)
  205. {
  206. sktArray[i].sin_family = AF_INET;
  207. sktArray[i].sin_addr.S_un.S_addr = inet_addr(ps->IpAddress.String);
  208. TRIVIAL_MSG((L"Found adapter #%d at [%S]", i+1, ps->IpAddress.String));
  209. i++;
  210. }
  211. }
  212. }
  213. *iFound = i;
  214. TRIVIAL_MSG((L"GetAllAdapters- %d found", *iFound));
  215. free(pAdpInfo);
  216. return 0;
  217. }
  218. INTERESTING_MSG((L"GetAdaptersInfo failed"));
  219. return 1;
  220. }
  221. /****************************************************************************
  222. **
  223. ** OpenPort(int port)
  224. ** if there is no ICS available, then we should just return...
  225. **
  226. ** Of course, we save away the Port, as it goes back in the
  227. ** FetchAllAddresses call, as the formatted "port" whenever a
  228. ** different one is not specified.
  229. **
  230. ****************************************************************************/
  231. DWORD APIENTRY OpenPort(int Port)
  232. {
  233. DWORD dwRet = (int)-1;
  234. TRIVIAL_MSG((L"OpenPort(%d)", Port ));
  235. if (!g_boolInitialized)
  236. {
  237. HEINOUS_E_MSG((L"ERROR: OpenPort- library not initialized"));
  238. return 0;
  239. }
  240. // save away for later retrieval
  241. g_iPort = Port;
  242. if (g_pDPNH && g_PortHandles)
  243. {
  244. HRESULT hr=0;
  245. int i;
  246. DPNHHANDLE *pHnd;
  247. SOCKADDR_IN lSockAddr[16];
  248. PMAPHANDLES hMap;
  249. for (i=0;i<g_iPortHandles && g_PortHandles[i] != NULL; i++);
  250. // are we running outta memory?
  251. // then double size of array
  252. if (i >= g_iPortHandles)
  253. {
  254. int new_handlecnt = g_iPortHandles*2;
  255. PMAPHANDLES *new_PortHandles = (PMAPHANDLES *)malloc(new_handlecnt * sizeof(PMAPHANDLES));
  256. if (new_PortHandles)
  257. {
  258. INTERESTING_MSG((L"Needed new handle memory: %d of %d used up, now requesting %d", i, g_iPortHandles, new_handlecnt));
  259. ZeroMemory(new_PortHandles, new_handlecnt * sizeof(PMAPHANDLES));
  260. CopyMemory(new_PortHandles, g_PortHandles, g_iPortHandles * sizeof(PMAPHANDLES));
  261. free(g_PortHandles);
  262. g_PortHandles = new_PortHandles;
  263. i = g_iPortHandles;
  264. g_iPortHandles = new_handlecnt;
  265. }
  266. else
  267. {
  268. // we have no more memory for mappings!
  269. // should never hit this, unless we are leaking...
  270. HEINOUS_E_MSG((L"Out of table space in OpenPort"));
  271. return 0;
  272. }
  273. }
  274. // now we have a pointer for our handle array
  275. hMap = (PMAPHANDLES)malloc(sizeof(MAPHANDLES));
  276. if (!hMap)
  277. {
  278. IMPORTANT_MSG((L"out of memory in OpenPort"));
  279. dwRet = 0;
  280. goto done;
  281. }
  282. g_PortHandles[i] = hMap;
  283. dwRet = ICS_HANDLE_OFFSET + i;
  284. // get adapters
  285. if( GetAllAdapters(&hMap->iMapped, ARRAYSIZE(lSockAddr), &lSockAddr[0]) == 1 )
  286. {
  287. // an error occurred
  288. INTERESTING_MSG((L"OpenPort@GetAllAdapters failed"));
  289. dwRet = 0;
  290. goto done;
  291. }
  292. TRIVIAL_MSG((L"GetAllAdapters found %d adapters to deal with", hMap->iMapped));
  293. /* Now we cycle through all the found adapters and get a mapping for each
  294. * This insures that the ICF is opened on all adapters...
  295. */
  296. for (i = 0; i < hMap->iMapped; i++)
  297. {
  298. pHnd = &hMap->hMapped[i];
  299. lSockAddr[i].sin_port = ntohs((unsigned)Port);
  300. hr = IDirectPlayNATHelp_RegisterPorts(g_pDPNH,
  301. (SOCKADDR *)&lSockAddr[i], sizeof(lSockAddr[0]), 1,
  302. 30000, pHnd, DPNHREGISTERPORTS_TCP);
  303. if (hr != DPNH_OK)
  304. {
  305. IMPORTANT_MSG((L"RegisterPorts failed in OpenPort for adapter #%d, ", i ));
  306. DumpLibHr(hr);
  307. }
  308. else
  309. {
  310. TRIVIAL_MSG((L"OpenPort Assigned: 0x%x", *pHnd));
  311. }
  312. }
  313. }
  314. else
  315. {
  316. dwRet = NO_ICS_HANDLE;
  317. TRIVIAL_MSG((L"OpenPort- no ICS found"));
  318. }
  319. done:
  320. TRIVIAL_MSG((L"OpenPort- returns 0x%x", dwRet ));
  321. return dwRet;
  322. }
  323. /****************************************************************************
  324. **
  325. ** Called to close a port, whenever a ticket is expired or closed.
  326. **
  327. ****************************************************************************/
  328. DWORD APIENTRY ClosePort(DWORD MapHandle)
  329. {
  330. DWORD dwRet = ERROR_SUCCESS;
  331. DWORD dwIndex;
  332. TRIVIAL_MSG((L"ClosePort(0x%x)", MapHandle ));
  333. if (!g_boolInitialized)
  334. {
  335. HEINOUS_E_MSG((L"ERROR: ClosePort- library not initialized"));
  336. return ERROR_INVALID_PARAMETER;
  337. }
  338. // if we didn't open this thru the ICS, then just return
  339. if (!g_pDPNH && MapHandle == NO_ICS_HANDLE)
  340. {
  341. return ERROR_SUCCESS;
  342. }
  343. dwIndex = MapHandle - ICS_HANDLE_OFFSET;
  344. if (g_pDPNH && dwIndex < (DWORD)g_iPortHandles)
  345. {
  346. HRESULT hr=0;
  347. int i;
  348. PMAPHANDLES pMap = g_PortHandles[dwIndex];
  349. if (pMap)
  350. {
  351. TRIVIAL_MSG((L"closing %d port mappings", pMap->iMapped));
  352. for (i = 0; i < pMap->iMapped; i++)
  353. {
  354. hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, pMap->hMapped[i], 0);
  355. if (hr != DPNH_OK)
  356. {
  357. IMPORTANT_MSG((L"DeregisterPorts failed in ClosePort for handle 0x%x", pMap->hMapped[i]));
  358. DumpLibHr(hr);
  359. dwRet = ERROR_INVALID_ACCESS;
  360. }
  361. }
  362. // remove the handle from our array
  363. free(g_PortHandles[dwIndex]);
  364. g_PortHandles[dwIndex] = NULL;
  365. }
  366. else
  367. {
  368. IMPORTANT_MSG((L"Port handle mapping corrupted in ClosePort!!"));
  369. dwRet = ERROR_INVALID_PARAMETER;
  370. }
  371. }
  372. else
  373. {
  374. IMPORTANT_MSG((L"Bad handle passed into ClosePort!!"));
  375. dwRet = ERROR_INVALID_PARAMETER;
  376. }
  377. TRIVIAL_MSG((L"ClosePort returning 0x%x", dwRet ));
  378. return(dwRet);
  379. }
  380. /****************************************************************************
  381. **
  382. ** FetchAllAddresses
  383. ** Returns a string listing all the valid IP addresses for the machine
  384. ** Formatting details:
  385. ** 1. Each address is seperated with a ";" (semicolon)
  386. ** 2. Each address consists of the "1.2.3.4", and is followed by ":p"
  387. ** where the colon is followed by the port number
  388. **
  389. ****************************************************************************/
  390. DWORD APIENTRY FetchAllAddresses(WCHAR *lpszAddr, int iBufSize)
  391. {
  392. return FetchAllAddressesEx(lpszAddr, iBufSize, IPF_ADD_DNS);
  393. }
  394. /****************************************************************************
  395. **
  396. ** CloseAllPorts
  397. ** Does just that- closes all port mappings that have been opened
  398. **
  399. ****************************************************************************/
  400. DWORD APIENTRY CloseAllOpenPorts(void)
  401. {
  402. DWORD dwRet = 1;
  403. int iClosed=0;
  404. INTERESTING_MSG((L"CloseAllOpenPorts()" ));
  405. if (g_pDPNH)
  406. {
  407. HRESULT hr=0;
  408. int i;
  409. // call DPNATHLP to unregister the mapping
  410. // then remove the handle from our array
  411. for (i = 0; i < g_iPortHandles; i++)
  412. {
  413. if (g_PortHandles[i])
  414. {
  415. PMAPHANDLES pMap = g_PortHandles[i];
  416. int j;
  417. for (j = 0; j < pMap->iMapped; j++)
  418. {
  419. hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, pMap->hMapped[j], 0);
  420. if (hr != DPNH_OK)
  421. {
  422. IMPORTANT_MSG((L"DeregisterPorts failed in CloseAllOpenPorts"));
  423. DumpLibHr(hr);
  424. }
  425. }
  426. iClosed++;
  427. free(g_PortHandles[i]);
  428. g_PortHandles[i] = 0;
  429. }
  430. }
  431. }
  432. else
  433. {
  434. IMPORTANT_MSG((L"IDirectPlay interface not initialized in CloseAllOpenPorts!!"));
  435. dwRet = ERROR_INVALID_ACCESS;
  436. }
  437. if (iClosed) TRIVIAL_MSG((L"Closed %d open ports", iClosed));
  438. return(dwRet);
  439. }
  440. /****************************************************************************
  441. **
  442. ** The worker thread for use with the DPHATHLP.DLL.
  443. **
  444. ** This keeps the leases updated on any open
  445. ** port assignments. Eventually, this will also check & update the sessmgr
  446. ** when the ICS comes & goes, or when the address list changes.
  447. **
  448. ****************************************************************************/
  449. DWORD WINAPI DpNatHlpThread(PVOID ContextPtr)
  450. {
  451. DWORD dwRet=1;
  452. DWORD dwWaitResult=WAIT_TIMEOUT;
  453. long l_waitTime = g_waitDuration;
  454. TRIVIAL_MSG((L"+++ DpNatHlpThread()" ));
  455. /*
  456. * The 2 minute wait loop
  457. */
  458. while(dwWaitResult == WAIT_TIMEOUT)
  459. {
  460. DWORD dwTime;
  461. if (g_pDPNH)
  462. {
  463. HRESULT hr;
  464. DPNHCAPS lCaps;
  465. /* Call GetCaps to renew all open leases */
  466. lCaps.dwSize = sizeof(lCaps);
  467. hr = IDirectPlayNATHelp_GetCaps(g_pDPNH, &lCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
  468. if (hr == DPNH_OK || hr == DPNHSUCCESS_ADDRESSESCHANGED)
  469. {
  470. if (hr == DPNHSUCCESS_ADDRESSESCHANGED)
  471. {
  472. TRIVIAL_MSG((L"+++ ICS address changed"));
  473. if (g_hAlertEvent)
  474. SetEvent(g_hAlertEvent);
  475. }
  476. // else
  477. // TRIVIAL_MSG((L"+++ ICS address change not found"));
  478. if (lCaps.dwRecommendedGetCapsInterval)
  479. l_waitTime = min(g_waitDuration, (long)lCaps.dwRecommendedGetCapsInterval);
  480. }
  481. else
  482. {
  483. IMPORTANT_MSG((L"+++ GetCaps failed in DpNatHlpThread"));
  484. DumpLibHr(hr);
  485. }
  486. }
  487. dwWaitResult = WaitForSingleObject(g_hStopThreadEvent, l_waitTime);
  488. }
  489. TRIVIAL_MSG((L"+++ DpNatHlpThread shutting down"));
  490. /*
  491. * Then the shutdown code
  492. * free all memory
  493. * then close out DPNATHLP.DLL
  494. * and return all objects
  495. */
  496. CloseDpnh(&g_hModDpNatHlp, &g_pDPNH);
  497. CloseHandle(g_hStopThreadEvent);
  498. TRIVIAL_MSG((L"+++ DpNatHlpThread() returning 0x%x", dwRet ));
  499. WSACleanup();
  500. ExitThread(dwRet);
  501. // of course we never get this far...
  502. return(dwRet);
  503. }
  504. BOOL GetUnusedPort(USHORT *pPort, SOCKET *pSocket)
  505. {
  506. SOCKADDR sa;
  507. SOCKET s;
  508. ULONG icmd;
  509. int ilen, status;
  510. s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  511. if (s == INVALID_SOCKET)
  512. {
  513. INTERESTING_MSG((L"Failed to create socket: %d",WSAGetLastError()));
  514. return FALSE;
  515. }
  516. //Bind the socket to a dynamically assigned port.
  517. memset(&sa,0,sizeof(sa));
  518. sa.sa_family=AF_INET;
  519. status = bind(s,&sa,sizeof(sa));
  520. if (status != NO_ERROR)
  521. {
  522. closesocket(s);
  523. return FALSE;
  524. }
  525. ilen = sizeof(sa);
  526. status = getsockname(s, &sa, &ilen);
  527. if (status)
  528. {
  529. INTERESTING_MSG((L"getsockname failed 0x%x", status));
  530. closesocket(s);
  531. return FALSE;
  532. }
  533. else
  534. {
  535. *pPort = ntohs((*((SOCKADDR_IN *) &sa)).sin_port);
  536. *pSocket = s;
  537. INTERESTING_MSG((L"found unused port=%d", *pPort));
  538. }
  539. return TRUE;
  540. }
  541. /****************************************************************************
  542. **
  543. ** This will close the NAT DLL
  544. **
  545. ****************************************************************************/
  546. DWORD CloseDpnh(HMODULE *hMod, PDIRECTPLAYNATHELP *pDirectPlayNATHelp)
  547. {
  548. DWORD dwRet = ERROR_SUCCESS;
  549. if (pDirectPlayNATHelp && *pDirectPlayNATHelp)
  550. {
  551. HRESULT hr = IDirectPlayNATHelp_Close(*pDirectPlayNATHelp, 0);
  552. if (hr != DPNH_OK)
  553. {
  554. IMPORTANT_MSG((L"IDirectPlayNATHelp_Close failed"));
  555. DumpLibHr(hr);
  556. }
  557. hr = IDirectPlayNATHelp_Release(*pDirectPlayNATHelp);
  558. if (hr != DPNH_OK)
  559. {
  560. IMPORTANT_MSG((L"IDirectPlayNATHelp_Release failed"));
  561. DumpLibHr(hr);
  562. }
  563. *pDirectPlayNATHelp = 0;
  564. }
  565. if (hMod && *hMod)
  566. {
  567. FreeLibrary(*hMod);
  568. *hMod = 0;
  569. }
  570. return dwRet;
  571. }
  572. /****************************************************************************
  573. **
  574. ** This will load up each DLL and return the capabilities of it...
  575. **
  576. ****************************************************************************/
  577. DWORD LoadDpnh(char *szDll, HMODULE *hMod, PDIRECTPLAYNATHELP *pDPnh, DWORD *dwCaps)
  578. {
  579. DPNHCAPS dpnhCaps;
  580. DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
  581. PFN_DIRECTPLAYNATHELPCREATE pfnDirectPlayNATHelpCreate;
  582. HRESULT hr;
  583. TRIVIAL_MSG((L"starting LoadDpnh for %S", szDll));
  584. /* Sanity check the params... */
  585. if (!szDll || !hMod || !pDPnh || !dwCaps)
  586. {
  587. IMPORTANT_MSG((L"ERROR: bad params passed to LoadDpnh, cannot continue"));
  588. dwRet = ERROR_INVALID_PARAMETER;
  589. goto done;
  590. }
  591. /* now clear all values returned */
  592. *hMod = 0;
  593. *pDPnh = NULL;
  594. *dwCaps = 0;
  595. *hMod = LoadLibraryA(szDll);
  596. if (!*hMod)
  597. {
  598. IMPORTANT_MSG((L"ERROR:%S could not be found", szDll));
  599. dwRet = ERROR_FILE_NOT_FOUND;
  600. goto done;
  601. }
  602. pfnDirectPlayNATHelpCreate = (PFN_DIRECTPLAYNATHELPCREATE) GetProcAddress(*hMod, "DirectPlayNATHelpCreate");
  603. if (!pfnDirectPlayNATHelpCreate)
  604. {
  605. IMPORTANT_MSG((L"\"DirectPlayNATHelpCreate\" proc in %S could not be found", szDll));
  606. FreeLibrary(*hMod);
  607. *hMod = 0;
  608. dwRet = ERROR_INVALID_FUNCTION;
  609. goto done;
  610. }
  611. hr = pfnDirectPlayNATHelpCreate(&IID_IDirectPlayNATHelp,
  612. (void**) (pDPnh));
  613. if (hr != DPNH_OK)
  614. {
  615. IMPORTANT_MSG((L"DirectPlayNATHelpCreate failed in %S", szDll));
  616. DumpLibHr(hr);
  617. FreeLibrary(*hMod);
  618. *hMod = 0;
  619. dwRet = ERROR_BAD_UNIT;
  620. goto done;
  621. }
  622. hr = IDirectPlayNATHelp_Initialize(*pDPnh, 0);
  623. if (hr != DPNH_OK)
  624. {
  625. IMPORTANT_MSG((L"IDirectPlayNATHelp_Initialize failed in %S", szDll));
  626. DumpLibHr(hr);
  627. CloseDpnh( hMod , pDPnh );
  628. // FreeLibrary(*hMod);
  629. *hMod = 0;
  630. dwRet = ERROR_BAD_UNIT;
  631. goto done;
  632. }
  633. /* Get capabilities of NAT server */
  634. dpnhCaps.dwSize = sizeof(dpnhCaps);
  635. hr = IDirectPlayNATHelp_GetCaps(*pDPnh, &dpnhCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
  636. if (hr != DPNH_OK && hr != DPNHSUCCESS_ADDRESSESCHANGED)
  637. {
  638. IMPORTANT_MSG((L"IDirectPlayNATHelp_GetCaps failed"));
  639. DumpLibHr(hr);
  640. CloseDpnh(hMod, pDPnh);
  641. dwRet = ERROR_BAD_UNIT;
  642. goto done;
  643. }
  644. *dwCaps = dpnhCaps.dwFlags;
  645. dwRet = ERROR_SUCCESS;
  646. done:
  647. TRIVIAL_MSG((L"done with LoadDpnh, result=0x%x caps=0x%x for %S", dwRet, dwCaps?*dwCaps:0, szDll?szDll:"NULL"));
  648. return dwRet;
  649. }
  650. DWORD GetAddr(SOCKADDR_IN *saddr)
  651. {
  652. PIP_ADAPTER_INFO p;
  653. PIP_ADDR_STRING ps;
  654. DWORD dw;
  655. ULONG ulSize = 0;
  656. PIP_ADAPTER_INFO pAdpInfo = NULL;
  657. dw = GetAdaptersInfo(
  658. pAdpInfo,
  659. &ulSize );
  660. if( dw == ERROR_BUFFER_OVERFLOW )
  661. {
  662. pAdpInfo = (IP_ADAPTER_INFO*)malloc(ulSize);
  663. if (!pAdpInfo)
  664. {
  665. INTERESTING_MSG((L"GetAddr malloc failed"));
  666. return 1;
  667. }
  668. dw = GetAdaptersInfo(
  669. pAdpInfo,
  670. &ulSize);
  671. if (dw != ERROR_SUCCESS)
  672. {
  673. INTERESTING_MSG((L"GetAdaptersInfo failed"));
  674. free(pAdpInfo);
  675. return 1;
  676. }
  677. for(p=pAdpInfo; p!=NULL; p=p->Next)
  678. {
  679. for(ps = &(p->IpAddressList); ps; ps=ps->Next)
  680. {
  681. if (strcmp(ps->IpAddress.String, "0.0.0.0") != 0)
  682. {
  683. // blah blah blah
  684. saddr->sin_addr.S_un.S_addr = inet_addr(ps->IpAddress.String);
  685. TRIVIAL_MSG((L"Initializing local address to [%S]", ps->IpAddress.String));
  686. free(pAdpInfo);
  687. return 0;
  688. }
  689. }
  690. }
  691. INTERESTING_MSG((L"GetAddr- none found"));
  692. free(pAdpInfo);
  693. return 1;
  694. }
  695. INTERESTING_MSG((L"GetAdaptersInfo failed"));
  696. return 1;
  697. }
  698. /****************************************************************************
  699. **
  700. ** This should initialize the ICS library for use with the DirectPlay
  701. ** ICS/NAT helper DLL.
  702. **
  703. ****************************************************************************/
  704. DWORD StartDpNatHlp(void)
  705. {
  706. DWORD dwRet = ERROR_CALL_NOT_IMPLEMENTED;
  707. DWORD dwUPNP = ERROR_CALL_NOT_IMPLEMENTED, dwPAST = ERROR_CALL_NOT_IMPLEMENTED, dwCapsUPNP=0, dwCapsPAST=0;
  708. HRESULT hr;
  709. HMODULE hModUPNP=0, hModPAST=0;
  710. PFN_DIRECTPLAYNATHELPCREATE pfnDirectPlayNATHelpCreate;
  711. PDIRECTPLAYNATHELP pDirectPlayNATHelpUPNP=NULL, pDirectPlayNATHelpPAST=NULL;
  712. // start out with no public address
  713. g_szPublicAddr[0] = 0;
  714. /* load up both DLLs so that we can compare capabilities */
  715. if (gDllFlag & 1) dwUPNP = LoadDpnh("dpnhupnp.dll", &hModUPNP, &pDirectPlayNATHelpUPNP, &dwCapsUPNP);
  716. if (gDllFlag & 2) dwPAST = LoadDpnh("dpnhpast.dll", &hModPAST, &pDirectPlayNATHelpPAST, &dwCapsPAST);
  717. if (dwUPNP != ERROR_SUCCESS && dwPAST != ERROR_SUCCESS)
  718. {
  719. IMPORTANT_MSG((L"ERROR: could not load either NAT dll"));
  720. if (!gDllFlag)
  721. dwRet = ERROR_SUCCESS;
  722. goto done;
  723. }
  724. #if 0 // fix for #418776
  725. /* If no NAT is found, then close both and go away */
  726. if (!(dwCapsUPNP & (DPNHCAPSFLAG_GATEWAYPRESENT | DPNHCAPSFLAG_LOCALFIREWALLPRESENT)) &&
  727. !(dwCapsPAST & (DPNHCAPSFLAG_GATEWAYPRESENT | DPNHCAPSFLAG_LOCALFIREWALLPRESENT)))
  728. {
  729. CloseDpnh(&hModUPNP, &pDirectPlayNATHelpUPNP);
  730. CloseDpnh(&hModPAST, &pDirectPlayNATHelpPAST);
  731. dwRet = ERROR_BAD_UNIT;
  732. TRIVIAL_MSG((L"No NAT or firewall device found"));
  733. goto done;
  734. }
  735. #endif
  736. /*
  737. * Now we must compare the capabilities of the two NAT interfaces and select the most
  738. * "capable" one. If it is a tie, then we should choose the UPNP form, as that will
  739. * be more stable.
  740. */
  741. if ((dwCapsPAST & DPNHCAPSFLAG_GATEWAYPRESENT) &&
  742. !(dwCapsUPNP & DPNHCAPSFLAG_GATEWAYPRESENT))
  743. {
  744. // there must be a WinME ICS box out there- we better use PAST
  745. g_boolIcsPresent = TRUE;
  746. TRIVIAL_MSG((L"WinME ICS discovered, using PAST"));
  747. if (dwCapsPAST & DPNHCAPSFLAG_LOCALFIREWALLPRESENT)
  748. {
  749. TRIVIAL_MSG((L"local firewall found"));
  750. g_boolFwPresent = TRUE;
  751. }
  752. g_pDPNH = pDirectPlayNATHelpPAST;
  753. g_hModDpNatHlp = hModPAST;
  754. g_lpszDllName = "dpnhpast.dll";
  755. CloseDpnh(&hModUPNP, &pDirectPlayNATHelpUPNP);
  756. }
  757. else if ((dwCapsPAST & DPNHCAPSFLAG_PUBLICADDRESSAVAILABLE) &&
  758. !(dwCapsUPNP & DPNHCAPSFLAG_PUBLICADDRESSAVAILABLE))
  759. {
  760. // that blasted UPNP is hung again- we better use PAST
  761. g_boolIcsPresent = TRUE;
  762. TRIVIAL_MSG((L"Hung UPnP discovered, using PAST"));
  763. if (dwCapsPAST & DPNHCAPSFLAG_LOCALFIREWALLPRESENT)
  764. {
  765. TRIVIAL_MSG((L"local firewall found"));
  766. g_boolFwPresent = TRUE;
  767. }
  768. g_pDPNH = pDirectPlayNATHelpPAST;
  769. g_hModDpNatHlp = hModPAST;
  770. g_lpszDllName = "dpnhpast.dll";
  771. CloseDpnh(&hModUPNP, &pDirectPlayNATHelpUPNP);
  772. }
  773. else
  774. {
  775. // default to UPNP
  776. if (dwCapsUPNP & DPNHCAPSFLAG_GATEWAYPRESENT)
  777. {
  778. TRIVIAL_MSG((L"UPnP NAT gateway found"));
  779. g_boolIcsPresent = TRUE;
  780. }
  781. if (dwCapsUPNP & DPNHCAPSFLAG_LOCALFIREWALLPRESENT)
  782. {
  783. TRIVIAL_MSG((L"local firewall found"));
  784. g_boolFwPresent = TRUE;
  785. }
  786. if (dwCapsUPNP & DPNHCAPSFLAG_GATEWAYISLOCAL)
  787. g_boolIcsOnThisMachine = TRUE;
  788. g_lpszDllName = "dpnhupnp.dll";
  789. g_pDPNH = pDirectPlayNATHelpUPNP;
  790. g_hModDpNatHlp = hModUPNP;
  791. CloseDpnh(&hModPAST, &pDirectPlayNATHelpPAST);
  792. }
  793. dwRet = ERROR_SUCCESS;
  794. if (g_boolIcsPresent)
  795. {
  796. // PIP_ADAPTER_INFO pAdpInfo = NULL;
  797. SOCKADDR_IN saddrOurLAN;
  798. PMIB_IPADDRTABLE pmib=NULL;
  799. ULONG ulSize = 0;
  800. DWORD dw;
  801. DPNHHANDLE dpHnd;
  802. USHORT port;
  803. SOCKET s;
  804. dwRet = ERROR_SUCCESS;
  805. ZeroMemory(&saddrOurLAN, sizeof(saddrOurLAN));
  806. saddrOurLAN.sin_family = AF_INET;
  807. saddrOurLAN.sin_addr.S_un.S_addr = INADDR_ANY;
  808. memcpy(&g_saddrLocal, &saddrOurLAN, sizeof(saddrOurLAN));
  809. GetAddr(&g_saddrLocal);
  810. // Does the ICS have a public address?
  811. // then we must discover the public address
  812. if (!GetUnusedPort(&port, &s))
  813. {
  814. dwRet = ERROR_OUTOFMEMORY;
  815. goto done;
  816. }
  817. saddrOurLAN.sin_port = port;
  818. /* first we ask for a new mapping */
  819. hr = IDirectPlayNATHelp_RegisterPorts(g_pDPNH,
  820. (SOCKADDR *)&saddrOurLAN, sizeof(saddrOurLAN), 1,
  821. 30000, &dpHnd, DPNHREGISTERPORTS_TCP);
  822. closesocket(s);
  823. if (hr != DPNH_OK)
  824. {
  825. IMPORTANT_MSG((L"IDirectPlayNATHelp_RegisterPorts failed in StartDpNatHlp"));
  826. DumpLibHr(hr);
  827. }
  828. else
  829. {
  830. /* we succeeded, so query for the address */
  831. SOCKADDR_IN lsi;
  832. DWORD dwSize, dwTypes;
  833. TRIVIAL_MSG((L"IDirectPlayNATHelp_RegisterPorts Assigned: 0x%x", dpHnd));
  834. dwSize = sizeof(lsi);
  835. ZeroMemory(&lsi, dwSize);
  836. hr = IDirectPlayNATHelp_GetRegisteredAddresses(g_pDPNH, dpHnd, (SOCKADDR *)&lsi,
  837. &dwSize, &dwTypes, NULL, 0);
  838. if (hr == DPNH_OK && dwSize)
  839. {
  840. wsprintfA(g_szPublicAddr, "%d.%d.%d.%d",
  841. lsi.sin_addr.S_un.S_un_b.s_b1,
  842. lsi.sin_addr.S_un.S_un_b.s_b2,
  843. lsi.sin_addr.S_un.S_un_b.s_b3,
  844. lsi.sin_addr.S_un.S_un_b.s_b4);
  845. TRIVIAL_MSG((L"Public Address=[%S]", g_szPublicAddr ));
  846. }
  847. else
  848. {
  849. IMPORTANT_MSG((L"GetRegisteredAddresses[0x%x] failed, size=0x%x", dpHnd, dwSize));
  850. DumpLibHr(hr);
  851. }
  852. /* close out the temp port we got */
  853. hr = IDirectPlayNATHelp_DeregisterPorts(g_pDPNH, dpHnd, 0);
  854. if (hr != DPNH_OK)
  855. {
  856. IMPORTANT_MSG((L"DeregisterPorts failed in StartDpNatHlp"));
  857. DumpLibHr(hr);
  858. dwRet = ERROR_INVALID_ACCESS;
  859. }
  860. }
  861. }
  862. done:
  863. TRIVIAL_MSG((L"done with StartDpNatHlp, result=0x%x", dwRet));
  864. return dwRet;
  865. };
  866. /****************************************************************************
  867. **
  868. ** The first call to be made into this library. It is responsible for
  869. ** starting up all worker threads, initializing all memory and libs,
  870. ** and starting up the DPHLPAPI.DLL function (if found).
  871. **
  872. ****************************************************************************/
  873. DWORD APIENTRY StartICSLib(void)
  874. {
  875. WSADATA WsaData;
  876. DWORD dwThreadId;
  877. HANDLE hEvent, hThread;
  878. HKEY hKey;
  879. int sktRet = ERROR_SUCCESS;
  880. // open reg key first, to get ALL the spew...
  881. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\ICSHelper", 0, KEY_READ, &hKey))
  882. {
  883. DWORD dwSize;
  884. dwSize = sizeof(gDbgFlag);
  885. RegQueryValueEx(hKey, L"DebugSpew", NULL, NULL, (LPBYTE)&gDbgFlag, &dwSize);
  886. dwSize = sizeof(gDllFlag);
  887. RegQueryValueEx(hKey, L"ProtocolLimits", NULL, NULL, (LPBYTE)&gDllFlag, &dwSize);
  888. dwSize = 0;
  889. if (g_lpszWierdICSAddress)
  890. {
  891. free(g_lpszWierdICSAddress);
  892. g_lpszWierdICSAddress= NULL;
  893. }
  894. RegQueryValueEx(hKey, L"NonStandardICSAddress", NULL, NULL, (LPBYTE)g_lpszWierdICSAddress, &dwSize);
  895. if (dwSize)
  896. {
  897. g_lpszWierdICSAddress = malloc((dwSize+1) * sizeof(*g_lpszWierdICSAddress));
  898. if( g_lpszWierdICSAddress == NULL )
  899. {
  900. RegCloseKey(hKey);
  901. sktRet = ERROR_NOT_ENOUGH_MEMORY;
  902. goto hard_clean_up;
  903. }
  904. RegQueryValueEx(hKey, L"NonStandardICSAddress", NULL, NULL, (LPBYTE)g_lpszWierdICSAddress, &dwSize);
  905. }
  906. g_waitDuration = 0;
  907. dwSize = sizeof(g_waitDuration);
  908. RegQueryValueEx(hKey, L"RetryTimeout", NULL, NULL, (LPBYTE)&g_waitDuration, &dwSize);
  909. if (g_waitDuration)
  910. g_waitDuration *= 1000;
  911. else
  912. g_waitDuration = 120000;
  913. RegCloseKey(hKey);
  914. }
  915. // should we create a debug log file?
  916. if (gDbgFlag & DBG_MSG_DEST_FILE)
  917. {
  918. WCHAR *szLogfileName=NULL;
  919. WCHAR *szLogname=L"\\SalemICSHelper.log";
  920. int iChars;
  921. iChars = GetSystemDirectory(szLogfileName, 0);
  922. iChars += lstrlen(szLogname);
  923. iChars += 4;
  924. szLogfileName = (WCHAR *)malloc(iChars * sizeof(WCHAR));
  925. if (szLogfileName)
  926. {
  927. ZeroMemory(szLogfileName, iChars * sizeof(WCHAR));
  928. GetSystemDirectory(szLogfileName, iChars);
  929. lstrcat(szLogfileName, szLogname);
  930. iDbgFileHandle = _wopen(szLogfileName, _O_APPEND | _O_BINARY | _O_RDWR, 0);
  931. if (-1 != iDbgFileHandle)
  932. {
  933. OutputDebugStringA("opened debug log file\n");
  934. }
  935. else
  936. {
  937. unsigned char UniCode[2] = {0xff, 0xfe};
  938. // we must create the file
  939. OutputDebugStringA("must create debug log file");
  940. iDbgFileHandle = _wopen(szLogfileName, _O_BINARY | _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE);
  941. if (-1 != iDbgFileHandle)
  942. _write(iDbgFileHandle, &UniCode, sizeof(UniCode));
  943. else
  944. {
  945. OutputDebugStringA("ERROR: failed to create debug log file");
  946. iDbgFileHandle = 0;
  947. }
  948. }
  949. free(szLogfileName);
  950. }
  951. }
  952. g_iPort = GetTsPort();
  953. g_iPortHandles = 256;
  954. g_PortHandles = (PMAPHANDLES *)malloc(g_iPortHandles * sizeof(PMAPHANDLES));
  955. if( g_PortHandles == NULL )
  956. {
  957. g_iPortHandles = 0;
  958. sktRet = ERROR_NOT_ENOUGH_MEMORY;
  959. goto hard_clean_up;
  960. }
  961. ZeroMemory(g_PortHandles, g_iPortHandles * sizeof(PMAPHANDLES));
  962. TRIVIAL_MSG((L"StartICSLib(), using %d PortHandles", g_iPortHandles));
  963. if (g_boolInitialized)
  964. {
  965. HEINOUS_E_MSG((L"ERROR: StartICSLib called twice"));
  966. sktRet = ERROR_ALREADY_INITIALIZED;
  967. goto hard_clean_up;
  968. }
  969. else
  970. g_boolInitialized = TRUE;
  971. // create an event for later use by the daemon thread
  972. hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  973. if (!hEvent)
  974. {
  975. IMPORTANT_MSG((L"Could not create an event for RSIP worker thread, err=0x%x", GetLastError()));
  976. sktRet = GetLastError();
  977. goto hard_clean_up;
  978. }
  979. g_hStopThreadEvent = hEvent;
  980. if (0 != WSAStartup(MAKEWORD(2,2), &WsaData))
  981. {
  982. if (0 != (sktRet = WSAStartup(MAKEWORD(2,0), &WsaData)))
  983. {
  984. IMPORTANT_MSG((L"WSAStartup failed:"));
  985. goto hard_clean_up;
  986. }
  987. }
  988. if (ERROR_SUCCESS == StartDpNatHlp())
  989. {
  990. // start RSIP daemon process, which will do all the work
  991. hThread = CreateThread( NULL, // SD- not needed
  992. 0, // Stack Size
  993. (LPTHREAD_START_ROUTINE)DpNatHlpThread,
  994. NULL,
  995. 0,
  996. &dwThreadId );
  997. if (!hThread)
  998. {
  999. IMPORTANT_MSG((L"Could not create RSIP worker thread, err=0x%x", GetLastError()));
  1000. sktRet = GetLastError();
  1001. goto hard_clean_up;
  1002. }
  1003. // save this for later, as we may need it in the close function
  1004. g_hWorkerThread = hThread;
  1005. }
  1006. TRIVIAL_MSG((L"StartICSLib() returning ERROR_SUCCESS"));
  1007. return(ERROR_SUCCESS);
  1008. hard_clean_up:
  1009. //
  1010. // free up all memory we created
  1011. // set all counters to zero
  1012. // make sure no threads are started
  1013. // return proper error
  1014. // act like stopics
  1015. if( g_hWorkerThread != NULL && g_hStopThreadEvent != NULL )
  1016. {
  1017. SetEvent( g_hStopThreadEvent );
  1018. WaitForSingleObject( g_hWorkerThread , 1000 );
  1019. CloseHandle( g_hWorkerThread );
  1020. g_hWorkerThread = NULL;
  1021. }
  1022. if( g_hStopThreadEvent != NULL )
  1023. {
  1024. CloseHandle( g_hStopThreadEvent );
  1025. g_hStopThreadEvent = NULL;
  1026. }
  1027. if( g_lpszWierdICSAddress != NULL )
  1028. {
  1029. free( g_lpszWierdICSAddress );
  1030. g_lpszWierdICSAddress = NULL;
  1031. }
  1032. if( g_PortHandles != NULL )
  1033. {
  1034. free( g_PortHandles );
  1035. g_PortHandles = NULL;
  1036. }
  1037. if( iDbgFileHandle != 0 )
  1038. {
  1039. _close( iDbgFileHandle );
  1040. iDbgFileHandle = 0;
  1041. }
  1042. return( sktRet );
  1043. }
  1044. /****************************************************************************
  1045. **
  1046. ** The last call to be made into this library. Do not call any other
  1047. ** function in this library after you call this!
  1048. **
  1049. ****************************************************************************/
  1050. DWORD APIENTRY StopICSLib(void)
  1051. {
  1052. DWORD dwRet = ERROR_SUCCESS;
  1053. DWORD dwTmp;
  1054. TRIVIAL_MSG((L"StopICSLib()" ));
  1055. if (!g_boolInitialized)
  1056. {
  1057. HEINOUS_E_MSG((L"ERROR: StopICSLib- library not initialized"));
  1058. return ERROR_INVALID_PARAMETER;
  1059. }
  1060. // signal the worker threads, so that they will shut down
  1061. // kill the IP address change thread
  1062. g_StopFlag = TRUE;
  1063. if (g_IpNotifyHandle)
  1064. CancelIo(g_IpNotifyHandle);
  1065. // then stop the ICS lease-renewal thread.
  1066. if (g_hStopThreadEvent && g_hWorkerThread)
  1067. {
  1068. SetEvent(g_hStopThreadEvent);
  1069. // then wait for it to shutdown.
  1070. dwTmp = WaitForSingleObject(g_hWorkerThread, 15000);
  1071. if (dwTmp == WAIT_OBJECT_0)
  1072. TRIVIAL_MSG((L"ICS worker thread closed down normally"));
  1073. else if (dwTmp == WAIT_ABANDONED)
  1074. IMPORTANT_MSG((L"ICS worker thread did not complete in 15 seconds"));
  1075. else
  1076. IMPORTANT_MSG((L"WaitForWorkerThread failed"));
  1077. CloseHandle(g_hWorkerThread);
  1078. g_hWorkerThread = NULL;
  1079. }
  1080. else
  1081. WSACleanup();
  1082. TRIVIAL_MSG((L"StopICSLib() returning 0x%x", dwRet ));
  1083. if (iDbgFileHandle)
  1084. _close(iDbgFileHandle);
  1085. iDbgFileHandle = 0;
  1086. if (g_lpszWierdICSAddress)
  1087. free(g_lpszWierdICSAddress);
  1088. g_lpszWierdICSAddress = NULL;
  1089. if (g_PortHandles) free(g_PortHandles);
  1090. g_PortHandles = NULL;
  1091. g_boolInitialized = FALSE;
  1092. return(dwRet);
  1093. }
  1094. /****************************************************************************
  1095. **
  1096. ** FetchAllAddressesEx
  1097. ** Returns a string listing all the valid IP addresses for the machine
  1098. ** controlled by a set of "flags". These are as follows:
  1099. ** IPflags=
  1100. ** IPF_ADD_DNS adds the DNS name to the IP list
  1101. ** IPF_COMPRESS compresses the IP address list (exclusive w/ IPF_ADD_DNS)
  1102. ** IPF_NO_SORT do not sort adapter IP list
  1103. **
  1104. ** Formatting details:
  1105. ** 1. Each address is seperated with a ";" (semicolon)
  1106. ** 2. Each address consists of the "1.2.3.4", and is followed by ":p"
  1107. ** where the colon is followed by the port number
  1108. **
  1109. ****************************************************************************/
  1110. #define WCHAR_CNT 4096
  1111. DWORD APIENTRY FetchAllAddressesEx(WCHAR *lpszAddr, int iBufSize, int IPflags)
  1112. {
  1113. DWORD dwRet = 1;
  1114. WCHAR *AddressLst;
  1115. int iAddrLen;
  1116. BOOL bSort=FALSE;
  1117. int bufSizeLeft;
  1118. AddressLst = (WCHAR *) malloc(WCHAR_CNT * sizeof(WCHAR));
  1119. if (!AddressLst)
  1120. {
  1121. HEINOUS_E_MSG((L"Fatal error: malloc failed in FetchAllAddressesEx"));
  1122. return 0;
  1123. }
  1124. *AddressLst = 0;
  1125. INTERESTING_MSG((L"FetchAllAddressesEx()" ));
  1126. bufSizeLeft = WCHAR_CNT;
  1127. if (g_boolIcsPresent && g_pDPNH)
  1128. {
  1129. int i;
  1130. // gotta cycle through the g_PortHandles list...
  1131. for (i=0;i<g_iPortHandles; i++)
  1132. {
  1133. if (g_PortHandles[i])
  1134. {
  1135. HRESULT hr = E_FAIL;
  1136. SOCKADDR_IN lsi;
  1137. DWORD dwSize, dwTypes;
  1138. DPNHCAPS lCaps;
  1139. int j;
  1140. PMAPHANDLES pMap = g_PortHandles[i];
  1141. /*
  1142. * Call GetCaps so that we get an updated address list .
  1143. * Not sure why we would want any other kind...
  1144. */
  1145. lCaps.dwSize = sizeof(lCaps);
  1146. hr = IDirectPlayNATHelp_GetCaps(g_pDPNH, &lCaps, DPNHGETCAPS_UPDATESERVERSTATUS);
  1147. for (j=0; j < pMap->iMapped; j++)
  1148. {
  1149. dwSize = sizeof(lsi);
  1150. ZeroMemory(&lsi, dwSize);
  1151. hr = IDirectPlayNATHelp_GetRegisteredAddresses(g_pDPNH, pMap->hMapped[j], (SOCKADDR *)&lsi,
  1152. &dwSize, &dwTypes, NULL, 0);
  1153. if (hr == DPNH_OK && dwSize)
  1154. {
  1155. WCHAR scratch[32];
  1156. _snwprintf(scratch , 32 , L"%d.%d.%d.%d:%d;",
  1157. lsi.sin_addr.S_un.S_un_b.s_b1,
  1158. lsi.sin_addr.S_un.S_un_b.s_b2,
  1159. lsi.sin_addr.S_un.S_un_b.s_b3,
  1160. lsi.sin_addr.S_un.S_un_b.s_b4,
  1161. ntohs( lsi.sin_port ));
  1162. scratch[31] = 0;
  1163. bufSizeLeft -= wcslen( scratch );
  1164. if( bufSizeLeft > 0 )
  1165. {
  1166. wcscat(AddressLst, scratch);
  1167. AddressLst[ WCHAR_CNT - bufSizeLeft] = 0;
  1168. }
  1169. TRIVIAL_MSG((L"GetRegisteredAddresses(0x%x)=[%s]", g_PortHandles[i], scratch ));
  1170. }
  1171. else
  1172. {
  1173. IMPORTANT_MSG((L"GetRegisteredAddresses[0x%x] failed, size=0x%x", g_PortHandles[i], dwSize));
  1174. DumpLibHr(hr);
  1175. }
  1176. }
  1177. goto got_address;
  1178. }
  1179. }
  1180. }
  1181. else if (g_lpszWierdICSAddress)
  1182. {
  1183. _snwprintf( AddressLst , WCHAR_CNT , L"%s;", g_lpszWierdICSAddress);
  1184. AddressLst[ WCHAR_CNT - 1 ] = 0;
  1185. }
  1186. got_address:
  1187. iAddrLen = wcslen(AddressLst);
  1188. GetIPAddress(AddressLst+iAddrLen, WCHAR_CNT-iAddrLen, g_iPort);
  1189. //
  1190. // GetIPAddress could have taken some of our buffer space
  1191. // reduce bufSizeLeft appropriately
  1192. //
  1193. bufSizeLeft = WCHAR_CNT - wcslen(AddressLst);
  1194. if (IPflags & IPF_ADD_DNS)
  1195. {
  1196. WCHAR *DnsName=NULL;
  1197. DWORD dwNameSz=0;
  1198. GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, NULL, &dwNameSz);
  1199. dwNameSz++;
  1200. DnsName = (WCHAR *)malloc(dwNameSz * sizeof(WCHAR));
  1201. if (DnsName)
  1202. {
  1203. *DnsName = 0;
  1204. if (GetComputerNameEx(ComputerNamePhysicalDnsFullyQualified, DnsName, &dwNameSz))
  1205. {
  1206. //if ((dwNameSz + iAddrLen) < WCHAR_CNT-4)
  1207. if( ( ( int )dwNameSz ) < bufSizeLeft )
  1208. {
  1209. bufSizeLeft -= dwNameSz;
  1210. wcsncat( AddressLst, DnsName , dwNameSz );
  1211. AddressLst[ WCHAR_CNT - bufSizeLeft ] = 0;
  1212. }
  1213. if (g_iPort)
  1214. {
  1215. WCHAR scr[16];
  1216. _snwprintf(scr, 16 , L":%d", g_iPort);
  1217. scr[15] = 0;
  1218. bufSizeLeft -= wcslen( scr );
  1219. if( bufSizeLeft > 0 )
  1220. {
  1221. wcscat(AddressLst, scr);
  1222. AddressLst[ WCHAR_CNT - bufSizeLeft ] = 0;
  1223. }
  1224. }
  1225. }
  1226. free(DnsName);
  1227. }
  1228. }
  1229. if (!(IPflags & IPF_NO_SORT) && bSort)
  1230. {
  1231. WCHAR *lpStart;
  1232. WCHAR szLast[36];
  1233. int i=0;
  1234. TRIVIAL_MSG((L"Sorting address list : %s", AddressLst));
  1235. lpStart = AddressLst+iAddrLen;
  1236. while (*(lpStart+i) && *(lpStart+i) != L';')
  1237. {
  1238. szLast[i] = *(lpStart+i);
  1239. i++;
  1240. }
  1241. szLast[i++]=0;
  1242. wcscpy(lpStart, lpStart+i);
  1243. TRIVIAL_MSG((L"inter sort: %s, %s", AddressLst, szLast));
  1244. bufSizeLeft -= wcslen( szLast ) + 1; // 1 is for ';'
  1245. if( bufSizeLeft > 0 )
  1246. {
  1247. wcscat(AddressLst, L";");
  1248. wcscat(AddressLst, szLast);
  1249. AddressLst[ WCHAR_CNT - bufSizeLeft ] = 0;
  1250. }
  1251. TRIVIAL_MSG((L"sort done"));
  1252. }
  1253. dwRet = 1 + wcslen(AddressLst);
  1254. if (lpszAddr && iBufSize >= (int)dwRet)
  1255. memcpy(lpszAddr, AddressLst, dwRet*(sizeof(AddressLst[0])));
  1256. INTERESTING_MSG((L"Fetched all Ex-addresses:cnt=%d, sz=[%s]", dwRet, AddressLst));
  1257. free(AddressLst);
  1258. return dwRet;
  1259. }
  1260. // it is hard to imagine a machine with this many simultaneous connections, but it is possible, I suppose
  1261. #define RAS_CONNS 6
  1262. DWORD GetConnections()
  1263. {
  1264. DWORD dwRet;
  1265. RASCONN *lpRasConn, *lpFree;
  1266. DWORD lpcb, lpcConnections;
  1267. int i;
  1268. TRIVIAL_MSG((L"entered GetConnections"));
  1269. lpFree = NULL;
  1270. lpcb = RAS_CONNS * sizeof(RASCONN);
  1271. lpRasConn = (LPRASCONN) malloc(lpcb);
  1272. if (!lpRasConn) return 0;
  1273. lpFree = lpRasConn;
  1274. lpRasConn->dwSize = sizeof(RASCONN);
  1275. lpcConnections = RAS_CONNS;
  1276. dwRet = RasEnumConnections(lpRasConn, &lpcb, &lpcConnections);
  1277. if (dwRet != 0)
  1278. {
  1279. IMPORTANT_MSG((L"RasEnumConnections failed: Error = %d", dwRet));
  1280. free(lpFree);
  1281. return 0;
  1282. }
  1283. dwRet = 0;
  1284. TRIVIAL_MSG((L"Found %d connections", lpcConnections));
  1285. if (lpcConnections)
  1286. {
  1287. for (i = 0; i < (int)lpcConnections; i++)
  1288. {
  1289. TRIVIAL_MSG((L"Entry name: %s, type=%s", lpRasConn->szEntryName, lpRasConn->szDeviceType));
  1290. if (!_wcsicmp(lpRasConn->szDeviceType, RASDT_Modem ))
  1291. {
  1292. TRIVIAL_MSG((L"Found a modem (%s)", lpRasConn->szDeviceName));
  1293. dwRet |= 1;
  1294. }
  1295. else if (!_wcsicmp(lpRasConn->szDeviceType, RASDT_Vpn))
  1296. {
  1297. TRIVIAL_MSG((L"Found a VPN (%s)", lpRasConn->szDeviceName));
  1298. dwRet |= 2;
  1299. }
  1300. else
  1301. {
  1302. // probably ISDN, or something like that...
  1303. TRIVIAL_MSG((L"Found something else, (%s)", lpRasConn->szDeviceType));
  1304. dwRet |= 4;
  1305. }
  1306. lpRasConn++;
  1307. }
  1308. }
  1309. if (lpFree)
  1310. free(lpFree);
  1311. TRIVIAL_MSG((L"GetConnections returning 0x%x", dwRet));
  1312. return dwRet;
  1313. }
  1314. #undef RAS_CONNS
  1315. /****************************************************************************
  1316. **
  1317. ** GetIcsStatus(PICSSTAT pStat)
  1318. ** Returns a structure detailing much of what is going on inside this
  1319. ** library. The dwSize entry must be filled in before calling this
  1320. ** function. Use "sizeof(ICSSTAT))" to populate this.
  1321. **
  1322. ****************************************************************************/
  1323. DWORD APIENTRY GetIcsStatus(PICSSTAT pStat)
  1324. {
  1325. DWORD dwSz;
  1326. if (!pStat || pStat->dwSize != sizeof( ICSSTAT ) )
  1327. {
  1328. HEINOUS_E_MSG((L"ERROR:Bad pointer or size passed in to GetIcsStatus"));
  1329. return ERROR_INVALID_PARAMETER;
  1330. }
  1331. // clear out the struct
  1332. dwSz = pStat->dwSize;
  1333. ZeroMemory(pStat, dwSz);
  1334. pStat->dwSize = dwSz;
  1335. pStat->bIcsFound = g_boolIcsPresent;
  1336. pStat->bFwFound = g_boolFwPresent;
  1337. pStat->bIcsServer = g_boolIcsOnThisMachine;
  1338. if (g_boolIcsPresent)
  1339. {
  1340. dwSz = sizeof( pStat->wszPubAddr ) / sizeof( WCHAR );
  1341. _snwprintf( pStat->wszPubAddr , dwSz , L"%S", g_szPublicAddr );
  1342. pStat->wszPubAddr[ dwSz - 1 ] = L'\0';
  1343. dwSz = sizeof( pStat->wszLocAddr ) / sizeof( WCHAR );
  1344. _snwprintf( pStat->wszLocAddr , dwSz , L"%d.%d.%d.%d",
  1345. g_saddrLocal.sin_addr.S_un.S_un_b.s_b1,
  1346. g_saddrLocal.sin_addr.S_un.S_un_b.s_b2,
  1347. g_saddrLocal.sin_addr.S_un.S_un_b.s_b3,
  1348. g_saddrLocal.sin_addr.S_un.S_un_b.s_b4);
  1349. pStat->wszLocAddr[ dwSz - 1 ] = L'\0';
  1350. dwSz = sizeof( pStat->wszDllName ) / sizeof( WCHAR );
  1351. _snwprintf( pStat->wszDllName , dwSz , L"%S", g_lpszDllName);
  1352. pStat->wszDllName[ dwSz - 1 ] = L'\0';
  1353. }
  1354. else
  1355. {
  1356. if( g_lpszWierdICSAddress != NULL )
  1357. {
  1358. dwSz = sizeof( pStat->wszPubAddr ) / sizeof( WCHAR );
  1359. _snwprintf( pStat->wszPubAddr , dwSz , L"%S", g_lpszWierdICSAddress);
  1360. pStat->wszPubAddr[ dwSz - 1 ] = L'\0';
  1361. }
  1362. // this is ok wszDllName is 32 characters long
  1363. wsprintf(pStat->wszDllName, L"none");
  1364. }
  1365. dwSz = GetConnections();
  1366. if (dwSz & 1)
  1367. pStat->bModemPresent = TRUE;
  1368. if (dwSz & 2)
  1369. pStat->bVpnPresent = TRUE;
  1370. return ERROR_SUCCESS;
  1371. }
  1372. #if 0 // bug id 547112 removing dead code
  1373. /****************************************************************************
  1374. **
  1375. ** SetAlertEvent
  1376. ** Pass in an event handle. Then, whenever the ICS changes state, I
  1377. ** will signal that event.
  1378. **
  1379. ****************************************************************************/
  1380. DWORD APIENTRY SetAlertEvent(HANDLE hEvent)
  1381. {
  1382. TRIVIAL_MSG((L"SetAlertEvent(0x%x)", hEvent));
  1383. if (!g_hAlertEvent && hEvent)
  1384. {
  1385. /* Our first entry here, so we should start up all our IO CompletionPort hooie... */
  1386. #if 0
  1387. //
  1388. // create event for overlapped I/O
  1389. //
  1390. g_IpNotifyEvent = CreateEvent(
  1391. NULL, // no security descriptor
  1392. TRUE, // manual reset event
  1393. FALSE, // start not signalled
  1394. L"g_IpNotifyEvent");
  1395. if ( !g_IpNotifyEvent )
  1396. {
  1397. DWORD status = GetLastError();
  1398. IMPORTANT_MSG((L"FAILED to create IP notify event = %d", status));
  1399. }
  1400. #endif
  1401. g_IpNotifyThread = CreateThread(
  1402. NULL,
  1403. 0,
  1404. (LPTHREAD_START_ROUTINE) IPHlpThread,
  1405. NULL,
  1406. 0,
  1407. & g_IpNotifyThreadId
  1408. );
  1409. if ( !g_IpNotifyThread )
  1410. {
  1411. DWORD status = GetLastError();
  1412. IMPORTANT_MSG((L"FAILED to create IP notify thread = %d", status));
  1413. }
  1414. }
  1415. g_hAlertEvent = hEvent;
  1416. return ERROR_SUCCESS;
  1417. }
  1418. #endif
  1419. /*************************************************************************************
  1420. **
  1421. **
  1422. *************************************************************************************/
  1423. int GetTsPort(void)
  1424. {
  1425. DWORD dwRet = 3389;
  1426. HKEY hKey;
  1427. // open reg key first, to get ALL the spew...HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp
  1428. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp", 0, KEY_READ, &hKey))
  1429. {
  1430. DWORD dwSize;
  1431. dwSize = sizeof(dwRet);
  1432. RegQueryValueEx(hKey, L"PortNumber", NULL, NULL, (LPBYTE)&dwRet, &dwSize);
  1433. RegCloseKey(hKey);
  1434. }
  1435. return dwRet;
  1436. }
  1437. #if 0
  1438. /*************************************************************************************
  1439. **
  1440. **
  1441. *************************************************************************************/
  1442. DWORD WINAPI IPHlpThread(PVOID ContextPtr)
  1443. {
  1444. DWORD status=0;
  1445. DWORD bytesRecvd;
  1446. BOOL fstartedNotify=FALSE;
  1447. BOOL fhaveIpChange = FALSE;
  1448. BOOL fsleep = FALSE;
  1449. HANDLE notifyHandle=0;
  1450. OVERLAPPED IpNotifyOverlapped;
  1451. TRIVIAL_MSG((L"*** IPHlpThread begins"));
  1452. g_IpNotifyHandle = NULL;
  1453. /*
  1454. * Then the wait loop
  1455. */
  1456. while ( !g_StopFlag )
  1457. {
  1458. //
  1459. // spin protect
  1460. // - if error in previous NotifyAddrChange or
  1461. // GetOverlappedResult do short sleep to avoid
  1462. // chance of hard spin
  1463. //
  1464. if ( fsleep )
  1465. {
  1466. /* if signalled, it means quittin' time */
  1467. if (WAIT_TIMEOUT != WaitForSingleObject(g_hStopThreadEvent, 60000 ))
  1468. goto Done;
  1469. fsleep = FALSE;
  1470. }
  1471. if ( g_StopFlag )
  1472. {
  1473. goto Done;
  1474. }
  1475. if (notifyHandle)
  1476. {
  1477. // CloseHandle(notifyHandle);
  1478. notifyHandle = 0;
  1479. }
  1480. RtlZeroMemory(&IpNotifyOverlapped, sizeof(IpNotifyOverlapped) );
  1481. fstartedNotify = FALSE;
  1482. status = NotifyAddrChange(
  1483. & notifyHandle,
  1484. & IpNotifyOverlapped );
  1485. if ( status == ERROR_IO_PENDING )
  1486. {
  1487. TRIVIAL_MSG((L"*** NotifyAddrChange succeeded"));
  1488. g_IpNotifyHandle = notifyHandle;
  1489. fstartedNotify = TRUE;
  1490. }
  1491. else
  1492. {
  1493. IMPORTANT_MSG((L"*** NotifyAddrChange() FAILED\n\tstatus = %d\n\thandle = %d\n\toverlapped event = %d\n",status,notifyHandle,IpNotifyOverlapped.hEvent ));
  1494. fsleep = TRUE;
  1495. }
  1496. if ( fhaveIpChange )
  1497. {
  1498. INTERESTING_MSG((L"*** IP change detected"));
  1499. SetEvent(g_hAlertEvent);
  1500. fhaveIpChange = FALSE;
  1501. }
  1502. //
  1503. // anti-spin protection
  1504. // - 15 second sleep between any notifications
  1505. //
  1506. if (WAIT_TIMEOUT != WaitForSingleObject(g_hStopThreadEvent, 15000 ))
  1507. goto Done;
  1508. //
  1509. // wait on notification
  1510. // - save notification result
  1511. // - sleep on error, but never if notification
  1512. //
  1513. if ( fstartedNotify )
  1514. {
  1515. fhaveIpChange = GetOverlappedResult(
  1516. g_IpNotifyHandle,
  1517. & IpNotifyOverlapped,
  1518. & bytesRecvd,
  1519. TRUE // wait
  1520. );
  1521. if ( !fhaveIpChange )
  1522. {
  1523. status = GetLastError();
  1524. fsleep = TRUE;
  1525. IMPORTANT_MSG((L"*** GetOverlappedResult() status = 0x%x",status ));
  1526. }
  1527. else
  1528. {
  1529. TRIVIAL_MSG((L"*** GetOverlappedResult() found change"));
  1530. }
  1531. }
  1532. }
  1533. Done:
  1534. TRIVIAL_MSG((L"*** Stop IP Notify thread shutdown" ));
  1535. if ( g_IpNotifyHandle )
  1536. {
  1537. CloseHandle(g_IpNotifyHandle);
  1538. g_IpNotifyHandle = NULL;
  1539. }
  1540. return( status );
  1541. }
  1542. #endif