|
|
/*
* lookup.cpp * * Purpose: * hostname lookup * * Owner: * EricAn * * History: * Jun 97: Created. * * Copyright (C) Microsoft Corp. 1997 */
#include <pch.hxx>
#include <process.h>
#include <demand.h>
#include "lookup.h"
ASSERTDATA
#define HWND_ALLOC_NUM 4
#define LOOKUP_ALLOC_NUM 16
#define MAX_CACHED_ADDRS 16
struct LOOKUPINFO { LPTSTR pszHostName; ULONG rgAddr[MAX_CACHED_ADDRS]; ULONG cAddr; HTHREAD hThreadLookup; HWND *rgHwndNotify; ULONG cHwnd; ULONG cHwndAlloc; };
static LOOKUPINFO *s_rgLookUp = NULL; static ULONG s_cLookUp = 0; static ULONG s_cLookUpAlloc = 0;
static CRITICAL_SECTION s_csLookup;
HRESULT AddHwnd(LOOKUPINFO *pLI, HWND hwnd) { HRESULT hr = S_OK;
if (pLI->cHwnd == pLI->cHwndAlloc) { if (FAILED(HrRealloc((LPVOID*)&pLI->rgHwndNotify, (pLI->cHwndAlloc + HWND_ALLOC_NUM) * sizeof(HWND)))) return E_OUTOFMEMORY; pLI->cHwndAlloc += HWND_ALLOC_NUM; }
pLI->rgHwndNotify[pLI->cHwnd++] = hwnd; return S_OK; }
unsigned int __stdcall LookupThreadProc(LPVOID pv) { LOOKUPINFO *pLI; LPHOSTENT pHostEnt; LPTSTR pszHostName; int iLastError = 0; ULONG ulAddr = (ULONG)-1, i;
EnterCriticalSection(&s_csLookup); pszHostName = s_rgLookUp[(ULONG_PTR)pv].pszHostName; LeaveCriticalSection(&s_csLookup);
// do the actual lookup
pHostEnt = gethostbyname(pszHostName); if (NULL == pHostEnt) iLastError = WSAGetLastError();
EnterCriticalSection(&s_csLookup); pLI = &s_rgLookUp[(ULONG_PTR)pv]; if (pHostEnt) { // copy the returned addresses into our buffer
while (pLI->cAddr < MAX_CACHED_ADDRS && pHostEnt->h_addr_list[pLI->cAddr]) { pLI->rgAddr[pLI->cAddr] = *(ULONG *)(pHostEnt->h_addr_list[pLI->cAddr]); pLI->cAddr++; } ulAddr = pLI->rgAddr[0]; } else { Assert(0 == pLI->cAddr); } // notify the registered windows that the lookup is complete
for (i = 0; i < pLI->cHwnd; i++) if (IsWindow(pLI->rgHwndNotify[i])) PostMessage(pLI->rgHwndNotify[i], SPM_WSA_GETHOSTBYNAME, (WPARAM)iLastError, (LPARAM)ulAddr); pLI->cHwnd = 0; CloseHandle(pLI->hThreadLookup); pLI->hThreadLookup = NULL; LeaveCriticalSection(&s_csLookup);
return 0; }
void InitLookupCache(void) { InitializeCriticalSection(&s_csLookup); }
void DeInitLookupCache(void) { ULONG i; LOOKUPINFO *pLI; HANDLE hThread;
EnterCriticalSection(&s_csLookup); for (i = 0, pLI = s_rgLookUp; i < s_cLookUp; i++, pLI++) { if (pLI->hThreadLookup) { pLI->cHwnd = 0; // Raid 42360: WSACleanup() faults on Win95 if we still have a
// lookup thread running. WaitForSingleObject() on a thread
// doesn't seem to work at DLL_PROCESS_DETACH time.
// TerminateThread() seems to be the only reliable solution -
// gross but it works.
TerminateThread(pLI->hThreadLookup, 0); CloseHandle(pLI->hThreadLookup); } SafeMemFree(pLI->pszHostName); SafeMemFree(pLI->rgHwndNotify); } SafeMemFree(s_rgLookUp); s_cLookUp = s_cLookUpAlloc = 0; LeaveCriticalSection(&s_csLookup); DeleteCriticalSection(&s_csLookup); }
HRESULT LookupHostName(LPTSTR pszHostName, HWND hwndNotify, ULONG *pulAddr, LPBOOL pfCached, BOOL fForce) { ULONG i; LOOKUPINFO *pLI; HRESULT hr; DWORD uiThreadId;
*pfCached = FALSE;
EnterCriticalSection(&s_csLookup);
for (i = 0, pLI = s_rgLookUp; i < s_cLookUp; i++, pLI++) { Assert(pLI->pszHostName); if (!lstrcmpi(pLI->pszHostName, pszHostName)) { if (pLI->hThreadLookup) { // there's a lookup in progress, so just append
hr = AddHwnd(pLI, hwndNotify); goto exit; } else if (fForce || !pLI->cAddr) { // a previous connect or lookup failed, so try again
pLI->cAddr = 0; goto startlookup; } else { // we've got the address cached
*pulAddr = pLI->rgAddr[0]; *pfCached = TRUE; hr = S_OK; goto exit; } } }
// we didn't find it, so add it
if (s_cLookUp == s_cLookUpAlloc) { if (FAILED(hr = HrRealloc((LPVOID*)&s_rgLookUp, (s_cLookUpAlloc + LOOKUP_ALLOC_NUM) * sizeof(LOOKUPINFO)))) goto exit; s_cLookUpAlloc += LOOKUP_ALLOC_NUM; ZeroMemory(&s_rgLookUp[s_cLookUp], LOOKUP_ALLOC_NUM * sizeof(LOOKUPINFO)); pLI = &s_rgLookUp[s_cLookUp]; }
pLI->pszHostName = PszDup(pszHostName); if (NULL == pLI->pszHostName) { hr = E_OUTOFMEMORY; goto exit; }
s_cLookUp++;
startlookup: Assert(pLI->cAddr == 0);
hr = AddHwnd(pLI, hwndNotify); if (FAILED(hr)) goto exit;
Assert(pLI->cHwnd == 1);
// pLI->hThreadLookup = (HANDLE)_beginthreadex(NULL, 0, LookupThreadProc, (LPVOID)i, 0, &uiThreadId);
pLI->hThreadLookup = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)LookupThreadProc, (LPVOID)IntToPtr(i), 0, &uiThreadId); if (NULL == pLI->hThreadLookup) { hr = E_FAIL; pLI->cHwnd = 0; }
exit: LeaveCriticalSection(&s_csLookup); return hr; }
HRESULT CancelLookup(LPTSTR pszHostName, HWND hwndNotify) { ULONG i, j, cMove; LOOKUPINFO *pLI; HRESULT hr = E_INVALIDARG;
EnterCriticalSection(&s_csLookup);
for (i = 0, pLI = s_rgLookUp; i < s_cLookUp; i++, pLI++) { Assert(pLI->pszHostName); if (!lstrcmpi(pLI->pszHostName, pszHostName)) { for (j = 0; j < pLI->cHwnd; j++) { if (pLI->rgHwndNotify[j] == hwndNotify) { while (j + 1 < pLI->cHwnd) { pLI->rgHwndNotify[j] = pLI->rgHwndNotify[j+1]; j++; } pLI->cHwnd--; hr = S_OK; break; } } break; } }
LeaveCriticalSection(&s_csLookup);
return hr; }
|