Release 961215

Sun Dec 15 16:18:15 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [graphics/x11drv/bitblt.c]
	Fixed BITBLT_StretchImage for partially covered or inverted
	bitmaps.

	* [objects/dib.c]
	Fixed the upside-down bitmap problem.

Sat Dec 14 02:49:57 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [if1632/user32.spec]
	IsMenu and RemoveMenu added (use existing Win16 functions).

	* [include/windows.h]
	Corrections to BITMAPINFOHEADER structure.

	* [loader/module.c] [if1632/kernel32.spec]
	New function GetModuleFileName32A (heavily based on original
	Win16 version).

	* [loader/pe_image.c]
	Hack to allow files with short PE header to be loaded (e.g.
	COMDLG32.DLL from Win32s).

	* [misc/winsock_async.c]
	#if out EIDRM case (not present in FreeBSD).

	* [tools/build.c]
	Remove trailing comments from .s files generated by build
	as these break assembly when not run through pre-processor.

	* [windows/graphics.c] [if1632/gdi32.spec]
	New function Polyline32 - based on original Polyline. Needs
	metafile support adding still.

Fri Dec 13 13:04:06 1996  Bruce Milner <Bruce.Milner@genetics.utah.edu>

	* [win32/findfile.c] [if1632/kernel.spec]
	FindFirstFile32A(): Use dos current directory for drive prefixes.
	FindNextFile32A(): Fill in file attribute information.
	Implement FindFirstFile16, FindNextFile16, FindClose16.

	* [files/drive.c]
	GetCurrentDirectory32A - Fix problem with null 3rd character in
	string.

Tue Dec 10 14:49:07 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [windows/painting.c][windows/message.c]
	Don't use linked lists to call SendMessage(), for it might destroy
 	the current listentry.

	* [misc/registry.c]
	Fixed temporary file saving (rename doesn't work across
	partitions).

	* [files/*.c]
	GetFullPathName*,GetDriveType32A fixed, CreateDirectoryEx*,
	GetVolumeInformation32W fixed.

	* [win32/process.c][if1632/kernel.spec][if1632/kernel32.spec]
	LoadLibrary* updated to new naming std., *32W added.

	* [win32/console.c] [include/wincon.h]
	Additions for NT commandline executables.

	* [if1632/advapi32.spec][if1632/kernel32.spec][win32/init.c]	
	GetUserName32W added, GetComputerName32W added,
	GetStartupInfo32W added, GetSystemInfo updated to NT standard.

	* [windows/msgbox.c][misc/shell.c][windows/graphics.c]
	MessageBox32W, ShellAbout32W, CommandLineToArgvW, Polygon32 added.

	* [misc/crtdll.c][include/crtdll.h][if1632/crtdll.spec][misc/ntdll.c]
	  [if1632/ntdll.spec]
	Lot of new unicode functions added (needed for NT).

	* [loader/pe_image.c]
	NtCurrentTeb added.

Tue Dec 10 22:39:33 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [windows/keyboard.c]
	Rewrote function TranslateAccelerator().

Mon Dec  9 14:52:13 1996  Slaven Rezic  <eserte@cs.tu-berlin.de>

	* [windows/defwnd.c] 
	DEFWND_SetText(): Set icon name.

Sun Dec  8 23:30:00 1996  Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [loader/signal.c] [misc/winsock.c] [misc/winsock_async.c]
	  [if1632/winsock.spec]
	IPC resource cleanup, bugfixes.

	* [windows/dialog.c] [windows/defdlg.c]
	More DefDlgProc() fixes.

Sun Dec  8 14:01:42 1996  Vadim Strizhevsky  <striv@ms.com>

	* [misc/clipboard.c] [objects/font.c] [win32/init.c]
 	  [win32/newfns.c] [windows/graphics.c]
	Added a few WIN32 functions which needed to run some win32
	accessories. Clock should now work almost as well as 16 bit version.
	Add: RegisterClipboardFormat32W GetTextExtentExPoint32*
	     GetModuleHandleW, DisableThreadLibraryCalls (empty stub),
	     Polygon32
	Fix: Polygon16 possible memory leak on error return.
diff --git a/misc/winsock.c b/misc/winsock.c
index 1ec7004..e26e84f 100644
--- a/misc/winsock.c
+++ b/misc/winsock.c
@@ -88,7 +88,7 @@
 static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base);
 static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base);
 
-static int delete_async_op(ws_socket*);
+static int cancel_async_select(ws_socket*);
 
 static void convert_sockopt(INT16 *level, INT16 *optname)
 {
@@ -203,8 +203,8 @@
 	    ws_socket *pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
 	    int fd = pws->fd;
 
-	    if( _check_ws(pwsi, pws) && FD_ISSET(fd, fds) ) 
-	    { 
+	    if( _check_ws(pwsi, pws) && FD_ISSET(fd, fds) )
+	    {
 		/* if error, move to errorfds */
 		if (errorfds && (FD_ISSET(fd, errorfds) || sock_error_p(fd)))
 		    FD_SET(fd, errorfds);
@@ -230,8 +230,8 @@
 	    ws_socket *pws = (ws_socket *)WS_HANDLE2PTR(ws->fd_array[i]);
 
 	    if (_check_ws(pwsi, pws) && (FD_ISSET(pws->fd, fds)
-					 || FD_ISSET(pws->fd, errorfds)))
-	      ws->fd_array[j++] = ws->fd_array[i];
+                                         || FD_ISSET(pws->fd, errorfds)))
+	    ws->fd_array[j++] = ws->fd_array[i];
 	}
 	ws->fd_count = j;
     }
@@ -298,6 +298,14 @@
   return(0);
 }
 
+void WINSOCK_Shutdown()
+{
+  if( async_qid != -1 )
+    if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
+          fprintf(stderr,"failed to delete WS message queue.\n");
+    else async_qid = -1;
+}
+
 INT16 WSACleanup(void)
 {
   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
@@ -316,11 +324,7 @@
       SIGNAL_MaskAsyncEvents( FALSE );
 
       wsi_unlink(pwsi);
-      if( _wsi_list == NULL && async_qid != -1 )
-        if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
-        { 
-          fprintf(stderr,"failed to delete WS message queue.\n");
-        } else async_qid = -1;
+      if( _wsi_list == NULL ) WINSOCK_Shutdown();
 
       if( pwsi->flags & WSI_BLOCKINGCALL )
 	  dprintf_winsock(stddeb,"\tinside blocking call!\n");
@@ -330,13 +334,14 @@
       for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
 	if( pwsi->sock[i].fd != -1 )
 	{ 
-	  n += delete_async_op(&pwsi->sock[i]);
+	  n += cancel_async_select(&pwsi->sock[i]);
           close(pwsi->sock[i].fd); j++; 
         }
       if( j ) 
 	  dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
 
       if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
+      if( pwsi->dbuffer ) SEGPTR_FREE(pwsi->dbuffer);
       WS_FREE(pwsi);
       return 0;
   }
@@ -468,12 +473,12 @@
   { 
     int		fd = pws->fd;
 
-    delete_async_op(pws);
-    pws->p_aop = NULL; pws->fd = -1;
+    cancel_async_select(pws);
+    pws->fd = -1;
     pws->flags = (unsigned)pwsi->last_free;
     pwsi->last_free = pws - &pwsi->sock[0];
-    if (close(fd) < 0) pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
-    else return 0;
+    if (close(fd) == 0) return 0;
+    pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
   }
   return SOCKET_ERROR;
 }
@@ -579,18 +584,28 @@
 
 SEGPTR WINSOCK_inet_ntoa(struct in_addr in)
 {
+  /* use "buffer for dummies" here because some applications have 
+   * propensity to decode addresses in ws_hostent structure without 
+   * saving them first...
+   */
+
   LPWSINFO      pwsi = wsi_find(GetCurrentTask());
-  char*		s = inet_ntoa(in);
 
   if( pwsi )
   {
-    if( s == NULL ) { pwsi->errno = wsaErrno(); return NULL; }
-    if( _check_buffer( pwsi, 32 ) )
-    { 
-      strncpy(pwsi->buffer, s, 32 );
-      return SEGPTR_GET(pwsi->buffer); 
+    char*	s = inet_ntoa(in);
+    if( s ) 
+    {
+	if( pwsi->dbuffer == NULL )
+	    if((pwsi->dbuffer = (char*) SEGPTR_ALLOC(32)) == NULL )
+	    {
+		pwsi->errno = WSAENOBUFS;
+		return (SEGPTR)NULL;
+	    }
+	strncpy(pwsi->dbuffer, s, 32 );
+	return SEGPTR_GET(pwsi->dbuffer); 
     }
-    pwsi->errno = WSAENOBUFS;
+    pwsi->errno = wsaErrno();
   }
   return (SEGPTR)NULL;
 }
@@ -683,7 +698,8 @@
   if( _check_ws(pwsi, pws) )
   {
     int length, fromlen32 = *fromlen16;
-    if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0) 
+
+    if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0 );
     {   
       *fromlen16 = fromlen32; 
        notify_client(pws, WS_FD_READ);
@@ -719,7 +735,7 @@
 	  {
 	    fd_set_update(pwsi, &readfds, ws_readfds, &errorfds);
 	    fd_set_update(pwsi, &writefds, ws_writefds, &errorfds);
- 	    fd_set_update_except(pwsi, &exceptfds, ws_exceptfds, &errorfds);
+	    fd_set_update_except(pwsi, &exceptfds, ws_exceptfds, &errorfds);
 	  }
 	  return highfd; 
      }
@@ -807,8 +823,8 @@
 			   (unsigned)pwsi, s, how );
   if( _check_ws(pwsi, pws) )
   {
-    pws->flags  = WS_FD_INACTIVE;
-    delete_async_op(pws);
+    pws->flags |= WS_FD_INACTIVE;
+    cancel_async_select(pws);
 
     if (shutdown(pws->fd, how) == 0) return 0;
     pwsi->errno = wsaErrno();
@@ -862,14 +878,13 @@
     {
         ws_socket*      pnew = wsi_alloc_socket(pwsi, sock);
 
-/*	printf("created %04x (%i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
- */
+	dprintf_winsock(stddeb,"\tcreated %04x (handle %i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
+
         if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
-        else
 	{
-	    close(sock);
-	    pwsi->errno = WSAENOBUFS;
-	    return INVALID_SOCKET;
+          close(sock);
+          pwsi->errno = WSAENOBUFS;
+          return INVALID_SOCKET;
 	}
     }
 
@@ -1044,7 +1059,7 @@
 
   read(p_aop->fd[0], &lLength, sizeof(unsigned));
   if( LOWORD(lLength) )
-    if( LOWORD(lLength) <= p_aop->buflen )
+    if( (int)LOWORD(lLength) <= p_aop->buflen )
     {
       char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base);
       read(p_aop->fd[0], buffer, LOWORD(lLength));
@@ -1089,7 +1104,7 @@
 
       if( pipe(async_ctl.ws_aop->fd) == 0 )
       {
-	async_ctl.ws_aop->init = (char*)init;
+	async_ctl.init = (char*)init;
 	async_ctl.lLength = len;
 	async_ctl.lEvent = type;
 
@@ -1130,6 +1145,7 @@
 		     case WSMSG_ASYNC_SERVBYNAME:
 			WS_do_async_getserv(pwsi,flag);
 		   }
+		   _exit(0); /* skip atexit()'ed cleanup */
                  }
       }
       WS_FREE(async_ctl.ws_aop);
@@ -1241,7 +1257,7 @@
     if( WINSOCK_check_async_op(p_aop) )
     {
   	kill(p_aop->pid, SIGKILL); 
-	waitpid(p_aop->pid, NULL, 0);
+	waitpid(p_aop->pid, NULL, 0); /* just in case */
 	close(p_aop->fd[0]);
 	WINSOCK_unlink_async_op(p_aop);
 	WS_FREE(p_aop);
@@ -1253,14 +1269,15 @@
 
 /* ----- asynchronous select() */
 
-int delete_async_op(ws_socket* pws)
+int cancel_async_select(ws_socket* pws)
 {
   if( pws->p_aop )
   {
     kill(pws->p_aop->pid, SIGKILL);
     waitpid(pws->p_aop->pid, NULL, 0);
-    WS_FREE(pws->p_aop); return 1;
-    pws->flags &= WS_FD_INTERNAL;
+    WS_FREE(pws->p_aop); 
+    pws->p_aop = NULL;
+    return 1;
   }
   return 0;
 }
@@ -1312,7 +1329,7 @@
 	else
 	{
 	    perror("AsyncSelect(parent)"); 
-	    delete_async_op(pws);
+	    cancel_async_select(pws);
 	    pws->flags &= WS_FD_INTERNAL;
 	    return 0;
 	}
@@ -1327,11 +1344,9 @@
 {
     ws_async_op*        p_aop;
 
-    if( delete_async_op(pws) )  /* delete old async handler if any */
-    {
-      pws->p_aop = NULL;
+    if( cancel_async_select(pws) )  /* delete old async handler if any */
       pws->flags &= WS_FD_INTERNAL;
-    }
+
     if( lEvent == 0 ) return 0;
 
     /* setup async handler - some data may be redundant */
@@ -1529,6 +1544,7 @@
        p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
        p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
        p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
+
        return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
    }
    return size;