Tidied up and made a public release. tclresolver-0-4-0
authorPat Thoyts <patthoyts@users.sourceforge.net>
Thu, 11 Nov 2004 23:47:11 +0000 (23:47 +0000)
committerPat Thoyts <patthoyts@users.sourceforge.net>
Thu, 11 Nov 2004 23:47:11 +0000 (23:47 +0000)
ChangeLog
Makefile
demo/demo.tcl
pkgIndex.tcl [new file with mode: 0644]
resolvchk.c [deleted file]
tclresolver2.c [deleted file]
tclresolver3.c [deleted file]
w32cat.c [deleted file]
win/tclresolver.c

index d8323649594b0a085cb6d235787fc6f5d14562c9..8f105bc53d144d0aba6d0000fd8d9224cd550f3a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2004-11-11  Pat Thoyts  <patthoyts@users.sourceforge.net>
+
+       ==== TAG tclresolver-0-4-0 ====
+       
+       * tclresolver3.c: Renamed to tclresolver. This is the thread
+       version.
+       * tclresolver2.c, resolvchk.c: Removed.
+
 2004-08-26  Pat Thoyts  <patthoyts@users.sourceforge.net>
 
        * all: Initial checkin
index 6df5a7dee0707da4227b1888dcc64e7eb97f1132..b49d9656af2804aab5d5d5772a26ffeb2d75b69c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,23 +8,13 @@ DEFS   =-DUSE_TCL_STUBS
 INC    =-Ic:\opt\tcl\include
 LIBS   =c:\opt\tcl\lib\tclstub84.lib ws2_32.lib
 
-all: resolver.exe resolvchk.exe tclresolver.dll tclresolver2.dll tclresolver3.dll
+all: resolver.exe tclresolver.dll
 
 resolver.exe: resolver.c
        $(CC) $(CFLAGS) -o $@ $**
 
-resolvchk.exe: resolvchk.c
-       $(CC) $(CFLAGS) -o $@ $**
-
 tclresolver.dll: tclresolver.obj
        $(LD) $(LDFLAGS) -out:$@ $(LIBS) $**
-
-tclresolver2.dll: tclresolver2.obj
-       $(LD) $(LDFLAGS) -out:$@ $(LIBS) $**
-
-tclresolver3.dll: tclresolver3.obj
-       $(LD) $(LDFLAGS) -out:$@ $(LIBS) $**
-
 .c.obj::
        $(CC) $(CFLAGS) $(DEFS) $(INC) -c @<<
 $<
@@ -32,18 +22,9 @@ $<
 
 clean:
        @if exist tclresolver.obj del tclresolver.obj
-       @if exist tclresolver2.obj del tclresolver2.obj
-       @if exist tclresolver3.obj del tclresolver3.obj
 
 realclean: clean
        @if exist tclresolver.dll del tclresolver.dll
        @if exist tclresolver.exp del tclresolver.exp
        @if exist tclresolver.lib del tclresolver.lib
-       @if exist tclresolver2.dll del tclresolver2.dll
-       @if exist tclresolver2.exp del tclresolver2.exp
-       @if exist tclresolver2.lib del tclresolver2.lib
-       @if exist tclresolver3.dll del tclresolver3.dll
-       @if exist tclresolver3.exp del tclresolver3.exp
-       @if exist tclresolver3.lib del tclresolver3.lib
        @if exist resolver.exe del resolver.exe
-       @if exist resolvchk.exe del resolvchk.exe
index 57b6093d8fc9b5e11e98cc74a68a7769d83940ef..74c4c08fff0708d335091e55c27255d31161ac8e 100644 (file)
@@ -1,5 +1,5 @@
-if {[file exists tclresolver3.dll]} {
-    load tclresolver3.dll Tclresolver
+if {[file exists tclresolver.dll]} {
+    load tclresolver.dll Tclresolver
 } else {
     package require Tclresolver
 }
diff --git a/pkgIndex.tcl b/pkgIndex.tcl
new file mode 100644 (file)
index 0000000..8ed4e52
--- /dev/null
@@ -0,0 +1,3 @@
+# pkgIndex.tcl - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
+#
+package ifneeded Tclresolver 0.4.0 [list load [file join $dir tclresolver.dll]]
diff --git a/resolvchk.c b/resolvchk.c
deleted file mode 100644 (file)
index ce8db7e..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <tchar.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define BUFSIZE 4096
-
-typedef struct {
-    HANDLE hReady;
-    HANDLE hDone;
-    HANDLE hIn;
-    HANDLE hOut;
-    LPBYTE pData;
-    BOOL   bRunning;
-} LookupInfo;
-
-static LPCTSTR LookupHostname(LookupInfo * pLookupInfo, LPCTSTR szHostname);
-static DWORD WINAPI Reader(LPVOID clientData);
-static BOOL CreateChildProcess(HANDLE hChildStdoutWr, HANDLE hChildStdinRd);
-static void ErrorExit(LPTSTR);
-static void Win32Error(FILE *fp, LPCTSTR szMessage, HRESULT hr);
-
-DWORD
-_tmain(int argc, LPCTSTR argv[]) 
-{
-    HANDLE hChildStdinWr, hChildStdinWrDup, hChildStdoutRd, hChildStdoutRdDup;
-    HANDLE hChildStdinRd, hChildStdoutWr;
-    LookupInfo lookupinfo;
-    HANDLE hReaderThread = INVALID_HANDLE_VALUE;
-    DWORD idReaderThread = 0;
-    SECURITY_ATTRIBUTES saAttr; 
-    BOOL fSuccess;
-    LPCTSTR szAddress;
-    int n;
-
-    if (argc < 2) {
-        ErrorExit(_T("usage: resolvchk hostname ?hostname ...?"));
-    }
-
-    // Set the bInheritHandle flag so pipe handles are inherited.
-    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
-    saAttr.bInheritHandle = TRUE;
-    saAttr.lpSecurityDescriptor = NULL;
-
-    // Create a pipe for the child process's STDOUT.
-    if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
-        ErrorExit("Stdout pipe creation failed\n");
-
-    // Create noninheritable read handle and close the inheritable read
-    // handle.
-    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
-                               GetCurrentProcess(), &hChildStdoutRdDup,
-                               0, FALSE,
-                               DUPLICATE_SAME_ACCESS);
-    if( !fSuccess )
-        ErrorExit("DuplicateHandle failed");
-    CloseHandle(hChildStdoutRd);
-
-    // Create a pipe for the child process's STDIN.
-    if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
-        ErrorExit("Stdin pipe creation failed\n");
-
-    // Duplicate the write handle to the pipe so it is not inherited.
-    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
-                               GetCurrentProcess(), &hChildStdinWrDup,
-                               0, FALSE,                  // not inherited
-                               DUPLICATE_SAME_ACCESS);
-    if (! fSuccess)
-        ErrorExit("DuplicateHandle failed");
-
-    CloseHandle(hChildStdinWr);
-
-    // Create an event for lookup synch.
-    lookupinfo.hReady = CreateEvent(NULL, FALSE, FALSE, NULL);
-    lookupinfo.hDone = CreateEvent(NULL, FALSE, FALSE, NULL);
-    lookupinfo.hIn = hChildStdoutRdDup;
-    lookupinfo.hOut = hChildStdinWrDup;
-    lookupinfo.bRunning = TRUE;
-    lookupinfo.pData = (LPBYTE)malloc(BUFSIZE);
-
-    // Create reader thread.
-    hReaderThread = CreateThread(NULL, 0, Reader, &lookupinfo,
-                                 0, &idReaderThread);
-
-    // Now create the child process.
-    fSuccess = CreateChildProcess(hChildStdoutWr, hChildStdinRd);
-    if (! fSuccess)
-        ErrorExit("Create process failed");
-
-    // Perform the address lookup.
-    for (n = 1; n < argc; n++) {
-        szAddress = LookupHostname(&lookupinfo, argv[n]);
-        _ftprintf(stdout, _T("'%s'\n"), szAddress);
-    }
-
-    lookupinfo.bRunning = FALSE;
-    free((LPBYTE)lookupinfo.pData);
-
-    // Close the pipe handle so the child process stops reading and exits.
-    if (! CloseHandle(hChildStdinWrDup))
-        ErrorExit("Close pipe failed");
-    if (!CloseHandle(hChildStdoutWr))
-        ErrorExit("CloseHandle failed");
-
-    return 0;
-}
-
-static LPCTSTR
-LookupHostname(LookupInfo *pLookupInfo, LPCTSTR szHostname)
-{
-    DWORD dwWrote;
-    BOOL br;
-    
-    ZeroMemory(pLookupInfo->pData, BUFSIZE);
-    lstrcpy((LPTSTR)pLookupInfo->pData, szHostname);
-    lstrcat((LPTSTR)pLookupInfo->pData, _T("\n"));
-    br = WriteFile(pLookupInfo->hOut, pLookupInfo->pData,
-                   lstrlen((LPTSTR)pLookupInfo->pData) * sizeof(TCHAR),
-                   &dwWrote, NULL);
-    if (br)
-        br = FlushFileBuffers(pLookupInfo->hOut);
-    if (br) {
-        ZeroMemory(pLookupInfo->pData, BUFSIZE);
-        SetEvent(pLookupInfo->hReady);
-        WaitForSingleObject(pLookupInfo->hDone, INFINITE);
-    }
-    if (!br) {
-        Win32Error(stderr, _T("lookup hostname"), GetLastError());
-    }
-    return (LPCTSTR)pLookupInfo->pData;
-}
-
-static DWORD WINAPI
-Reader(LPVOID clientData)
-{
-    LookupInfo *pLookupInfo = (LookupInfo *)clientData;
-    DWORD dwErr = 0, dwRead = 0;
-    BOOL br;
-
-    while (pLookupInfo->bRunning) {
-        dwErr = WaitForSingleObject(pLookupInfo->hReady, 500);
-        if (dwErr == WAIT_OBJECT_0) {
-            br = ReadFile(pLookupInfo->hIn, pLookupInfo->pData,
-                          BUFSIZE, &dwRead, NULL);
-
-            if (dwRead > 0) {
-                LPTSTR p = (LPTSTR)pLookupInfo->pData;
-                for (p = p + lstrlen(p) - 1;
-                     p > pLookupInfo->pData && _istspace(*p);
-                     p--)
-                    ;
-                *++p = 0;
-            }
-            SetEvent(pLookupInfo->hDone);
-        } else {
-            Win32Error(stderr, _T("reader wait"), dwErr);
-        }
-    }
-    return 0;
-}
-
-static BOOL
-CreateChildProcess(HANDLE hChildStdoutWr, HANDLE hChildStdinRd) 
-{
-    PROCESS_INFORMATION piProcInfo;
-    STARTUPINFO siStartInfo;
-    BOOL bFuncRetn = FALSE;
-
-    // Set up members of the PROCESS_INFORMATION structure.
-    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
-
-    // Set up members of the STARTUPINFO structure.
-    ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
-    siStartInfo.cb = sizeof(STARTUPINFO);
-    siStartInfo.hStdError = hChildStdoutWr;
-    siStartInfo.hStdOutput = hChildStdoutWr;
-    siStartInfo.hStdInput = hChildStdinRd;
-    siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
-    // Create the child process.
-    bFuncRetn = CreateProcess(NULL,
-                              "resolver",    // command line 
-                              NULL,          // process security attributes 
-                              NULL,          // primary thread security attributes 
-                              TRUE,          // handles are inherited 
-                              0,             // creation flags 
-                              NULL,          // use parent's environment 
-                              NULL,          // use parent's current directory 
-                              &siStartInfo,  // STARTUPINFO pointer 
-                              &piProcInfo);  // receives PROCESS_INFORMATION 
-   
-    if (bFuncRetn == 0) {
-        ErrorExit("CreateProcess failed");
-        return FALSE;
-    } else {
-        CloseHandle(piProcInfo.hProcess);
-        CloseHandle(piProcInfo.hThread);
-        return bFuncRetn;
-    }
-}
-static void
-ErrorExit (LPTSTR lpszMessage)
-{
-    _ftprintf(stderr, _T("%s\n"), lpszMessage);
-    ExitProcess(0);
-}
-
-static void
-Win32Error(FILE *fp, LPCTSTR szMessage, HRESULT hr)
-{
-    LPTSTR lpBuffer = NULL;
-    DWORD  dwLen = 0;
-    
-    dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                          | FORMAT_MESSAGE_FROM_SYSTEM,
-                          NULL, (DWORD)hr, LANG_NEUTRAL,
-                          (LPTSTR)&lpBuffer, 0, NULL);
-    if (dwLen < 1) {
-        dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                              | FORMAT_MESSAGE_FROM_STRING
-                              | FORMAT_MESSAGE_ARGUMENT_ARRAY,
-                              _T("code 0x%1!08X!%n"), 0, LANG_NEUTRAL,
-                              (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
-    }
-    _ftprintf(fp, _T("%s"), szMessage);
-    if (dwLen > 0) {
-        _ftprintf(fp, _T(": "));
-        _ftprintf(fp, lpBuffer);
-    }
-    LocalFree((HLOCAL)lpBuffer);
-}
diff --git a/tclresolver2.c b/tclresolver2.c
deleted file mode 100644 (file)
index 6684408..0000000
+++ /dev/null
@@ -1,319 +0,0 @@
-/* tclresolver.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
- *
- *
- *
- * $Id$
- */
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h> 
-#include <tchar.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include <tcl.h>
-
-#if _MSC_VER >= 1000
-#pragma comment(lib, "ws2_32")
-#endif
-
-#define BUFSIZE 4096
-#undef TCL_STORAGE_CLASS
-#define TCL_STORAGE_CLASS DLLEXPORT
-
-static const char ASSOC_KEY[] = "tclresolver_key";
-
-EXTERN int Tclresolver_Init(Tcl_Interp *interp);
-EXTERN int Tclresolver_Unload(Tcl_Interp *interp);
-EXTERN int TclGetHostByName(LPSOCKADDR_IN saddrPtr, 
-                            const char *hostname, int port);
-
-typedef struct {
-    HANDLE hReader;
-    DWORD  idReader;
-    HANDLE hReady;
-    HANDLE hDone;
-    LPBYTE pData;
-    BOOL   bRunning;
-    Tcl_ThreadId tclid;
-    Tcl_Command command;
-} LOOKUPINFO, *LPLOOKUPINFO;
-
-typedef struct {
-    Tcl_Event header;
-    LPLOOKUPINFO info;
-} RESOLVEREVENT, *LPRESOLVEREVENT;
-
-static Tcl_ObjCmdProc TclresolverObjCmd;
-static Tcl_ExitProc Terminate;
-static int Initialize(Tcl_Interp *interp, LPLOOKUPINFO pLookupInfo);
-static LPCTSTR LookupHostname(LPLOOKUPINFO pLookupInfo, LPCTSTR szHostname);
-static DWORD WINAPI Reader(LPVOID clientData);
-static void QueueEvent(LPLOOKUPINFO pLookupInfo);
-static int  ResolverEventProc(Tcl_Event *evPtr, int flags);
-static int GetAddress(char *query);
-static Tcl_Obj *Win32Error(const char * szPrefix, HRESULT hr);
-
-/* ---------------------------------------------------------------------- */
-
-int
-Tclresolver_Init(Tcl_Interp *interp)
-{
-    int initialized = 0;
-    LPLOOKUPINFO pLookupInfo = NULL;
-
-#ifdef USE_TCL_STUBS
-    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
-        return TCL_ERROR;
-    }
-#endif
-    
-    pLookupInfo = (LPLOOKUPINFO)Tcl_Alloc(sizeof(LOOKUPINFO));
-    if (pLookupInfo == NULL) {
-        Tcl_SetResult(interp, "out of memory", TCL_STATIC);
-        return TCL_ERROR;
-    }
-    ZeroMemory(pLookupInfo, sizeof(LOOKUPINFO));
-
-    if (Initialize(interp, pLookupInfo) != TCL_OK) {
-        Tcl_Free((char*)pLookupInfo);
-        return TCL_ERROR;
-    }
-    pLookupInfo->tclid = Tcl_GetCurrentThread();
-    pLookupInfo->command = Tcl_CreateObjCommand(interp, "resolve", 
-                                                TclresolverObjCmd,
-                                                (ClientData)pLookupInfo,
-                                                (Tcl_CmdDeleteProc *)NULL);
-    Tcl_CreateExitHandler(Terminate, (ClientData)pLookupInfo);
-    Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)pLookupInfo);
-    return Tcl_PkgProvide(interp, "Tclresolver", "1.2.0");
-}
-
-EXTERN int
-Tclresolver_SafeInit(Tcl_Interp *interp)
-{
-    return Tclresolver_Init(interp);
-}
-
-int 
-Tclresolver_Unload(Tcl_Interp *interp)
-{
-    LPLOOKUPINFO pLookupInfo = NULL;
-    pLookupInfo = (LPLOOKUPINFO)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
-    Tcl_DeleteCommandFromToken(interp, pLookupInfo->command);
-    Terminate((ClientData)pLookupInfo);
-    Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)NULL);    
-    return TCL_OK;
-}
-
-static int
-TclresolverObjCmd(ClientData clientData, Tcl_Interp *interp, 
-                  int objc, Tcl_Obj *CONST objv[])
-{
-    LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
-    Tcl_Obj *resObj = NULL;
-    if (objc != 2) {
-        Tcl_WrongNumArgs(interp, objc, objv, "hostname");
-        return TCL_ERROR;
-    }
-    resObj = Tcl_NewStringObj(LookupHostname(pLookupInfo,
-                                             Tcl_GetString(objv[1])), -1);
-    Tcl_SetObjResult(interp, resObj);
-    return TCL_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int
-Initialize(Tcl_Interp *interp, LPLOOKUPINFO pLookupInfo) 
-{
-    WSADATA wsd;
-    
-    OutputDebugString(_T("Initialize\n"));
-    
-    /* Initialize windows sockets. */
-    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
-       Tcl_Obj *errObj = Win32Error("WSAStartup error", GetLastError());
-        Tcl_SetObjResult(interp, errObj);
-        return TCL_ERROR;
-    }
-    
-    if (LOBYTE(wsd.wVersion) != 2 ||
-        HIBYTE(wsd.wVersion) != 2) {
-        Tcl_SetResult(interp,
-           "error: failed to load a compatible winsock version", TCL_STATIC);
-       WSACleanup();
-        return TCL_ERROR;
-    }
-
-    /* Create synchronization events */
-    pLookupInfo->hReady = CreateEvent(NULL, FALSE, FALSE, NULL);
-    pLookupInfo->hDone  = CreateEvent(NULL, FALSE, FALSE, NULL);
-    pLookupInfo->bRunning = TRUE;
-    pLookupInfo->pData = (LPBYTE)Tcl_Alloc(BUFSIZE);
-
-    /* Create the reader thread */
-    pLookupInfo->hReader = CreateThread(NULL, 0, Reader, pLookupInfo,
-                                        0, &pLookupInfo->idReader);
-
-    return TCL_OK;
-}
-
-static void
-Terminate(ClientData clientData)
-{
-    LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
-    OutputDebugString(_T("Terminate\n"));
-    pLookupInfo->bRunning = FALSE;
-    Tcl_DeleteExitHandler(Terminate, clientData);
-    WaitForSingleObject(pLookupInfo->hReader, 400);
-    CloseHandle(pLookupInfo->hReader);
-    CloseHandle(pLookupInfo->hReady);
-    CloseHandle(pLookupInfo->hDone);
-    Tcl_Free(pLookupInfo->pData);
-    Tcl_Free((LPBYTE)pLookupInfo);
-    WSACleanup();
-}
-
-static LPCTSTR
-LookupHostname(LPLOOKUPINFO pLookupInfo, LPCTSTR szHostname)
-{
-    DWORD dwWait;
-    
-    /* copy the hostname into out buffer */
-    ZeroMemory(pLookupInfo->pData, BUFSIZE);
-    lstrcpy((LPTSTR)pLookupInfo->pData, szHostname);
-    
-    /* notify the reader thread that it should begin reading */
-    SetEvent(pLookupInfo->hReady);
-
-    /* Run a tcl event loop while we wait for the answer */
-    while (1) {
-        Tcl_DoOneEvent(0); /* when tk loaded */
-        //Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
-        OutputDebugString("done one event\n");
-        dwWait = WaitForSingleObject(pLookupInfo->hDone, 0);
-        if (dwWait == WAIT_OBJECT_0)
-            break;
-    }
-
-    return (LPCTSTR)pLookupInfo->pData;
-}
-
-static DWORD WINAPI
-Reader(LPVOID clientData)
-{
-    LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
-    DWORD dwErr = 0, dwRead = 0;
-
-    while (pLookupInfo->bRunning) {
-        dwErr = WaitForSingleObject(pLookupInfo->hReady, 500);
-        if (dwErr == WAIT_OBJECT_0) {
-           GetAddress((char *)pLookupInfo->pData);
-            QueueEvent(pLookupInfo);
-        }
-    }
-    return 0;
-}
-
-static void
-QueueEvent(LPLOOKUPINFO pLookupInfo)
-{
-    LPRESOLVEREVENT evPtr;
-    OutputDebugString(_T("QueueEvent\n"));
-    evPtr = (LPRESOLVEREVENT)Tcl_Alloc(sizeof(RESOLVEREVENT));
-    evPtr->header.proc = ResolverEventProc;
-    evPtr->header.nextPtr = NULL;
-    evPtr->info = pLookupInfo;
-    Tcl_ThreadQueueEvent(pLookupInfo->tclid, 
-                         (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
-}
-
-static int
-ResolverEventProc(Tcl_Event *evPtr, int flags)
-{
-    LPRESOLVEREVENT revPtr = (LPRESOLVEREVENT)evPtr;
-    OutputDebugString(_T("ResolverEventProc\n"));
-    SetEvent(revPtr->info->hDone);
-    return 1;
-}
-
-static Tcl_Obj *
-Win32Error(const char * szPrefix, HRESULT hr)
-{
-    Tcl_Obj *msgObj = NULL;
-    char * lpBuffer = NULL;
-    DWORD  dwLen = 0;
-    
-    dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                          | FORMAT_MESSAGE_FROM_SYSTEM,
-                          NULL, (DWORD)hr, LANG_NEUTRAL,
-                          (LPTSTR)&lpBuffer, 0, NULL);
-    if (dwLen < 1) {
-        dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                              | FORMAT_MESSAGE_FROM_STRING
-                              | FORMAT_MESSAGE_ARGUMENT_ARRAY,
-                              "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
-                              (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
-    }
-
-    msgObj = Tcl_NewStringObj(szPrefix, -1);
-    if (dwLen > 0) {
-       char *p = lpBuffer + dwLen - 1;        /* remove cr-lf at end */
-       for ( ; p && *p && isspace(*p); p--)
-           ;
-       *++p = 0;
-       Tcl_AppendToObj(msgObj, ": ", 2);
-       Tcl_AppendToObj(msgObj, lpBuffer, -1);
-    }
-    LocalFree((HLOCAL)lpBuffer);
-    return msgObj;
-}
-
-static int
-GetAddress(char *query)
-{
-    struct addrinfo hints = {0};
-    struct addrinfo *res = NULL;
-    char *hostname, *p, *q;
-    int r = 0, nc = 0;
-    
-    /* trim whitespace */
-    for (p = query; *p && isspace(*p); p++)
-       ;
-    for (q = p + strlen(p) - 1; q > p && *q && isspace(*q); q--)
-       ;
-    *++q = 0;
-    hostname = p;
-
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_family = PF_UNSPEC;
-    hints.ai_flags = AI_CANONNAME;
-    hints.ai_socktype = SOCK_STREAM;
-    r = getaddrinfo(hostname, "", &hints, &res);
-    *query = 0;
-
-    if (r != 0) {
-       Tcl_Obj *o = Win32Error("error", WSAGetLastError());
-       strcpy(query, Tcl_GetString(o));
-       Tcl_DecrRefCount(o);
-    } else {
-       struct addrinfo *resPtr = res;
-       for (resPtr = res; resPtr != NULL; resPtr = resPtr->ai_next) {
-           char name[NI_MAXHOST];
-
-           getnameinfo(resPtr->ai_addr, resPtr->ai_addrlen, 
-                       name, NI_MAXHOST,
-                       NULL, 0,
-                       NI_NUMERICHOST | NI_NUMERICSERV);
-
-           if (resPtr != res)
-               strcat(query, " ");
-           strcat(query, name);
-       }
-       freeaddrinfo(res);
-    }
-    return r;
-}
-    
-
diff --git a/tclresolver3.c b/tclresolver3.c
deleted file mode 100644 (file)
index d465b5b..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-/* tclresolver.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
- *
- * Non-blocking name resolution.
- *
- * $Id$
- */
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h> 
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include <tcl.h>
-
-#if _MSC_VER >= 1000
-#pragma comment(lib, "ws2_32")
-#pragma comment(lib, "user32")
-#endif
-
-#define BUFSIZE 4096
-#define XWM_RESOLVE WM_APP + 1
-
-#undef TCL_STORAGE_CLASS
-#define TCL_STORAGE_CLASS DLLEXPORT
-
-static const char ASSOC_KEY[] = "tclresolver_key";
-
-EXTERN int Tclresolver_Init(Tcl_Interp *interp);
-EXTERN int Tclresolver_Unload(Tcl_Interp *interp);
-EXTERN int TclGetHostByName(LPSOCKADDR_IN saddrPtr, 
-                            const char *hostname, int port);
-
-typedef struct {
-    HANDLE hReader;
-    DWORD  idReader;
-    Tcl_ThreadId tclid;
-    Tcl_Command command;
-} PKGINFO, *LPPKGINFO;
-
-typedef struct {
-    HANDLE lock;
-    LONG   cookie;
-    char   data[BUFSIZE];
-} QUERYINFO, *LPQUERYINFO;
-
-typedef struct {
-    Tcl_Event header;
-    LPQUERYINFO query;
-} RESOLVEREVENT, *LPRESOLVEREVENT;
-
-static Tcl_ObjCmdProc TclresolverObjCmd;
-static Tcl_ExitProc Terminate;
-static int Initialize(Tcl_Interp *interp, LPPKGINFO pkgPtr);
-static Tcl_Obj *LookupHostname(LPPKGINFO pkgPtr, const char *hostname);
-static DWORD WINAPI Reader(LPVOID clientData);
-static void QueueEvent(Tcl_ThreadId id, LPQUERYINFO pQuery);
-static int  ResolverEventProc(Tcl_Event *evPtr, int flags);
-static int GetAddress(char *query);
-static Tcl_Obj *Win32Error(const char * szPrefix, HRESULT hr);
-
-/* ---------------------------------------------------------------------- */
-
-int
-Tclresolver_Init(Tcl_Interp *interp)
-{
-    int initialized = 0;
-    LPPKGINFO pkgPtr = NULL;
-
-#ifdef USE_TCL_STUBS
-    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
-        return TCL_ERROR;
-    }
-#endif
-    
-    pkgPtr = (LPPKGINFO)Tcl_Alloc(sizeof(PKGINFO));
-    if (pkgPtr == NULL) {
-        Tcl_SetResult(interp, "out of memory", TCL_STATIC);
-        return TCL_ERROR;
-    }
-    ZeroMemory(pkgPtr, sizeof(PKGINFO));
-
-    if (Initialize(interp, pkgPtr) != TCL_OK) {
-        Tcl_Free((char*)pkgPtr);
-        return TCL_ERROR;
-    }
-    pkgPtr->tclid = Tcl_GetCurrentThread();
-    pkgPtr->command = Tcl_CreateObjCommand(interp, "resolve", 
-                                                TclresolverObjCmd,
-                                                (ClientData)pkgPtr,
-                                                (Tcl_CmdDeleteProc *)NULL);
-    Tcl_CreateExitHandler(Terminate, (ClientData)pkgPtr);
-    Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)pkgPtr);
-    return Tcl_PkgProvide(interp, "Tclresolver", "1.3.0");
-}
-
-EXTERN int
-Tclresolver_SafeInit(Tcl_Interp *interp)
-{
-    return Tclresolver_Init(interp);
-}
-
-int 
-Tclresolver_Unload(Tcl_Interp *interp)
-{
-    LPPKGINFO pkgPtr = NULL;
-    pkgPtr = (LPPKGINFO)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
-    Tcl_DeleteCommandFromToken(interp, pkgPtr->command);
-    Terminate((ClientData)pkgPtr);
-    Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)NULL);    
-    return TCL_OK;
-}
-
-static int
-TclresolverObjCmd(ClientData clientData, Tcl_Interp *interp, 
-                  int objc, Tcl_Obj *CONST objv[])
-{
-    LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
-    Tcl_Obj *resObj = NULL;
-    if (objc != 2) {
-        Tcl_WrongNumArgs(interp, objc, objv, "hostname");
-        return TCL_ERROR;
-    }
-    resObj = LookupHostname(pkgPtr, Tcl_GetString(objv[1]));
-    Tcl_SetObjResult(interp, resObj);
-    return TCL_OK;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int
-Initialize(Tcl_Interp *interp, LPPKGINFO pkgPtr) 
-{
-    WSADATA wsd;
-    
-    OutputDebugStringA("Initialize\n");
-    
-    /* Initialize windows sockets. */
-    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
-       Tcl_Obj *errObj = Win32Error("WSAStartup error", GetLastError());
-        Tcl_SetObjResult(interp, errObj);
-        return TCL_ERROR;
-    }
-    
-    if (LOBYTE(wsd.wVersion) != 2 ||
-        HIBYTE(wsd.wVersion) != 2) {
-        Tcl_SetResult(interp,
-           "error: failed to load a compatible winsock version", TCL_STATIC);
-       WSACleanup();
-        return TCL_ERROR;
-    }
-
-    /* Create the reader thread */
-    pkgPtr->hReader = CreateThread(NULL, 0, Reader, pkgPtr,
-                                        0, &pkgPtr->idReader);
-
-    return TCL_OK;
-}
-
-static void
-Terminate(ClientData clientData)
-{
-    LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
-    OutputDebugStringA("Terminate\n");
-    PostThreadMessage(pkgPtr->idReader, WM_QUIT, 0, 0L);
-    Tcl_DeleteExitHandler(Terminate, clientData);
-    WaitForSingleObject(pkgPtr->hReader, 400);
-    CloseHandle(pkgPtr->hReader);
-    Tcl_Free((LPBYTE)pkgPtr);
-    WSACleanup();
-}
-
-static Tcl_Obj *
-LookupHostname(LPPKGINFO pkgPtr, const char * hostname)
-{
-    Tcl_Obj *resObj = NULL;
-    DWORD dwWait;
-    LPQUERYINFO queryPtr;
-    static LONG cookie;
-    char sz[128];
-
-    /* copy the hostname into out buffer */
-    queryPtr = (LPQUERYINFO)Tcl_Alloc(sizeof(QUERYINFO));
-    memset(queryPtr, 0, sizeof(QUERYINFO));
-    queryPtr->lock = CreateEvent(NULL, FALSE, FALSE, NULL);
-    queryPtr->cookie = InterlockedIncrement(&cookie);
-    strcpy(queryPtr->data, hostname);
-
-    sprintf(sz, "query %d begin\n", queryPtr->cookie);
-    OutputDebugString(sz);
-    
-    /* notify the reader thread that it should begin reading */
-    PostThreadMessage(pkgPtr->idReader, XWM_RESOLVE, 0, (LPARAM)queryPtr);
-
-    /* Run a tcl event loop while we wait for the answer */
-    while (1) {
-        Tcl_DoOneEvent(0); /* when tk loaded */
-        //Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
-        dwWait = WaitForSingleObject(queryPtr->lock, 0);
-        if (dwWait == WAIT_OBJECT_0) {
-           sprintf(sz, "query %d complete\n", queryPtr->cookie);
-           OutputDebugString(sz);
-            break;
-       }
-    }
-
-    resObj = Tcl_NewStringObj(queryPtr->data, -1);
-    CloseHandle(queryPtr->lock);
-    Tcl_Free((char *)queryPtr);
-    return resObj;
-}
-
-static DWORD WINAPI
-Reader(LPVOID clientData)
-{
-    LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
-    LPQUERYINFO queryPtr = NULL;
-    MSG msg;
-    DWORD dwErr = 0, dwRead = 0;
-    
-    while(GetMessage(&msg, 0, 0, 0)) {
-       if (msg.hwnd == NULL) {
-           switch (msg.message) {
-               case XWM_RESOLVE:
-                   queryPtr = (LPQUERYINFO)msg.lParam;
-                   GetAddress(queryPtr->data);
-                   QueueEvent(pkgPtr->tclid, queryPtr);
-                   break;
-           }
-       }
-       DispatchMessage(&msg);
-    }
-
-    OutputDebugStringA("Reader exiting.\n");
-    return 0;
-}
-
-static void
-QueueEvent(Tcl_ThreadId id, LPQUERYINFO queryPtr)
-{
-    LPRESOLVEREVENT evPtr;
-    OutputDebugStringA("QueueEvent\n");
-    evPtr = (LPRESOLVEREVENT)Tcl_Alloc(sizeof(RESOLVEREVENT));
-    evPtr->header.proc = ResolverEventProc;
-    evPtr->header.nextPtr = NULL;
-    evPtr->query = queryPtr;
-    Tcl_ThreadQueueEvent(id, (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
-}
-
-static int
-ResolverEventProc(Tcl_Event *evPtr, int flags)
-{
-    LPRESOLVEREVENT revPtr = (LPRESOLVEREVENT)evPtr;
-    OutputDebugStringA("ResolverEventProc\n");
-    SetEvent(revPtr->query->lock);
-    return 1;
-}
-
-static Tcl_Obj *
-Win32Error(const char * szPrefix, HRESULT hr)
-{
-    Tcl_Obj *msgObj = NULL;
-    char * lpBuffer = NULL;
-    DWORD  dwLen = 0;
-    
-    dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                          | FORMAT_MESSAGE_FROM_SYSTEM,
-                          NULL, (DWORD)hr, LANG_NEUTRAL,
-                          (LPTSTR)&lpBuffer, 0, NULL);
-    if (dwLen < 1) {
-        dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                              | FORMAT_MESSAGE_FROM_STRING
-                              | FORMAT_MESSAGE_ARGUMENT_ARRAY,
-                              "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
-                              (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
-    }
-
-    msgObj = Tcl_NewStringObj(szPrefix, -1);
-    if (dwLen > 0) {
-       char *p = lpBuffer + dwLen - 1;        /* remove cr-lf at end */
-       for ( ; p && *p && isspace(*p); p--)
-           ;
-       *++p = 0;
-       Tcl_AppendToObj(msgObj, ": ", 2);
-       Tcl_AppendToObj(msgObj, lpBuffer, -1);
-    }
-    LocalFree((HLOCAL)lpBuffer);
-    return msgObj;
-}
-
-static int
-GetAddress(char *query)
-{
-    struct addrinfo hints = {0};
-    struct addrinfo *res = NULL;
-    char *hostname, *p, *q;
-    int r = 0, nc = 0;
-    
-    /* trim whitespace */
-    for (p = query; *p && isspace(*p); p++)
-       ;
-    for (q = p + strlen(p) - 1; q > p && *q && isspace(*q); q--)
-       ;
-    *++q = 0;
-    hostname = p;
-
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_family = PF_INET; /* use PF_UNSPEC if we want IPv6 too */
-    hints.ai_flags = AI_CANONNAME;
-    hints.ai_socktype = SOCK_STREAM;
-    r = getaddrinfo(hostname, "", &hints, &res);
-    *query = 0;
-
-    if (r != 0) {
-       Tcl_Obj *o = Win32Error("error", WSAGetLastError());
-       strcpy(query, Tcl_GetString(o));
-       Tcl_DecrRefCount(o);
-    } else {
-       struct addrinfo *resPtr = res;
-       for (resPtr = res; resPtr != NULL; resPtr = resPtr->ai_next) {
-           char name[NI_MAXHOST];
-
-           getnameinfo(resPtr->ai_addr, resPtr->ai_addrlen, 
-                       name, NI_MAXHOST,
-                       NULL, 0,
-                       NI_NUMERICHOST | NI_NUMERICSERV);
-
-           if (resPtr != res)
-               strcat(query, " ");
-           strcat(query, name);
-       }
-       freeaddrinfo(res);
-    }
-    return r;
-}
-    
-
diff --git a/w32cat.c b/w32cat.c
deleted file mode 100644 (file)
index 560d15a..0000000
--- a/w32cat.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* w32cat.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
- *
- * This illustrates a line-oriented cat program. Each line read from the
- * console is echoed to the output.
- *
- * NB: only reads from the CONSOLE though. Not piped input.
- *
- * $Id$
- */
-
-#if defined(_UNICODE) && !defined(UNICODE)
-#define UNICODE
-#endif
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <tchar.h>
-
-void Win32Error(HANDLE hFile, LPCTSTR sz, HRESULT hr);
-
-int
-_tmain(int argc, LPCTSTR argv[])
-{
-    HANDLE hStdin, hStdout, hStderr;
-    DWORD dwMode;
-
-    if ((hStderr = GetStdHandle(STD_ERROR_HANDLE)) == INVALID_HANDLE_VALUE) {
-        return -2;
-    }
-
-    if ((hStdout = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        Win32Error(hStderr, _T("get stdout handle"), GetLastError());
-        return -1;
-    }
-
-    if ((hStdin = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
-        Win32Error(hStderr, _T("get stdin handle"), GetLastError());
-        return -1;
-    }
-
-    /* 
-     * By default the console input is processed line oriented so we
-     * don't need to do anything special.
-     */
-
-    GetConsoleMode(hStdin, &dwMode);
-    dwMode &= ~ENABLE_LINE_INPUT;
-    SetConsoleMode(hStdin, dwMode);
-    GetConsoleMode(hStdout, &dwMode);
-    dwMode &= ~ENABLE_LINE_INPUT;
-    SetConsoleMode(hStdout, dwMode);
-
-    while (1) {
-        DWORD cbRead = 0;
-        TCHAR buffer[1024];
-
-        if (! ReadFile(hStdin, buffer, 1023, &cbRead, NULL))
-            break;
-        if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
-                          _T("quit"), 4, buffer, 4) == CSTR_EQUAL)
-            break;
-        
-        WriteFile(hStdout, buffer, cbRead, NULL, NULL);
-    }
-
-    return 0;
-}
-
-void
-Win32Error(HANDLE hFile, LPCTSTR sz, HRESULT hr)
-{
-    LPTSTR lpBuffer = NULL;
-    DWORD dwLen = 0;
-
-    dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                          | FORMAT_MESSAGE_FROM_SYSTEM,
-                          NULL, (DWORD)hr, LANG_NEUTRAL,
-                          (LPTSTR)&lpBuffer, 0, NULL);
-    if (dwLen < 1) {
-        HRESULT ahr[1] = {hr};
-        dwLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER 
-                              | FORMAT_MESSAGE_FROM_STRING
-                              | FORMAT_MESSAGE_ARGUMENT_ARRAY,
-                              _T("code: 0x%1!08X!%n"), 0, LANG_NEUTRAL,
-                              (LPTSTR)&lpBuffer, 0, (va_list *)ahr);
-    }
-    WriteConsole(hFile, sz, lstrlen(sz), NULL, NULL);
-    if (dwLen > 0) {
-        WriteConsole(hFile, _T(": "), 3, NULL, NULL);
-        WriteConsole(hFile, lpBuffer, dwLen, NULL, NULL);
-    }
-    LocalFree((HLOCAL)lpBuffer);
-}
index bcd143ffb2b62b6a22a171cdf354929ed3da0e10..3b7dc6339d1e87f0ce3fd0fac66108247b00487f 100644 (file)
@@ -1,18 +1,25 @@
 /* tclresolver.c - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
  *
- *
+ * Non-blocking name resolution.
  *
  * $Id$
  */
 
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h> 
-#include <tchar.h>
 #include <winsock2.h>
+#include <ws2tcpip.h>
 
 #include <tcl.h>
 
+#if _MSC_VER >= 1000
+#pragma comment(lib, "ws2_32")
+#pragma comment(lib, "user32")
+#endif
+
 #define BUFSIZE 4096
+#define XWM_RESOLVE WM_APP + 1
+
 #undef TCL_STORAGE_CLASS
 #define TCL_STORAGE_CLASS DLLEXPORT
 
@@ -26,32 +33,30 @@ EXTERN int TclGetHostByName(LPSOCKADDR_IN saddrPtr,
 typedef struct {
     HANDLE hReader;
     DWORD  idReader;
-    HANDLE hReady;
-    HANDLE hDone;
-    HANDLE hIn;
-    HANDLE hOut;
-    LPBYTE pData;
-    BOOL   bRunning;
     Tcl_ThreadId tclid;
     Tcl_Command command;
-} LOOKUPINFO, *LPLOOKUPINFO;
+} PKGINFO, *LPPKGINFO;
+
+typedef struct {
+    HANDLE lock;
+    LONG   cookie;
+    char   data[BUFSIZE];
+} QUERYINFO, *LPQUERYINFO;
 
 typedef struct {
     Tcl_Event header;
-    LPLOOKUPINFO info;
+    LPQUERYINFO query;
 } RESOLVEREVENT, *LPRESOLVEREVENT;
 
-//static int TclResolverObjCmd(ClientData clientData, Tcl_Interp *interp,
-//                             int objc, Tcl_Obj *CONST objv[]);
 static Tcl_ObjCmdProc TclresolverObjCmd;
 static Tcl_ExitProc Terminate;
-static int Initialize(Tcl_Interp *interp, LPLOOKUPINFO pLookupInfo);
-static BOOL CreateChildProcess(HANDLE hChildStdoutWr, HANDLE hChildStdinRd);
-static LPCTSTR LookupHostname(LPLOOKUPINFO pLookupInfo, LPCTSTR szHostname);
+static int Initialize(Tcl_Interp *interp, LPPKGINFO pkgPtr);
+static Tcl_Obj *LookupHostname(LPPKGINFO pkgPtr, const char *hostname);
 static DWORD WINAPI Reader(LPVOID clientData);
-static void QueueEvent(LPLOOKUPINFO pLookupInfo);
+static void QueueEvent(Tcl_ThreadId id, LPQUERYINFO pQuery);
 static int  ResolverEventProc(Tcl_Event *evPtr, int flags);
-
+static int GetAddress(char *query);
+static Tcl_Obj *Win32Error(const char * szPrefix, HRESULT hr);
 
 /* ---------------------------------------------------------------------- */
 
@@ -59,7 +64,7 @@ int
 Tclresolver_Init(Tcl_Interp *interp)
 {
     int initialized = 0;
-    LPLOOKUPINFO pLookupInfo = NULL;
+    LPPKGINFO pkgPtr = NULL;
 
 #ifdef USE_TCL_STUBS
     if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
@@ -67,26 +72,25 @@ Tclresolver_Init(Tcl_Interp *interp)
     }
 #endif
     
-    pLookupInfo = (LPLOOKUPINFO)Tcl_Alloc(sizeof(LOOKUPINFO));
-    if (pLookupInfo == NULL) {
+    pkgPtr = (LPPKGINFO)Tcl_Alloc(sizeof(PKGINFO));
+    if (pkgPtr == NULL) {
         Tcl_SetResult(interp, "out of memory", TCL_STATIC);
         return TCL_ERROR;
     }
-    ZeroMemory(pLookupInfo, sizeof(LOOKUPINFO));
+    ZeroMemory(pkgPtr, sizeof(PKGINFO));
 
-    if (Initialize(interp, pLookupInfo) != TCL_OK) {
-        Tcl_Free((char*)pLookupInfo);
-        //Tcl_SetResult(interp, "failed to initialize package", TCL_STATIC);
+    if (Initialize(interp, pkgPtr) != TCL_OK) {
+        Tcl_Free((char*)pkgPtr);
         return TCL_ERROR;
     }
-    pLookupInfo->tclid = Tcl_GetCurrentThread();
-    pLookupInfo->command = Tcl_CreateObjCommand(interp, "resolve", 
+    pkgPtr->tclid = Tcl_GetCurrentThread();
+    pkgPtr->command = Tcl_CreateObjCommand(interp, "resolve", 
                                                 TclresolverObjCmd,
-                                                (ClientData)pLookupInfo,
+                                                (ClientData)pkgPtr,
                                                 (Tcl_CmdDeleteProc *)NULL);
-    Tcl_CreateExitHandler(Terminate, (ClientData)pLookupInfo);
-    Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)pLookupInfo);
-    return Tcl_PkgProvide(interp, "Tclresolver", "1.0.0");
+    Tcl_CreateExitHandler(Terminate, (ClientData)pkgPtr);
+    Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)pkgPtr);
+    return Tcl_PkgProvide(interp, "Tclresolver", "0.4.0");
 }
 
 EXTERN int
@@ -98,10 +102,10 @@ Tclresolver_SafeInit(Tcl_Interp *interp)
 int 
 Tclresolver_Unload(Tcl_Interp *interp)
 {
-    LPLOOKUPINFO pLookupInfo = NULL;
-    pLookupInfo = (LPLOOKUPINFO)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
-    Tcl_DeleteCommandFromToken(interp, pLookupInfo->command);
-    Terminate((ClientData)pLookupInfo);
+    LPPKGINFO pkgPtr = NULL;
+    pkgPtr = (LPPKGINFO)Tcl_GetAssocData(interp, ASSOC_KEY, NULL);
+    Tcl_DeleteCommandFromToken(interp, pkgPtr->command);
+    Terminate((ClientData)pkgPtr);
     Tcl_SetAssocData(interp, ASSOC_KEY, NULL, (ClientData)NULL);    
     return TCL_OK;
 }
@@ -110,14 +114,13 @@ static int
 TclresolverObjCmd(ClientData clientData, Tcl_Interp *interp, 
                   int objc, Tcl_Obj *CONST objv[])
 {
-    LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
+    LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
     Tcl_Obj *resObj = NULL;
     if (objc != 2) {
         Tcl_WrongNumArgs(interp, objc, objv, "hostname");
         return TCL_ERROR;
     }
-    resObj = Tcl_NewStringObj(LookupHostname(pLookupInfo,
-                                             Tcl_GetString(objv[1])), -1);
+    resObj = LookupHostname(pkgPtr, Tcl_GetString(objv[1]));
     Tcl_SetObjResult(interp, resObj);
     return TCL_OK;
 }
@@ -125,251 +128,210 @@ TclresolverObjCmd(ClientData clientData, Tcl_Interp *interp,
 /* ---------------------------------------------------------------------- */
 
 static int
-Initialize(Tcl_Interp *interp, LPLOOKUPINFO pLookupInfo) 
-{ 
-    SECURITY_ATTRIBUTES saAttr;
-    BOOL fSuccess;
-    HANDLE hChildStdinRd, hChildStdinWr, hChildStdoutRd, hChildStdoutWr;
-    HANDLE hChildStdoutRdDup, hChildStdinWrDup;
-
-    // Set the bInheritHandle flag so pipe handles are inherited.
-    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
-    saAttr.bInheritHandle = TRUE;
-    saAttr.lpSecurityDescriptor = NULL;
-    // Create a pipe for the child process's STDOUT.
-    if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {
-        Tcl_SetResult(interp, "Stdout pipe creation failed", TCL_STATIC); 
-        return TCL_ERROR;
-    }
-    // Create noninheritable read handle and close the inheritable read 
-    // handle.
-    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
-                               GetCurrentProcess(), &hChildStdoutRdDup , 0,
-                               FALSE,
-                               DUPLICATE_SAME_ACCESS);
-    if( !fSuccess ) {
-        Tcl_SetResult(interp,  "DuplicateHandle failed", TCL_STATIC);
-        return TCL_ERROR;
-    }
-    CloseHandle(hChildStdoutRd);
-
-    // Create a pipe for the child process's STDIN.
-    if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
-        Tcl_SetResult(interp, "Stdin pipe creation failed", TCL_STATIC);
+Initialize(Tcl_Interp *interp, LPPKGINFO pkgPtr) 
+{
+    WSADATA wsd;
+    
+    OutputDebugStringA("Initialize\n");
+    
+    /* Initialize windows sockets. */
+    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
+       Tcl_Obj *errObj = Win32Error("WSAStartup error", GetLastError());
+        Tcl_SetObjResult(interp, errObj);
         return TCL_ERROR;
     }
-    // Duplicate the write handle to the pipe so it is not inherited.
-    fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr, 
-                               GetCurrentProcess(), &hChildStdinWrDup, 0, 
-                               FALSE,                  // not inherited 
-                               DUPLICATE_SAME_ACCESS); 
-    if (! fSuccess) {
-        Tcl_SetResult(interp, "DuplicateHandle failed", TCL_STATIC);
+    
+    if (LOBYTE(wsd.wVersion) != 2 ||
+        HIBYTE(wsd.wVersion) != 2) {
+        Tcl_SetResult(interp,
+           "error: failed to load a compatible winsock version", TCL_STATIC);
+       WSACleanup();
         return TCL_ERROR;
     }
-    CloseHandle(hChildStdinWr); 
-
-    /* Create synchronization events */
-    pLookupInfo->hReady = CreateEvent(NULL, FALSE, FALSE, NULL);
-    pLookupInfo->hDone  = CreateEvent(NULL, FALSE, FALSE, NULL);
-    pLookupInfo->hIn = hChildStdoutRdDup;
-    pLookupInfo->hOut = hChildStdinWrDup;
-    pLookupInfo->bRunning = TRUE;
-    pLookupInfo->pData = (LPBYTE)Tcl_Alloc(BUFSIZE);
 
     /* Create the reader thread */
-    pLookupInfo->hReader = CreateThread(NULL, 0, Reader, pLookupInfo,
-                                        0, &pLookupInfo->idReader);
+    pkgPtr->hReader = CreateThread(NULL, 0, Reader, pkgPtr,
+                                        0, &pkgPtr->idReader);
 
-    /* Now create the child process. */
-    fSuccess = CreateChildProcess(hChildStdoutWr, hChildStdinRd);
-    if (! fSuccess) {
-        Tcl_SetResult(interp, "Create process failed", TCL_STATIC);
-        return TCL_ERROR;
-    }
-    
     return TCL_OK;
 }
 
 static void
 Terminate(ClientData clientData)
 {
-    LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
-    OutputDebugString("Pkgdeleteproc\n");
-    pLookupInfo->bRunning = FALSE;
-    WaitForSingleObject(pLookupInfo->hReader, 400);
-    CloseHandle(pLookupInfo->hReader);
-    CloseHandle(pLookupInfo->hReady);
-    CloseHandle(pLookupInfo->hDone);
-    CloseHandle(pLookupInfo->hIn);
-    CloseHandle(pLookupInfo->hOut);
-    Tcl_Free(pLookupInfo->pData);
-    Tcl_Free((LPBYTE)pLookupInfo);
+    LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
+    OutputDebugStringA("Terminate\n");
+    PostThreadMessage(pkgPtr->idReader, WM_QUIT, 0, 0L);
+    Tcl_DeleteExitHandler(Terminate, clientData);
+    WaitForSingleObject(pkgPtr->hReader, 400);
+    CloseHandle(pkgPtr->hReader);
+    Tcl_Free((LPBYTE)pkgPtr);
+    WSACleanup();
 }
 
-static LPCTSTR
-LookupHostname(LPLOOKUPINFO pLookupInfo, LPCTSTR szHostname)
+static Tcl_Obj *
+LookupHostname(LPPKGINFO pkgPtr, const char * hostname)
 {
-    DWORD dwWrote, dwWait;
-    BOOL br;
+    Tcl_Obj *resObj = NULL;
+    DWORD dwWait;
+    LPQUERYINFO queryPtr;
+    static LONG cookie;
+    char sz[128];
+
+    /* copy the hostname into out buffer */
+    queryPtr = (LPQUERYINFO)Tcl_Alloc(sizeof(QUERYINFO));
+    memset(queryPtr, 0, sizeof(QUERYINFO));
+    queryPtr->lock = CreateEvent(NULL, FALSE, FALSE, NULL);
+    queryPtr->cookie = InterlockedIncrement(&cookie);
+    strcpy(queryPtr->data, hostname);
+
+    sprintf(sz, "query %d begin\n", queryPtr->cookie);
+    OutputDebugString(sz);
     
-    ZeroMemory(pLookupInfo->pData, BUFSIZE);
-    lstrcpy((LPTSTR)pLookupInfo->pData, szHostname);
-    lstrcat((LPTSTR)pLookupInfo->pData, _T("\n"));
-    br = WriteFile(pLookupInfo->hOut, pLookupInfo->pData,
-                   lstrlen((LPTSTR)pLookupInfo->pData) * sizeof(TCHAR),
-                   &dwWrote, NULL);
-    if (br)
-        br = FlushFileBuffers(pLookupInfo->hOut);
-    if (br) {
-        /* clear out the buffer ready for reading */
-        ZeroMemory(pLookupInfo->pData, BUFSIZE);
-        /* notify the reader thread that it should begin reading */
-        SetEvent(pLookupInfo->hReady);
-#ifdef USE_WIN32_EVENTS
-        /* Doing this will block Tcl event processing */
-        dwWait = WaitForSingleObject(pLookupInfo->hDone, INFINITE);
-#else
-        /* Run a tcl event loop while we wait for the answer */
-        while (1) {
-            Tcl_DoOneEvent(0); /* when tk loaded */
-            //Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
-            OutputDebugString("done one event\n");
-            dwWait = WaitForSingleObject(pLookupInfo->hDone, 0);
-            if (dwWait == WAIT_OBJECT_0)
-                break;
-        }
-#endif
-    }
-    if (!br) {
-        return _T("");
-    }
-    return (LPCTSTR)pLookupInfo->pData;
-}
-static BOOL
-CreateChildProcess(HANDLE hChildStdoutWr, HANDLE hChildStdinRd) 
-{ 
-    PROCESS_INFORMATION piProcInfo; 
-    STARTUPINFO siStartInfo;
-    BOOL bFuncRetn = FALSE; 
-    /* Set up members of the PROCESS_INFORMATION structure.*/
-    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
-    /* Set up members of the STARTUPINFO structure.*/
-    ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
-    siStartInfo.cb = sizeof(STARTUPINFO); 
-    siStartInfo.hStdError = hChildStdoutWr;
-    siStartInfo.hStdOutput = hChildStdoutWr;
-    siStartInfo.hStdInput = hChildStdinRd;
-    siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
-    /* Create the child process.*/
-    bFuncRetn = CreateProcess(NULL, 
-                              "resolver",    // command line 
-                              NULL,          // process security attributes 
-                              NULL,          // primary thread security attributes 
-                              TRUE,          // handles are inherited 
-                              DETACHED_PROCESS, // no console
-                              NULL,          // use parent's environment 
-                              NULL,          // use parent's current directory 
-                              &siStartInfo,  // STARTUPINFO pointer 
-                              &piProcInfo);  // receives PROCESS_INFORMATION 
-   
-    if (bFuncRetn == 0) 
-        return bFuncRetn; /*ErrorExit("CreateProcess failed");*/
-    else 
-    {
-        CloseHandle(piProcInfo.hProcess);
-        CloseHandle(piProcInfo.hThread);
-        return bFuncRetn;
+    /* notify the reader thread that it should begin reading */
+    PostThreadMessage(pkgPtr->idReader, XWM_RESOLVE, 0, (LPARAM)queryPtr);
+
+    /* Run a tcl event loop while we wait for the answer */
+    while (1) {
+        Tcl_DoOneEvent(0); /* when tk loaded */
+        //Tcl_DoOneEvent(TCL_ALL_EVENTS|TCL_DONT_WAIT);
+        dwWait = WaitForSingleObject(queryPtr->lock, 0);
+        if (dwWait == WAIT_OBJECT_0) {
+           sprintf(sz, "query %d complete\n", queryPtr->cookie);
+           OutputDebugString(sz);
+            break;
+       }
     }
+
+    resObj = Tcl_NewStringObj(queryPtr->data, -1);
+    CloseHandle(queryPtr->lock);
+    Tcl_Free((char *)queryPtr);
+    return resObj;
 }
 
 static DWORD WINAPI
 Reader(LPVOID clientData)
 {
-    LPLOOKUPINFO pLookupInfo = (LPLOOKUPINFO)clientData;
+    LPPKGINFO pkgPtr = (LPPKGINFO)clientData;
+    LPQUERYINFO queryPtr = NULL;
+    MSG msg;
     DWORD dwErr = 0, dwRead = 0;
-    BOOL br;
-
-    while (pLookupInfo->bRunning) {
-        dwErr = WaitForSingleObject(pLookupInfo->hReady, 500);
-        if (dwErr == WAIT_OBJECT_0) {
-            br = ReadFile(pLookupInfo->hIn, pLookupInfo->pData,
-                          BUFSIZE, &dwRead, NULL);
-
-            if (dwRead > 0) {
-                LPTSTR p = (LPTSTR)pLookupInfo->pData;
-                for (p = p + lstrlen(p) - 1;
-                     p > pLookupInfo->pData && _istspace(*p);
-                     p--)
-                    ;
-                *++p = 0;
-            }
-#ifdef USE_WIN32_EVENTS
-            SetEvent(pLookupInfo->hDone);
-#else
-            QueueEvent(pLookupInfo);
-#endif
-        }
+    
+    while(GetMessage(&msg, 0, 0, 0)) {
+       if (msg.hwnd == NULL) {
+           switch (msg.message) {
+               case XWM_RESOLVE:
+                   queryPtr = (LPQUERYINFO)msg.lParam;
+                   GetAddress(queryPtr->data);
+                   QueueEvent(pkgPtr->tclid, queryPtr);
+                   break;
+           }
+       }
+       DispatchMessage(&msg);
     }
+
+    OutputDebugStringA("Reader exiting.\n");
     return 0;
 }
 
 static void
-QueueEvent(LPLOOKUPINFO pLookupInfo)
+QueueEvent(Tcl_ThreadId id, LPQUERYINFO queryPtr)
 {
     LPRESOLVEREVENT evPtr;
-    OutputDebugString("queueevent\n");
+    OutputDebugStringA("QueueEvent\n");
     evPtr = (LPRESOLVEREVENT)Tcl_Alloc(sizeof(RESOLVEREVENT));
     evPtr->header.proc = ResolverEventProc;
     evPtr->header.nextPtr = NULL;
-    evPtr->info = pLookupInfo;
-    Tcl_ThreadQueueEvent(pLookupInfo->tclid, 
-                         (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
+    evPtr->query = queryPtr;
+    Tcl_ThreadQueueEvent(id, (Tcl_Event *)evPtr, TCL_QUEUE_TAIL);
 }
 
 static int
 ResolverEventProc(Tcl_Event *evPtr, int flags)
 {
     LPRESOLVEREVENT revPtr = (LPRESOLVEREVENT)evPtr;
-    OutputDebugString("resolvereventproc\n");
-    SetEvent(revPtr->info->hDone);
+    OutputDebugStringA("ResolverEventProc\n");
+    SetEvent(revPtr->query->lock);
     return 1;
 }
 
-#if 0
-int
-TclGetHostByName(LPSOCKADDR_IN saddrPtr, const char *hostname, int port)
+static Tcl_Obj *
+Win32Error(const char * szPrefix, HRESULT hr)
+{
+    Tcl_Obj *msgObj = NULL;
+    char * lpBuffer = NULL;
+    DWORD  dwLen = 0;
+    
+    dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER 
+                          | FORMAT_MESSAGE_FROM_SYSTEM,
+                          NULL, (DWORD)hr, LANG_NEUTRAL,
+                          (LPTSTR)&lpBuffer, 0, NULL);
+    if (dwLen < 1) {
+        dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER 
+                              | FORMAT_MESSAGE_FROM_STRING
+                              | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                              "code 0x%1!08X!%n", 0, LANG_NEUTRAL,
+                              (LPTSTR)&lpBuffer, 0, (va_list *)&hr);
+    }
+
+    msgObj = Tcl_NewStringObj(szPrefix, -1);
+    if (dwLen > 0) {
+       char *p = lpBuffer + dwLen - 1;        /* remove cr-lf at end */
+       for ( ; p && *p && isspace(*p); p--)
+           ;
+       *++p = 0;
+       Tcl_AppendToObj(msgObj, ": ", 2);
+       Tcl_AppendToObj(msgObj, lpBuffer, -1);
+    }
+    LocalFree((HLOCAL)lpBuffer);
+    return msgObj;
+}
+
+static int
+GetAddress(char *query)
 {
-    struct in_addr addr;
-
-    ZeroMemory(saddrPtr, sizeof(SOCKADDR_IN));
-    saddrPtr->sin_family = AF_INET;
-    saddrPtr->sin_port = htons((unsigned short)port);
-    /* if no hostname then the answer is any host */
-    if (hostname == NULL || *hostname == 0) {
-        addr.s_addr = INADDR_ANY;
+    struct addrinfo hints = {0};
+    struct addrinfo *res = NULL;
+    char *hostname, *p, *q;
+    int r = 0, nc = 0;
+    
+    /* trim whitespace */
+    for (p = query; *p && isspace(*p); p++)
+       ;
+    for (q = p + strlen(p) - 1; q > p && *q && isspace(*q); q--)
+       ;
+    *++q = 0;
+    hostname = p;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = PF_INET; /* use PF_UNSPEC if we want IPv6 too */
+    hints.ai_family = PF_UNSPEC;
+    hints.ai_flags = AI_CANONNAME;
+    hints.ai_socktype = SOCK_STREAM;
+    r = getaddrinfo(hostname, "", &hints, &res);
+    *query = 0;
+
+    if (r != 0) {
+       Tcl_Obj *o = Win32Error("error", WSAGetLastError());
+       strcpy(query, Tcl_GetString(o));
+       Tcl_DecrRefCount(o);
     } else {
-        /* see if we have been given an ip number already */
-        addr.s_addr = inet_addr(hostname);
-        if (addr.s_addr == INADDR_NONE) {
-            /* Perform the address lookup via our subprocess */
-            addr.s_addr = inet_addr(LookupHostname(hostname));
-            if (addr.s_addr == INADDR_NONE) {
-#ifdef EHOSTUNREACH
-                Tcl_SetErrno(EHOSTUNREACH);
-#endif
-                return 0; /* error */
-            }
-        }
+       struct addrinfo *resPtr = res;
+       for (resPtr = res; resPtr != NULL; resPtr = resPtr->ai_next) {
+           char name[NI_MAXHOST];
+
+           getnameinfo(resPtr->ai_addr, resPtr->ai_addrlen, 
+                       name, NI_MAXHOST,
+                       NULL, 0,
+                       NI_NUMERICHOST | NI_NUMERICSERV);
+
+           if (resPtr != res)
+               strcat(query, " ");
+           strcat(query, name);
+       }
+       freeaddrinfo(res);
     }
-    saddrPtr->sin_addr.s_addr = addr.s_addr;
-    return 1;
+    return r;
 }
-#endif
+    
+