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.

251 lines
6.8 KiB

  1. /*
  2. * lookup.cpp
  3. *
  4. * Purpose:
  5. * hostname lookup
  6. *
  7. * Owner:
  8. * EricAn
  9. *
  10. * History:
  11. * Jun 97: Created.
  12. *
  13. * Copyright (C) Microsoft Corp. 1997
  14. */
  15. #include <pch.hxx>
  16. #include <process.h>
  17. #include <demand.h>
  18. #include "lookup.h"
  19. ASSERTDATA
  20. #define HWND_ALLOC_NUM 4
  21. #define LOOKUP_ALLOC_NUM 16
  22. #define MAX_CACHED_ADDRS 16
  23. struct LOOKUPINFO {
  24. LPTSTR pszHostName;
  25. ULONG rgAddr[MAX_CACHED_ADDRS];
  26. ULONG cAddr;
  27. HTHREAD hThreadLookup;
  28. HWND *rgHwndNotify;
  29. ULONG cHwnd;
  30. ULONG cHwndAlloc;
  31. };
  32. static LOOKUPINFO *s_rgLookUp = NULL;
  33. static ULONG s_cLookUp = 0;
  34. static ULONG s_cLookUpAlloc = 0;
  35. static CRITICAL_SECTION s_csLookup;
  36. HRESULT AddHwnd(LOOKUPINFO *pLI, HWND hwnd)
  37. {
  38. HRESULT hr = S_OK;
  39. if (pLI->cHwnd == pLI->cHwndAlloc)
  40. {
  41. if (FAILED(HrRealloc((LPVOID*)&pLI->rgHwndNotify, (pLI->cHwndAlloc + HWND_ALLOC_NUM) * sizeof(HWND))))
  42. return E_OUTOFMEMORY;
  43. pLI->cHwndAlloc += HWND_ALLOC_NUM;
  44. }
  45. pLI->rgHwndNotify[pLI->cHwnd++] = hwnd;
  46. return S_OK;
  47. }
  48. unsigned int __stdcall LookupThreadProc(LPVOID pv)
  49. {
  50. LOOKUPINFO *pLI;
  51. LPHOSTENT pHostEnt;
  52. LPTSTR pszHostName;
  53. int iLastError = 0;
  54. ULONG ulAddr = (ULONG)-1, i;
  55. EnterCriticalSection(&s_csLookup);
  56. pszHostName = s_rgLookUp[(ULONG_PTR)pv].pszHostName;
  57. LeaveCriticalSection(&s_csLookup);
  58. // do the actual lookup
  59. pHostEnt = gethostbyname(pszHostName);
  60. if (NULL == pHostEnt)
  61. iLastError = WSAGetLastError();
  62. EnterCriticalSection(&s_csLookup);
  63. pLI = &s_rgLookUp[(ULONG_PTR)pv];
  64. if (pHostEnt)
  65. {
  66. // copy the returned addresses into our buffer
  67. while (pLI->cAddr < MAX_CACHED_ADDRS && pHostEnt->h_addr_list[pLI->cAddr])
  68. {
  69. pLI->rgAddr[pLI->cAddr] = *(ULONG *)(pHostEnt->h_addr_list[pLI->cAddr]);
  70. pLI->cAddr++;
  71. }
  72. ulAddr = pLI->rgAddr[0];
  73. }
  74. else
  75. {
  76. Assert(0 == pLI->cAddr);
  77. }
  78. // notify the registered windows that the lookup is complete
  79. for (i = 0; i < pLI->cHwnd; i++)
  80. if (IsWindow(pLI->rgHwndNotify[i]))
  81. PostMessage(pLI->rgHwndNotify[i], SPM_WSA_GETHOSTBYNAME, (WPARAM)iLastError, (LPARAM)ulAddr);
  82. pLI->cHwnd = 0;
  83. CloseHandle(pLI->hThreadLookup);
  84. pLI->hThreadLookup = NULL;
  85. LeaveCriticalSection(&s_csLookup);
  86. return 0;
  87. }
  88. void InitLookupCache(void)
  89. {
  90. InitializeCriticalSection(&s_csLookup);
  91. }
  92. void DeInitLookupCache(void)
  93. {
  94. ULONG i;
  95. LOOKUPINFO *pLI;
  96. HANDLE hThread;
  97. EnterCriticalSection(&s_csLookup);
  98. for (i = 0, pLI = s_rgLookUp; i < s_cLookUp; i++, pLI++)
  99. {
  100. if (pLI->hThreadLookup)
  101. {
  102. pLI->cHwnd = 0;
  103. // Raid 42360: WSACleanup() faults on Win95 if we still have a
  104. // lookup thread running. WaitForSingleObject() on a thread
  105. // doesn't seem to work at DLL_PROCESS_DETACH time.
  106. // TerminateThread() seems to be the only reliable solution -
  107. // gross but it works.
  108. TerminateThread(pLI->hThreadLookup, 0);
  109. CloseHandle(pLI->hThreadLookup);
  110. }
  111. SafeMemFree(pLI->pszHostName);
  112. SafeMemFree(pLI->rgHwndNotify);
  113. }
  114. SafeMemFree(s_rgLookUp);
  115. s_cLookUp = s_cLookUpAlloc = 0;
  116. LeaveCriticalSection(&s_csLookup);
  117. DeleteCriticalSection(&s_csLookup);
  118. }
  119. HRESULT LookupHostName(LPTSTR pszHostName, HWND hwndNotify, ULONG *pulAddr, LPBOOL pfCached, BOOL fForce)
  120. {
  121. ULONG i;
  122. LOOKUPINFO *pLI;
  123. HRESULT hr;
  124. DWORD uiThreadId;
  125. *pfCached = FALSE;
  126. EnterCriticalSection(&s_csLookup);
  127. for (i = 0, pLI = s_rgLookUp; i < s_cLookUp; i++, pLI++)
  128. {
  129. Assert(pLI->pszHostName);
  130. if (!lstrcmpi(pLI->pszHostName, pszHostName))
  131. {
  132. if (pLI->hThreadLookup)
  133. {
  134. // there's a lookup in progress, so just append
  135. hr = AddHwnd(pLI, hwndNotify);
  136. goto exit;
  137. }
  138. else if (fForce || !pLI->cAddr)
  139. {
  140. // a previous connect or lookup failed, so try again
  141. pLI->cAddr = 0;
  142. goto startlookup;
  143. }
  144. else
  145. {
  146. // we've got the address cached
  147. *pulAddr = pLI->rgAddr[0];
  148. *pfCached = TRUE;
  149. hr = S_OK;
  150. goto exit;
  151. }
  152. }
  153. }
  154. // we didn't find it, so add it
  155. if (s_cLookUp == s_cLookUpAlloc)
  156. {
  157. if (FAILED(hr = HrRealloc((LPVOID*)&s_rgLookUp, (s_cLookUpAlloc + LOOKUP_ALLOC_NUM) * sizeof(LOOKUPINFO))))
  158. goto exit;
  159. s_cLookUpAlloc += LOOKUP_ALLOC_NUM;
  160. ZeroMemory(&s_rgLookUp[s_cLookUp], LOOKUP_ALLOC_NUM * sizeof(LOOKUPINFO));
  161. pLI = &s_rgLookUp[s_cLookUp];
  162. }
  163. pLI->pszHostName = PszDup(pszHostName);
  164. if (NULL == pLI->pszHostName)
  165. {
  166. hr = E_OUTOFMEMORY;
  167. goto exit;
  168. }
  169. s_cLookUp++;
  170. startlookup:
  171. Assert(pLI->cAddr == 0);
  172. hr = AddHwnd(pLI, hwndNotify);
  173. if (FAILED(hr))
  174. goto exit;
  175. Assert(pLI->cHwnd == 1);
  176. // pLI->hThreadLookup = (HANDLE)_beginthreadex(NULL, 0, LookupThreadProc, (LPVOID)i, 0, &uiThreadId);
  177. pLI->hThreadLookup = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)LookupThreadProc, (LPVOID)IntToPtr(i), 0, &uiThreadId);
  178. if (NULL == pLI->hThreadLookup)
  179. {
  180. hr = E_FAIL;
  181. pLI->cHwnd = 0;
  182. }
  183. exit:
  184. LeaveCriticalSection(&s_csLookup);
  185. return hr;
  186. }
  187. HRESULT CancelLookup(LPTSTR pszHostName, HWND hwndNotify)
  188. {
  189. ULONG i, j, cMove;
  190. LOOKUPINFO *pLI;
  191. HRESULT hr = E_INVALIDARG;
  192. EnterCriticalSection(&s_csLookup);
  193. for (i = 0, pLI = s_rgLookUp; i < s_cLookUp; i++, pLI++)
  194. {
  195. Assert(pLI->pszHostName);
  196. if (!lstrcmpi(pLI->pszHostName, pszHostName))
  197. {
  198. for (j = 0; j < pLI->cHwnd; j++)
  199. {
  200. if (pLI->rgHwndNotify[j] == hwndNotify)
  201. {
  202. while (j + 1 < pLI->cHwnd)
  203. {
  204. pLI->rgHwndNotify[j] = pLI->rgHwndNotify[j+1];
  205. j++;
  206. }
  207. pLI->cHwnd--;
  208. hr = S_OK;
  209. break;
  210. }
  211. }
  212. break;
  213. }
  214. }
  215. LeaveCriticalSection(&s_csLookup);
  216. return hr;
  217. }