Release 950817

Thu Aug 17 19:30:14 1995  Alexandre Julliard  <julliard@sunsite.unc.edu>

	* [*/Makefile.in]
	Removed winelibclean target, as it doesn't work anyway.

	* [controls/button.c]
	Avoid drawing the focus rectangle outside of the button.

	* [controls/widgets.c]
	Fixed bug with the size of the reserved bytes for the Edit
	control (caused Eudora to crash).

	* [debugger/*] [include/debugger.h]
	Unified debugger address handling. Segmented and linear addresses
	are no grouped in a single type DBG_ADDR.
	All commands now accept seg:off addresses.
	Module entry points are now loaded upon first entry to the
	debugger, so that entry points of the loaded executable also
	appear in the symbol table.

	* [include/registers.h] [miscemu/*.c]
	Register macros are now of the form 'AX_reg(context)' instead of 'AX'.
	This makes code less readable, but will prevent a lot of name
	clashes with other definitions. It also avoids a hidden reference
	to the 'context' variable.

	* [ipc/dde_atom.c] [misc/atom.c]
	All *AddAtom and *FindAtom functions now take a SEGPTR parameter,
	to allow supporting integer atoms.
	Moved atom.c to memory/ directory.

	* [loader/task.c]
	Fixed environment allocation to compute the size dynamically.
	Added 'windir' environment variable.
	Fixed GetDOSEnvironment() to return the current task environment.

	* [windows/message.c]
	Fixed bug in MSG_GetWindowForEvent().

Wed Aug  9 11:40:43 1995  Marcus Meissner  <msmeissn@faui01.informatik.uni-erlangen.de>

	* [include/ole.h]
	Added a lot of structures  from my Borland Manual. Neither complete,
	nor 100% right (check please)
	
	* [misc/shell.c]
	Fixed some of the Reg* functions.
	Enhanced ShellExecute.
	Please test: wine "regedit.exe /v" mplayer.exe soundrec.exe
	Do YOU know the format of \WINDOWS\REG.DAT? Mail me please :)

	* [misc/dos_fs.c]
	Make umsdos mounted windows dirs work again.

	* [miscemu/emulate.c]
	Added some comments, preimplementation of subfunction 7.

	* [multimedia/mmsystem.c]
	Implemented mciSendString. not complete, not clean, not
	necessarily working (only checked with a program which uses
 	'cdaudio' (one working program is cool.exe, a shareware waveditor
 	with cdaudio play facilities.)

	* [multimedia/mcicda.c]
	Segptr fixes in DriverProc
	Default cdrom drive in Linux is /dev/cdrom ... usually a symbolic
 	link to your real cdrom device.

Tue Aug  8 19:41:50 CDT 1995 Daniel Schepler <dks2@cec.wustl.edu>

	* [loader/resource.c]
	Don't crash in a LoadString to NULL

	* [loader/resource.c]
	Fixed accelerators to work with modifiers.  (ALT-x modifiers still
 	won't work unless the ALT keypress exited the menu.)

	* [misc/file.c]
	Expand a file to the current offset with an _lwrite of size zero.

	* [misc/file.c]
	Set a newly created file to read-write instead of write-only.
	
Sun Aug  6 20:28:35 1995  Anand Kumria <akumria@ozemail.com.au>

	* [misc/main.c] [include/msdos.h]
	Fixed to return DOS version 6.22, and the correct byte order
	for Windows programs.

Wed Aug  2 12:36:33 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

	* [include/options.h] [memory/global.c] [misc/main.c]
	Make the new IPC run-time selectible, disabling it by default.
	(I think it's only useful for libwine, anyway.)

	* [loader/task.c] [memory/selector.c]
	In FreeSelector(), walk up the stack and fix the frames.

	* [objects/dib.c]
	Missing break statement in DIB_SetImageBits_RLE8().
	In GetDIBits(), set the compression flag in the bitmap info to zero.

	* [windows/dialog.c]
	GetNextDlgGroupItem() needs to treat the first child as if it had
	an implicit WS_GROUP bit set.

Mon Jul 31 15:44:47 EDT 1995 Louis-D. Dubeau <ldd@step.polymtl.ca>

	* [misc/dos_fs.c]
	Quick'n dirty fix for the initialisation of the Z: information
	structure.
diff --git a/misc/Imakefile b/misc/Imakefile
index 9e52608..1470bad 100644
--- a/misc/Imakefile
+++ b/misc/Imakefile
@@ -3,7 +3,6 @@
 MODULE = misc
 
 SRCS = \
-	atom.c \
 	clipboard.c \
 	comm.c \
 	commdlg.c \
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 84afd90..c2bdaa7 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -11,7 +11,7 @@
 
 MODULE 	= misc
 
-SRCS 	= atom.c clipboard.c comm.c commdlg.c compobj.c dos_fs.c \
+SRCS 	= clipboard.c comm.c commdlg.c compobj.c dos_fs.c \
 	driver.c exec.c escape.c file.c keyboard.c kernel32.c lstr.c \
 	main.c ole2.c ole2disp.c ole2nls.c olecli.c olesvr.c network.c \
 	profile.c rect.c shell.c sound.c spy.c stress.c user.c \
@@ -24,8 +24,8 @@
 
 all: checkrc $(MODULE).o
 
-checkrc:
-	(cd $(TOPSRC)/rc; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)')
+checkrc: dummy
+	cd $(TOPSRC)/rc; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)'
 
 $(MODULE).o: $(OBJS)
 	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
@@ -33,27 +33,17 @@
 depend:
 	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
 	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
-	cp tmp_make Makefile
-	rm tmp_make
+	mv tmp_make Makefile
 
 clean:
 	rm -f *.o \#*\# *~ tmp_make
 
 distclean: clean
-	rm Makefile
+	rm -f Makefile
 
 countryclean:
 	rm -f ole2nls.o shell.o commdlg.o
 
-NAMES = $(SRCS:.c=)
-
-winelibclean:
-	for i in $(NAMES); do \
-	if test `grep -c WINELIB $$i.c` -ne 0; then \
-	rm $$i.o; \
-	fi; \
-	done
- 
 dummy:
 
 ### Dependencies:
diff --git a/misc/atom.c b/misc/atom.c
deleted file mode 100644
index f3286cd..0000000
--- a/misc/atom.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Atom table functions
- *
- * Copyright 1993, 1994, 1995 Alexandre Julliard
- */
-
-/*
- * Current limitations:
- *
- * - The code assumes that LocalAlloc() returns a block aligned on a
- * 4-bytes boundary (because of the shifting done in HANDLETOATOM).
- * If this is not the case, the allocation code will have to be changed.
- *
- * - Integer atoms created with MAKEINTATOM are not supported.  This is
- * because they can't generally be differentiated from string constants
- * located below 0x10000 in the emulation library.  If you need
- * integer atoms, use the "#1234" form.
- *
- * 13/Feb, miguel
- * Changed the calls to LocalAlloc to LocalAlign. When compiling WINELIB
- * you call a special version of LocalAlloc that would do the alignement.
- * When compiling the emulator we depend on LocalAlloc returning the
- * aligned block. Needed to test the Library.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "atom.h"
-#include "instance.h"
-#include "ldt.h"
-#include "stackframe.h"
-#include "user.h"
-
-#define DEFAULT_ATOMTABLE_SIZE    37
-#define MIN_STR_ATOM              0xc000
-
-#define ATOMTOHANDLE(atom)        ((HANDLE)(atom) << 2)
-#define HANDLETOATOM(handle)      ((ATOM)(0xc000 | ((handle) >> 2)))
-
-#define HAS_ATOM_TABLE(sel)  \
-          ((INSTANCEDATA*)PTR_SEG_OFF_TO_LIN(sel,0))->atomtable != 0)
-
-#define GET_ATOM_TABLE(sel)  ((ATOMTABLE*)PTR_SEG_OFF_TO_LIN(sel, \
-          ((INSTANCEDATA*)PTR_SEG_OFF_TO_LIN(sel,0))->atomtable))
-		
-#ifdef WINELIB
-#define USER_HeapSel	0
-#endif
-
-/***********************************************************************
- *           ATOM_InitTable
- */
-static WORD ATOM_InitTable( WORD selector, WORD entries )
-{
-    int i;
-    HANDLE handle;
-    ATOMTABLE *table;
-
-      /* Allocate the table */
-
-    handle = LOCAL_Alloc( selector, LMEM_FIXED,
-                          sizeof(ATOMTABLE) + (entries-1) * sizeof(HANDLE) );
-    if (!handle) return 0;
-    table = (ATOMTABLE *)PTR_SEG_OFF_TO_LIN( selector, handle );
-    table->size = entries;
-    for (i = 0; i < entries; i++) table->entries[i] = 0;
-
-      /* Store a pointer to the table in the instance data */
-
-    ((INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( selector, 0 ))->atomtable = handle;
-    return handle;
-}
-
-
-/***********************************************************************
- *           ATOM_Init
- *
- * Global table initialisation.
- */
-WORD ATOM_Init()
-{
-    return ATOM_InitTable( USER_HeapSel, DEFAULT_ATOMTABLE_SIZE );
-}
-
-
-/***********************************************************************
- *           ATOM_GetTable
- *
- * Return a pointer to the atom table of a given segment, creating
- * it if necessary.
- */
-static ATOMTABLE * ATOM_GetTable( WORD selector, BOOL create )
-{
-    INSTANCEDATA *ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( selector, 0 );
-    if (!ptr->atomtable)
-    {
-        if (!create) return NULL;
-        if (!ATOM_InitTable( selector, DEFAULT_ATOMTABLE_SIZE )) return NULL;
-    }
-    return (ATOMTABLE *)((char *)ptr + ptr->atomtable);
-}
-
-
-/***********************************************************************
- *           ATOM_MakePtr
- *
- * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()).
- */
-static ATOMENTRY * ATOM_MakePtr( WORD selector, HANDLE handle )
-{
-    return (ATOMENTRY *)PTR_SEG_OFF_TO_LIN( selector, handle );
-}
-
-
-/***********************************************************************
- *           ATOM_Hash
- */
-static WORD ATOM_Hash( WORD entries, LPCSTR str, WORD len )
-{
-    WORD i, hash = 0;
-
-    for (i = 0; i < len; i++) hash ^= toupper(str[i]) + i;
-    return hash % entries;
-}
-
-
-/***********************************************************************
- *           ATOM_AddAtom
- */
-static ATOM ATOM_AddAtom( WORD selector, LPCSTR str )
-{
-    WORD hash;
-    HANDLE entry;
-    ATOMENTRY * entryPtr;
-    ATOMTABLE * table;
-    int len;
-    
-    if ((len = strlen( str )) > 255) len = 255;
-
-      /* Check for integer atom */
-/*    if (!((int)str & 0xffff0000)) return (ATOM)((int)str & 0xffff); */
-    if (str[0] == '#') return atoi( &str[1] );
-
-    if (!(table = ATOM_GetTable( selector, TRUE ))) return 0;
-    hash = ATOM_Hash( table->size, str, len );
-    entry = table->entries[hash];
-    while (entry)
-    {
-	entryPtr = ATOM_MakePtr( selector, entry );
-	if ((entryPtr->length == len) && 
-	    (!strncasecmp( entryPtr->str, str, len )))
-	{
-	    entryPtr->refCount++;
-	    return HANDLETOATOM( entry );
-	}
-	entry = entryPtr->next;
-    }
-
-    entry = LOCAL_Alloc( selector, LMEM_FIXED, sizeof(ATOMENTRY)+len-1 );
-    if (!entry) return 0;
-    entryPtr = ATOM_MakePtr( selector, entry );
-    entryPtr->next = table->entries[hash];
-    entryPtr->refCount = 1;
-    entryPtr->length = len;
-    memcpy( entryPtr->str, str, len );
-    table->entries[hash] = entry;
-    return HANDLETOATOM( entry );
-}
-
-
-/***********************************************************************
- *           ATOM_DeleteAtom
- */
-static ATOM ATOM_DeleteAtom( WORD selector, ATOM atom )
-{
-    ATOMENTRY * entryPtr;
-    ATOMTABLE * table;
-    HANDLE entry, *prevEntry;
-    WORD hash;
-    
-    if (atom < MIN_STR_ATOM) return 0;  /* Integer atom */
-
-    if (!(table = ATOM_GetTable( selector, FALSE ))) return 0;
-    entry = ATOMTOHANDLE( atom );
-    entryPtr = ATOM_MakePtr( selector, entry );
-
-      /* Find previous atom */
-    hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length );
-    prevEntry = &table->entries[hash];
-    while (*prevEntry && *prevEntry != entry)
-    {
-	ATOMENTRY * prevEntryPtr = ATOM_MakePtr( selector, *prevEntry );
-	prevEntry = &prevEntryPtr->next;
-    }    
-    if (!*prevEntry) return atom;
-
-      /* Delete atom */
-    if (--entryPtr->refCount == 0)
-    {
-	*prevEntry = entryPtr->next;
-        LOCAL_Free( selector, entry );
-    }    
-    return 0;
-}
-
-
-/***********************************************************************
- *           ATOM_FindAtom
- */
-static ATOM ATOM_FindAtom( WORD selector, LPCSTR str )
-{
-    ATOMTABLE * table;
-    WORD hash;
-    HANDLE entry;
-    int len;
-    
-    if ((len = strlen( str )) > 255) len = 255;
-    
-      /* Check for integer atom */
-/*    if (!((int)str & 0xffff0000)) return (ATOM)((int)str & 0xffff); */
-    if (str[0] == '#') return atoi( &str[1] );
-
-    if (!(table = ATOM_GetTable( selector, FALSE ))) return 0;
-    hash = ATOM_Hash( table->size, str, len );
-    entry = table->entries[hash];
-    while (entry)
-    {
-	ATOMENTRY * entryPtr = ATOM_MakePtr( selector, entry );
-	if ((entryPtr->length == len) && 
-	    (!strncasecmp( entryPtr->str, str, len )))
-	    return HANDLETOATOM( entry );
-	entry = entryPtr->next;
-    }
-    return 0;
-}
-
-
-/***********************************************************************
- *           ATOM_GetAtomName
- */
-static WORD ATOM_GetAtomName( WORD selector, ATOM atom,
-                              LPSTR buffer, short count )
-{
-    ATOMTABLE * table;
-    ATOMENTRY * entryPtr;
-    HANDLE entry;
-    char * strPtr;
-    int len;
-    char text[8];
-    
-    if (!count) return 0;
-    if (atom < MIN_STR_ATOM)
-    {
-	sprintf( text, "#%d", atom );
-	len = strlen(text);
-	strPtr = text;
-    }
-    else
-    {
-        if (!(table = ATOM_GetTable( selector, FALSE ))) return 0;
-	entry = ATOMTOHANDLE( atom );
-	entryPtr = ATOM_MakePtr( selector, entry );
-	len = entryPtr->length;
-	strPtr = entryPtr->str;
-    }
-    if (len >= count) len = count-1;
-    memcpy( buffer, strPtr, len );
-    buffer[len] = '\0';
-    return len;
-}
-
-
-/***********************************************************************
- *           InitAtomTable   (KERNEL.68)
- */
-WORD InitAtomTable( WORD entries )
-{
-    return ATOM_InitTable( CURRENT_DS, entries );
-}
-
-
-/***********************************************************************
- *           GetAtomHandle   (KERNEL.73)
- */
-HANDLE GetAtomHandle( ATOM atom )
-{
-    if (atom < MIN_STR_ATOM) return 0;
-    return ATOMTOHANDLE( atom );
-}
-
-
-/***********************************************************************
- *           AddAtom   (KERNEL.70)
- */
-ATOM AddAtom( LPCSTR str )
-{
-    return ATOM_AddAtom( CURRENT_DS, str );
-}
-
-
-/***********************************************************************
- *           DeleteAtom   (KERNEL.71)
- */
-ATOM DeleteAtom( ATOM atom )
-{
-    return ATOM_DeleteAtom( CURRENT_DS, atom );
-}
-
-
-/***********************************************************************
- *           FindAtom   (KERNEL.69)
- */
-ATOM FindAtom( LPCSTR str )
-{
-    return ATOM_FindAtom( CURRENT_DS, str );
-}
-
-
-/***********************************************************************
- *           GetAtomName   (KERNEL.72)
- */
-WORD GetAtomName( ATOM atom, LPSTR buffer, short count )
-{
-    return ATOM_GetAtomName( CURRENT_DS, atom, buffer, count );
-}
-
-
-/***********************************************************************
- *           LocalAddAtom   (USER.268)
- */
-ATOM LocalAddAtom( LPCSTR str )
-{
-    return ATOM_AddAtom( USER_HeapSel, str );
-}
-
-
-/***********************************************************************
- *           LocalDeleteAtom   (USER.269)
- */
-ATOM LocalDeleteAtom( ATOM atom )
-{
-    return ATOM_DeleteAtom( USER_HeapSel, atom );
-}
-
-
-/***********************************************************************
- *           LocalFindAtom   (USER.270)
- */
-ATOM LocalFindAtom( LPCSTR str )
-{
-    return ATOM_FindAtom( USER_HeapSel, str );
-}
-
-
-/***********************************************************************
- *           LocalGetAtomName   (USER.271)
- */
-WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count )
-{
-    return ATOM_GetAtomName( USER_HeapSel, atom, buffer, count );
-}
diff --git a/misc/commdlg.c b/misc/commdlg.c
index f660674..79cfb69 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -368,7 +368,7 @@
   else
     *tmpstr = 0;
   if (!FILEDLG_ScanDir(hWnd, tmpstr))
-    fprintf(stderr, "FileDlg: couldn't read initial directory!\n");
+    fprintf(stderr, "FileDlg: couldn't read initial directory %s!\n", tmpstr);
   /* select current drive in combo 2 */
   n = DOS_GetDefaultDrive();
   SendDlgItemMessage(hWnd, cmb2, CB_SETCURSEL, n - 1, 0);
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index c1fd240..322ddab 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -124,6 +124,7 @@
 {
     while(*s){
 	if (*s == '\\') *s = '/';
+	*s=tolower(*s); /* umsdos fs can't read files without :( */
 	s++;
     }
 }
@@ -188,7 +189,6 @@
 	DosDrives[x].disabled = 0;
     }
     DosDrives[25].rootdir = "/";
-    strcpy(DosDrives[25].cwd, "/");
     strcpy(DosDrives[25].label, "UNIX-FS");
     DosDrives[25].serialnumber = 0x12345678;
     DosDrives[25].disabled = 0;
@@ -206,6 +206,7 @@
 
     getcwd(temp, 254);
     strcat(temp, "/");      /* For DOS_GetDosFileName */
+    strcpy(DosDrives[25].cwd, temp );
     strcpy(temp, DOS_GetDosFileName(temp));
     if(temp[0] != 'Z')
     {
diff --git a/misc/file.c b/misc/file.c
index 3581ce3..895e180 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -72,8 +72,8 @@
 {
   int result;
 
-  dprintf_file(stddeb, "_lread: handle %d, buffer = %ld, length = %d\n",
-	  		hFile, (long) lpBuffer, wBytes);
+  dprintf_file(stddeb, "_lread: handle %d, buffer = %p, length = %d\n",
+	  		hFile, lpBuffer, wBytes);
   
   result = wBytes == 0 ? 0 : read (hFile, lpBuffer, wBytes);
 
@@ -90,10 +90,28 @@
 {
     int result;
 
-    dprintf_file(stddeb, "_lwrite: handle %d, buffer = %ld, length = %d\n",
-		 hFile, (long) lpBuffer, wBytes);
+    dprintf_file(stddeb, "_lwrite: handle %d, buffer = %p, length = %d\n",
+		 hFile, lpBuffer, wBytes);
 
-    result = wBytes == 0 ? 0 : write (hFile, lpBuffer, wBytes);
+    if(wBytes == 0) {  /* Expand the file size if necessary */
+	char toWrite = 0;
+	off_t prev, end;
+	
+	prev = lseek(hFile, 0, SEEK_CUR);
+	if(prev == -1) return HFILE_ERROR;
+	end = lseek(hFile, 0, SEEK_END);
+	if(end == -1) return HFILE_ERROR;
+	if(prev > end) {
+	    lseek(hFile, prev-1, SEEK_SET);
+	    result = write(hFile, &toWrite, 1) - 1;
+	    if(result == -2) ++result;
+	}
+	else {
+	    lseek(hFile, prev, SEEK_SET);
+	    result = 0;
+	}
+    }
+    else result = write (hFile, lpBuffer, wBytes);
 
     if (result == -1)
         return HFILE_ERROR;
@@ -325,7 +343,7 @@
 		lpszFilename, fnAttribute);
 	if ((UnixFileName = DOS_GetUnixFileName(lpszFilename)) == NULL)
   		return HFILE_ERROR;
-	handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY, 0666);
+	handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_RDWR, 0666);
 
 	if (handle == -1)
 		return HFILE_ERROR;
diff --git a/misc/lstr.c b/misc/lstr.c
index 7ba113e..a37b6de 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -109,7 +109,7 @@
 /* IsCharAlphanumeric USER 434 */
 BOOL IsCharAlphanumeric(char ch)
 {
-  return (ch<'0')?0:(ch<'9');
+  return (ch < '0') ? 0 : (ch <= '9');
 }
 
 /* IsCharUpper USER 435 */
diff --git a/misc/main.c b/misc/main.c
index 3528df5..1eb750c 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -69,7 +69,8 @@
     SW_SHOWNORMAL,  /* cmdShow */
     FALSE,
     FALSE,          /* AllowReadOnly */
-    FALSE           /* Enhanced mode */
+    FALSE,          /* Enhanced mode */
+    FALSE           /* IPC enabled */
 };
 
 
@@ -80,6 +81,7 @@
     { "-depth",         ".depth",           XrmoptionSepArg, (caddr_t)NULL },
     { "-display",       ".display",         XrmoptionSepArg, (caddr_t)NULL },
     { "-iconic",        ".iconic",          XrmoptionNoArg,  (caddr_t)"on" },
+    { "-ipc",           ".ipc",             XrmoptionNoArg,  (caddr_t)"off"},
     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
@@ -100,6 +102,7 @@
   "    -desktop geom   Use a desktop window of the given geometry\n" \
   "    -display name   Use the specified display\n" \
   "    -iconic         Start as an icon\n" \
+  "    -ipc            Enable IPC facilities\n" \
   "    -debug          Enter debugger before starting application\n" \
   "    -name name      Set the application name\n" \
   "    -privatemap     Use a private color map\n" \
@@ -309,6 +312,8 @@
         Options.allowReadOnly = TRUE;
     if (MAIN_GetResource( db, ".enhanced", &value ))
         Options.enhanced = TRUE;
+    if (MAIN_GetResource( db, ".ipc", &value ))
+        Options.ipc = TRUE;
     if (MAIN_GetResource( db, ".depth", &value))
 	screenDepth = atoi( value.addr );
     if (MAIN_GetResource( db, ".desktop", &value))
@@ -558,7 +563,7 @@
  */
 LONG GetVersion(void)
 {
-    return MAKELONG( WINVERSION, DOSVERSION );
+    return MAKELONG( WINVERSION, WINDOSVER );
 }
 
 /***********************************************************************
diff --git a/misc/profile.c b/misc/profile.c
index 0c3df91..3a400d7 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -134,6 +134,7 @@
 
 
     state = FirstBrace;
+    next = CharBuffer;
     while ((c = fgetc (f)) != EOF){
 	if (c == '\r')		/* Ignore Carriage Return */
 	    continue;
diff --git a/misc/shell.c b/misc/shell.c
index ebdfd91..2157470 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <ctype.h>
 #include "windows.h"
 #include "shell.h"
 #include "neexe.h"
@@ -17,7 +18,7 @@
 
 LPKEYSTRUCT	lphRootKey = NULL,lphTopKey = NULL;
 
-static char RootKeyName[]=".classes", TopKeyName[] = "(null)";
+static char RootKeyName[]=".classes", TopKeyName[] = "[top-null]";
 
 /*************************************************************************
  *                        SHELL_RegCheckForRoot()     internal use only
@@ -62,7 +63,7 @@
  */
 LONG RegOpenKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
 {
-	LPKEYSTRUCT	lpKey;
+	LPKEYSTRUCT	lpKey,lpNextKey;
 	LPCSTR		ptr;
 	char		str[128];
 	LONG            dwRet;
@@ -71,18 +72,21 @@
         if (dwRet != ERROR_SUCCESS) return dwRet;
 	dprintf_reg(stddeb, "RegOpenKey(%08lX, %p='%s', %p)\n",
 						hKey, lpSubKey, lpSubKey, lphKey);
-	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
 	if (lphKey == NULL) return ERROR_INVALID_PARAMETER;
         switch(hKey) {
 	case 0: 
 	  lpKey = lphTopKey; break;
         case HKEY_CLASSES_ROOT: /* == 1 */
+        case 0x80000000:
           lpKey = lphRootKey; break;
         default: 
 	  dprintf_reg(stddeb,"RegOpenKey // specific key = %08lX !\n", hKey);
 	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
         }
-        if (!*lpSubKey)  { *lphKey = hKey; return ERROR_SUCCESS; }
+	if (lpSubKey == NULL || !*lpSubKey)  { 
+	  *lphKey = hKey; 
+	  return ERROR_SUCCESS; 
+	}
         while(*lpSubKey) {
           ptr = strchr(lpSubKey,'\\');
           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
@@ -91,8 +95,11 @@
           lpSubKey = ptr; 
           if (*lpSubKey) lpSubKey++;
 	  
-	  lpKey = lpKey->lpSubLvl;
-          while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { lpKey = lpKey->lpNextKey; }
+	  lpNextKey = lpKey->lpSubLvl;
+          while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { 
+          	lpKey = lpNextKey;
+          	if (lpKey) lpNextKey = lpKey->lpNextKey;
+          }
           if (lpKey == NULL) {
 	    dprintf_reg(stddeb,"RegOpenKey: key %s not found!\n",str);
 	    return ERROR_BADKEY;
@@ -119,18 +126,21 @@
 	dwRet = SHELL_RegCheckForRoot();
         if (dwRet != ERROR_SUCCESS) return dwRet;
 	dprintf_reg(stddeb, "RegCreateKey(%08lX, '%s', %p)\n",	hKey, lpSubKey, lphKey);
-	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
 	if (lphKey == NULL) return ERROR_INVALID_PARAMETER;
         switch(hKey) {
 	case 0: 
 	  lpKey = lphTopKey; break;
         case HKEY_CLASSES_ROOT: /* == 1 */
+        case 0x80000000:
           lpKey = lphRootKey; break;
         default: 
 	  dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", hKey);
 	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
         }
-        if (!*lpSubKey)  { *lphKey = hKey; return ERROR_SUCCESS; }
+	if (lpSubKey == NULL || !*lpSubKey)  { 
+	  *lphKey = hKey; 
+	  return ERROR_SUCCESS;
+	}
         while (*lpSubKey) {
           dprintf_reg(stddeb, "RegCreateKey: Looking for subkey %s\n", lpSubKey);
           ptr = strchr(lpSubKey,'\\');
@@ -210,7 +220,7 @@
     LONG       	dwRet;
     dprintf_reg(stddeb, "RegSetValue(%08lX, '%s', %08lX, '%s', %08lX);\n",
 		hKey, lpSubKey, dwType, lpVal, dwIgnored);
-    if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
+    /*if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;*/
     if (lpVal == NULL) return ERROR_INVALID_PARAMETER;
     if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
 	dprintf_reg(stddeb, "RegSetValue // key not found ... so create it !\n");
@@ -240,7 +250,7 @@
 	int			size;
 	dprintf_reg(stddeb, "RegQueryValue(%08lX, '%s', %p, %p);\n",
 							hKey, lpSubKey, lpVal, lpcb);
-	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
+	/*if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;*/
 	if (lpVal == NULL) return ERROR_INVALID_PARAMETER;
 	if (lpcb == NULL) return ERROR_INVALID_PARAMETER;
         if (!*lpcb) return ERROR_INVALID_PARAMETER;
@@ -285,12 +295,12 @@
 	case 0: 
 	  lpKey = lphTopKey; break;
         case HKEY_CLASSES_ROOT: /* == 1 */
+        case 0x80000000:
           lpKey = lphRootKey; break;
         default: 
 	  dprintf_reg(stddeb,"RegEnumKey // specific key = %08lX !\n", hKey);
 	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
         }
-
         lpKey = lpKey->lpSubLvl;
         while(lpKey != NULL){
           if (!dwSubKey){
@@ -301,7 +311,7 @@
 	    return ERROR_SUCCESS;
 	  }
           dwSubKey--;
-	  lpKey = lpKey->lpNextKey;
+          lpKey = lpKey->lpNextKey;
         }
 	dprintf_reg(stddeb, "RegEnumKey: key not found!\n");
 	return ERROR_INVALID_PARAMETER;
@@ -351,30 +361,75 @@
 HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, int iShowCmd)
 {
     char cmd[400];
+    char *p,*x;
+    long len;
+    char subclass[200];
+    /* OK. We are supposed to lookup the program associated with lpFile,
+     * then to execute it using that program. If lpFile is a program,
+     * we have to pass the parameters. If an instance is already running,
+     * we might have to send DDE commands.
+     */
     dprintf_exec(stddeb, "ShellExecute(%4X,'%s','%s','%s','%s',%x)\n",
 		hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
 		lpParameters ? lpParameters : "<null>", 
 		lpDirectory ? lpDirectory : "<null>", iShowCmd);
-    if(lpOperation && !strcasecmp(lpOperation,"print"))
-    {
-        fprintf(stderr, "Shell print %s: not supported\n", lpFile);
-    	return 2; /* file not found */
+    if (lpFile==NULL) return 0; /* should not happen */
+    if (lpOperation==NULL) /* default is open */
+      lpOperation="open";
+    p=strrchr(lpFile,'.');
+    if (p!=NULL) {
+      x=p; /* the suffixes in the register database are lowercased */
+      while (*x) {*x=tolower(*x);x++;}
     }
-    if(lpOperation && !strcasecmp(lpOperation,"open"))
-    {
-        fprintf(stderr, "ShellExecute: Unknown operation %s\n",lpOperation);
-        return 2;
-    }
-    /* OK. We are supposed to lookup the program associated with lpFile,
-       then to execute it using that program. If lpFile is a program,
-       we have to pass the parameters. If an instance is already running,
-       we might have to send DDE commands.
-       This implementation does none of that. It assumes lpFile is a program.
-       Plain WinExec will do what we need */
-    if(lpParameters)
+    if (p==NULL || !strcmp(p,".exe")) {
+      p=".exe";
+      if (lpParameters) {
         sprintf(cmd,"%s %s",lpFile,lpParameters);
-    else
+      } else {
         strcpy(cmd,lpFile);
+      }
+    } else {
+      len=200;
+      if (RegQueryValue(HKEY_CLASSES_ROOT,p,subclass,&len)==ERROR_SUCCESS) {
+	if (len>20)
+	  fprintf(stddeb,"ShellExecute:subclass with len %ld? (%s), please report.\n",len,subclass);
+	subclass[len]='\0';
+	strcat(subclass,"\\shell\\");
+	strcat(subclass,lpOperation);
+	strcat(subclass,"\\command");
+	dprintf_exec(stddeb,"ShellExecute:looking for %s.\n",subclass);
+	len=400;
+	if (RegQueryValue(HKEY_CLASSES_ROOT,subclass,cmd,&len)==ERROR_SUCCESS) {
+	  char *t;
+	  dprintf_exec(stddeb,"ShellExecute:...got %s\n",cmd);
+	  cmd[len]='\0';
+	  t=strstr(cmd,"%1");
+	  if (t==NULL) {
+	    strcat(cmd," ");
+	    strcat(cmd,lpFile);
+	  } else {
+	    char *s;
+	    s=malloc(len+strlen(lpFile)+10);
+	    strncpy(s,cmd,t-cmd);
+	    strcat(s,lpFile);
+	    strcat(s,t+2);
+	    strcpy(cmd,s);
+	    free(s);
+	  }
+	  /* does this use %x magic too? */
+	  if (lpParameters) {
+	    strcat(cmd," ");
+	    strcat(cmd,lpParameters);
+	  }
+	} else {
+	  fprintf(stddeb,"ShellExecute: No %s\\shell\\%s\\command found for \"%s\" suffix.\n",subclass,lpOperation,p);
+	  return 14; /* unknown type */
+	}
+      } else {
+	fprintf(stddeb,"ShellExecute: No operation found for \"%s\" suffix.\n",p);
+	return 14; /* file not found */
+      }
+    }
     return WinExec(cmd,iShowCmd);
 }