Release 960516

Thu May 16 13:35:31 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [*/*.c]
	Renamed RECT, POINT and SIZE structures to RECT16, POINT16 and
	SIZE16. Implemented Win32 version of most functions that take
	these types as parameters.

	* [configure]
	Patched autoconf to attempt to correctly detect -lnsl and
	-lsocket. Please check this out.
	
	* [controls/button.c]
	Added support for Win32 BM_* messages.

	* [controls/menu.c]
	Avoid sending extra WM_MENUSELECT messages. This avoids crashes
	with Excel.

	* [memory.heap.c] [include/heap.h]
	Added support for SEGPTRs in Win32 heaps. Added a few macros to
 	make using SEGPTRs easier. They are a bit slower than MAKE_SEGPTR,
 	but they work with Win32.

	* [memory/atom.c]
	Implemented Win32 atom functions.

	* [memory/local.c]
	Fixed LocalReAlloc() changes to avoid copying the whole block twice.

	* [win32/memory.c]
	Use /dev/zero instead of MAP_ANON for VirtualAlloc().

	* [windows/class.c]
	Properly implemented the Win32 class functions.

	* [windows/winproc.c] (New file)
	New file handling the message translation between Win16 and Win32.

Mon May 13 18:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>

	* [windows/mdi.c] [windows/menu.c]
	Improved WM_MDICREATE and WM_MDICASCADE handling.

	* [windows/event.c] [objects/bitblt.c]
	Handle GraphicsExpose event for BitBlt from screen to screen.

	* [windows/event.c] [windows/win.c] [windows/nonclient.c]
	Bunch of fixes for problems with -managed.

	* [windows/win.c] [windows/winpos.c]
	Changed conditions for WM_SIZE, WM_MOVE, and WM_GETMINMAXINFO
	in CreateWindow.

	* [windows/win.c] [windows/queue.c] [misc/user.c]
	Do not send WM_PARENTNOTIFY when in AppExit and call WH_SHELL
	on window creation/destruction.

	* [objects/palette.c]
	Crude RealizePalette(). At least something is visible in LviewPro.

Sun May 12 02:05:00 1996  Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>

	* [if1632/gdi32.spec]
	Added Rectangle (use win16 version).

	* [if1632/kernel32.spec]
	Added GetWindowsDirectoryA (use win16 GetWindowsDirectory).

	* [if1632/user32.spec]
	Added GetSubMenu, MoveWindow, SetScrollPos, SetScrollRange (use win16
	versions).
	Added SetWindowsHookExA (empty stub for now).

	* [include/handle32.h]
	Changed #include <malloc.h> to #include <stdlib.h> to prevent
	hate message from FreeBSD compiler.

	* [win32/newfns.c]
	Added new function SetWindowsHookEx32A (empty stub for now).

	* [win32/user32.c]
	Removed redundant debugging printf statement.

Sun May 12 01:24:57 1996  Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>

	* [memory/local.c]
	Avoid creating adjacent free blocks.
	Free the block in LocalReAlloc() before allocating a new one.
	Fixed LocalReAlloc() for discarded blocks.
	
Fri May 10 23:05:12 1996  Jukka Iivonen <iivonen@cc.helsinki.fi>

	* [resources/sysres_Fi.rc]
	ChooseFont and ChooseColor dialogs updated.

Fri May 10 17:19:33 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [files/drive.c,if1632/kernel.spec]
	GetCurrentDirectory(),SetCurrentDirectory() implemented.

	* [if1632/advapi32.spec] [if1632/kernel.spec] [if1632/shell.spec]
	  [include/windows.h] [include/winreg.h] [loader/main.c]
	  [misc/main.c] [misc/shell.c] [misc/registry.c]
	Registry fixes:
	- loads win95 registry databases,
	- save only updated keys on default,
	- now adhers to the new function naming standard,
	- minor cleanups.

Tue May 7 22:36:13 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [combo.c]
	Added WM_COMMAND-handling for interaction between EDIT and COMBOLBOX
        and synchronized mine with Greg Kreider's works.

	* [commdlg.c]
	Bugfix in ChooseFont: font size handling.
diff --git a/misc/shell.c b/misc/shell.c
index dd2d591..ff63653 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -17,6 +17,7 @@
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
+#include "winreg.h"
 
 extern HANDLE 	CURSORICON_LoadHandler( HANDLE, HINSTANCE, BOOL);
 extern WORD 	GetIconID( HANDLE hResource, DWORD resType );
@@ -37,7 +38,7 @@
 /*************************************************************************
  *				DragQueryFile		[SHELL.11]
  */
-UINT DragQueryFile(HDROP hDrop, WORD wFile, LPSTR lpszFile, WORD wLength)
+UINT DragQueryFile(HDROP16 hDrop, WORD wFile, LPSTR lpszFile, WORD wLength)
 {
     /* hDrop is a global memory block allocated with GMEM_SHARE 
      * with DROPFILESTRUCT as a header and filenames following
@@ -81,7 +82,7 @@
 /*************************************************************************
  *				DragFinish		[SHELL.12]
  */
-void DragFinish(HDROP h)
+void DragFinish(HDROP16 h)
 {
     GlobalFree16((HGLOBAL16)h);
 }
@@ -90,14 +91,14 @@
 /*************************************************************************
  *				DragQueryPoint		[SHELL.13]
  */
-BOOL DragQueryPoint(HDROP hDrop, POINT *p)
+BOOL DragQueryPoint(HDROP16 hDrop, POINT16 *p)
 {
     LPDROPFILESTRUCT lpDropFileStruct;  
     BOOL             bRet;
 
     lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
 
-    memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT));
+    memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
     bRet = lpDropFileStruct->fInNonClientArea;
 
     GlobalUnlock16(hDrop);
@@ -145,7 +146,7 @@
       }
     } else {
       len=200;
-      if (RegQueryValue((HKEY)HKEY_CLASSES_ROOT,p,subclass,&len)==SHELL_ERROR_SUCCESS) {
+      if (RegQueryValue16((HKEY)HKEY_CLASSES_ROOT,p,subclass,&len)==SHELL_ERROR_SUCCESS) {
 	if (len>20)
 	  fprintf(stddeb,"ShellExecute:subclass with len %ld? (%s), please report.\n",len,subclass);
 	subclass[len]='\0';
@@ -154,7 +155,7 @@
 	strcat(subclass,"\\command");
 	dprintf_exec(stddeb,"ShellExecute:looking for %s.\n",subclass);
 	len=400;
-	if (RegQueryValue((HKEY)HKEY_CLASSES_ROOT,subclass,cmd,&len)==SHELL_ERROR_SUCCESS) {
+	if (RegQueryValue16((HKEY)HKEY_CLASSES_ROOT,subclass,cmd,&len)==SHELL_ERROR_SUCCESS) {
 	  char *t;
 	  dprintf_exec(stddeb,"ShellExecute:...got %s\n",cmd);
 	  cmd[len]='\0';
@@ -196,10 +197,131 @@
  */
 HINSTANCE FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
 {
-	fprintf(stdnimp, "FindExecutable: someone has to fix me and this is YOUR turn! :-)\n");
+    char *extension = NULL; /* pointer to file extension */
+    char tmpext[5];         /* local copy to mung as we please */
+    char filetype[256];     /* registry name for this filetype */
+    LONG filetypelen=256;   /* length of above */
+    char command[256];      /* command from registry */
+    LONG commandlen=256;    /* This is the most DOS can handle :) */
+    char buffer[256];       /* Used to GetProfileString */
+    HINSTANCE retval=31;    /* default - 'No association was found' */
+    char *tok;              /* token pointer */
+    int i;                  /* random counter */
 
-	lpResult[0]='\0';
-        return 31;		/* no association */
+    dprintf_exec(stddeb, "FindExecutable: File %s, Dir %s\n", 
+		 (lpFile != NULL?lpFile:"-"), 
+		 (lpDirectory != NULL?lpDirectory:"-"));
+
+    lpResult[0]='\0'; /* Start off with an empty return string */
+
+    /* trap NULL parameters on entry */
+    if (( lpFile == NULL ) || ( lpDirectory == NULL ) || 
+	( lpResult == NULL ))
+    {
+	/* FIXME - should throw a warning, perhaps! */
+	return 2; /* File not found. Close enough, I guess. */
+    }
+
+    /* First thing we need is the file's extension */
+    extension = strchr( lpFile, '.' ); /* Assumes first "." is the one... */
+    if ((extension == NULL) || (extension == &lpFile[strlen(lpFile)]))
+    {
+	return 31; /* no association */
+    }
+
+    /* Make local copy & lowercase it for reg & 'programs=' lookup */
+    strncpy( tmpext, extension, 5 );
+    if (strlen(extension)<=4)
+	tmpext[strlen(extension)]='\0';
+    else
+	tmpext[4]='\0';
+    for (i=0;i<strlen(tmpext);i++) tmpext[i]=tolower(tmpext[i]);
+    dprintf_exec(stddeb, "FindExecutable: %s file\n", tmpext);
+    
+    /* Three places to check: */
+    /* 1. win.ini, [windows], programs (NB no leading '.') */
+    /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
+    /* 3. win.ini, [extensions], extension (NB no leading '.' */
+    /* All I know of the order is that registry is checked before */
+    /* extensions; however, it'd make sense to check the programs */
+    /* section first, so that's what happens here. */
+
+    /* See if it's a program */
+    GetProfileString("windows", "programs", "exe pif bat com",
+		      buffer, sizeof(buffer)); /* FIXME check return code! */
+
+    for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
+
+    tok = strtok(buffer, " \t"); /* ? */
+    while( tok!= NULL)
+    {
+	if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
+	{
+	    strcpy(lpResult, lpFile); /* Need to perhaps check that */
+				      /* the file has a path attached */
+	    dprintf_exec(stddeb, "FindExecutable: found %s\n", lpResult);
+	    return 33; /* Greater than 32 to indicate success FIXME */
+		       /* what are the correct values here? */
+	}
+	tok=strtok(NULL, " \t");
+    }
+
+    /* Check registry */
+    if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
+                         &filetypelen ) == SHELL_ERROR_SUCCESS )
+    {
+	filetype[filetypelen]='\0';
+	dprintf_exec(stddeb, "File type: %s\n", filetype);
+
+	/* Looking for ...buffer\shell\open\command */
+	strcat( filetype, "\\shell\\open\\command" );
+	
+	if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
+                             &commandlen ) == SHELL_ERROR_SUCCESS )
+	{
+	    /* Is there a replace() function anywhere? */
+	    command[commandlen]='\0';
+	    strcpy( lpResult, command );
+	    tok=strstr( lpResult, "%1" );
+	    if (tok != NULL)
+	    {
+		tok[0]='\0'; /* truncate string at the percent */
+		strcat( lpResult, lpFile ); /* what if no dir in lpFile? */
+		tok=strstr( command, "%1" );
+		if ((tok!=NULL) && (strlen(tok)>2))
+		{
+		    strcat( lpResult, &tok[2] );
+		}
+	    }
+	    retval=33;
+	}
+    }
+    else /* Check win.ini */
+    {
+	/* Toss the leading dot */
+	extension++;
+	GetProfileString( "extensions", extension, "", command,
+			 sizeof(command));
+	if (strlen(command)!=0)
+	{
+	    strcpy( lpResult, command );
+	    tok=strstr( lpResult, "^" ); /* should be ^.extension? */
+	    if (tok != NULL)
+	    {
+		tok[0]='\0';
+		strcat( lpResult, lpFile ); /* what if no dir in lpFile? */
+		tok=strstr( command, "^" ); /* see above */
+		if ((tok != NULL) && (strlen(tok)>5))
+		{
+		    strcat( lpResult, &tok[5]);
+		}
+	    }
+	    retval=33;
+	}
+    }
+
+    dprintf_exec(stddeb, "FindExecutable: returning %s\n", lpResult);
+    return retval;
 }
 
 static char AppName[128], AppMisc[1536];
@@ -466,7 +588,7 @@
   UINT 	l = strlen(entry); 
   for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
      {
-       if( strncasecmp(lpEnv, entry, l) ) continue;
+       if( lstrncmpi(lpEnv, entry, l) ) continue;
        
        if( !*(lpEnv+l) )
          return (lpEnv + l); 		/* empty entry */