Release 940602

Sat May 28 12:03:23 1994  Bob Amstadt  (bob@pooh)

	* miscemu/int21.c (OpenExistingFile): 
	OpenExistingFile needed to return handle in AX register instead
	of the BX register.

	* miscemu/int21.c (ioctlGetDeviceInfo): 
	Added a little code to give a fake result for normal files.

Wed May 25 21:55:38 1994  Bob Amstadt  (bob@pooh)

	* [memory/global.c]
	return value from GlobalSize was completely wrong.

	* [miscemu/int21.h]
	fixed bug in FindFirst.  Directory pointer (dp) was not placed in
	dta correctly.

	* [tools/build.c]
	fixed creation of pop.h to guarantee that flags are restored correctly.

	* [misc/comm.c]
	changed all occurance of strncmp() to strncasecmp().
	BuildCommDCB() should not require that OpenComm() be called first.

	* [loader/selector.c]
	Heap initialized to size of full segment less stack size and 
	automatic data size.

Sat May 28 09:14:33 1994  Rick Sladkey  (jrs@world.std.com)

	* [controls/listbox.c]
	Correct typos in ListBoxResetContent where lpls variable is
	used where lsls2 variable is meant.  Don't call USER_HEAP_FREE
	twice on the same handle if hData and hMem are the same.

	* [debugger/opcodes/i386-dis.c]
	Add new name array names_rmw for table driven decoding of the
	16-bit mod/rm field.  Omit large case statement in OP_E and
	replace with array reference to match existing coding style.
	Add new static variable machine with value 286 or 386 to
	correctly decode mod/rm field in either 16 or 32 bit modes.
	Set it in print_insn_i{2,3}86.  In OP_E use it to decide how
	to decode mod/rm.  While the code was correct for 16 bit code,
	it was improperly decoding mod/rm fields on word prefixed
	32 bit instructions.

	* [debugger/debug.l]
	Recognize new token ABORT.   Recognize single letters 'p'
	and 'q' as tokens.

	* [debugger/dbg.y]
	Add new token ABORT.  Allow print command to be invoked by
	'p' and quit command by 'q', ala GDB.  Change lots of '};'
	to just '}'.  Add static dummy_regs to wine_debug so that
	wine_debug(0, NULL) doesn't core dump with qmagic.

	* [debugger/info.c]
	Correct syntax of break command in helptext and omit former
	comment about probable bugginess of the disassembly since it
	is now correct.  Change fprintf of first backtrace stack
	frame to match that of the second and subsequent frames.

	* [loader/selector.c]
	Change construction of command line in CreatePSP from creating
	a string that looks like "arg1 arg2 \r" to "arg1 arg2".  A DOS
	PSP command line looks like " arg1 arg2\r" with the length not
	including the trailing "\r" but that is not how Windows does it.

	* [loader/library.c]
	Change uses of %s to print strings in GetModuleHandle to %x so
	that string IDs don't cause a core dump with qmagic.  Handle
	converting a string id to a literal module handle.  For
	example, GetModuleHandle((LPSTR) 0x57) now returns 0x57 if
	it is a real module handle.

	* [misc/message.c]
	In MessageBox, translate a NULL title argument to the string "Error".

	* [misc/profile.c]
	In GetSetProfile translate a NULL Default argument to "".  Any
	caller whose Default argument is NULL is buggy, but CHARMAP does it
	anyway.

	* [objects/font.c]
	Add NULL pointer checks in EnumFontFamilies to prevent core dumps.

Sat May 28 20:01:51 1994 Jon Tombs (jon@gtex02.us.es) 

	* New options/resourses nosaveunders and nobackingstore.  By 
	default backingstore and saveunders are now enabled, these use 
	more memory but avoids those slow (sometimes multiple) redraws 
	caused be exposure events.

May 30, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [misc/driver.c] New file
	Skeleton for 'Installable Wine Drivers' functions. :-)
	* [misc/audio.c] New file
	Skeleton for basic 'Audio Driver' functions.
	* [misc/network.c] New file
	Stubs for few networking functions.

	* [misc/mmsystem.c]
	More coding ... a dust in a galaxy ...
	* [misc/shell.c]
	Some coding for 'RegXXX' functions ... a dust in the wind ...

	* [misc/profile.c]
	Bug fix in GetSetProfile(), bad enumeration if KeyName == NULL.

	* [objects/gdi.c]
	New function CreateDiscardableBitmap(), it just calling 
	CreateCompatibleBitmap() for now. It's get 'clock.exe' running ! :-)

	* [controls/listbox.c]
	* [controls/combo.c]
	New font member assigned to SYSTEM_FONT as default.
	Added processing for WM_SETFONT message;


Tue May 31 20:34:25 EDT 1994  John Richardson <jrichard@cs.uml.edu>

        * [windows/event.c]
        Added AsyncMouseButtonsStates array for GetAsyncKeyState.

        * [windows/keyboard.c]
        Implemented beginning of GetAsyncKeyState.

Wed May 25 23:35:03 1994  David Metcalfe <david@prism.demon.co.uk>

        * [objects/metafile.c] [include/metafile.h]
          [windows/mapping.c] [objects/clipping.c] [objects/bitblt.c]
          [windows/dc.c]
        Further metafile support.
diff --git a/ChangeLog b/ChangeLog
index 1d12476..5b0424f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,141 @@
 ----------------------------------------------------------------------
+Sat May 28 12:03:23 1994  Bob Amstadt  (bob@pooh)
+
+	* miscemu/int21.c (OpenExistingFile): 
+	OpenExistingFile needed to return handle in AX register instead
+	of the BX register.
+
+	* miscemu/int21.c (ioctlGetDeviceInfo): 
+	Added a little code to give a fake result for normal files.
+
+Wed May 25 21:55:38 1994  Bob Amstadt  (bob@pooh)
+
+	* [memory/global.c]
+	return value from GlobalSize was completely wrong.
+
+	* [miscemu/int21.h]
+	fixed bug in FindFirst.  Directory pointer (dp) was not placed in
+	dta correctly.
+
+	* [tools/build.c]
+	fixed creation of pop.h to guarantee that flags are restored correctly.
+
+	* [misc/comm.c]
+	changed all occurance of strncmp() to strncasecmp().
+	BuildCommDCB() should not require that OpenComm() be called first.
+
+	* [loader/selector.c]
+	Heap initialized to size of full segment less stack size and 
+	automatic data size.
+
+Sat May 28 09:14:33 1994  Rick Sladkey  (jrs@world.std.com)
+
+	* [controls/listbox.c]
+	Correct typos in ListBoxResetContent where lpls variable is
+	used where lsls2 variable is meant.  Don't call USER_HEAP_FREE
+	twice on the same handle if hData and hMem are the same.
+
+	* [debugger/opcodes/i386-dis.c]
+	Add new name array names_rmw for table driven decoding of the
+	16-bit mod/rm field.  Omit large case statement in OP_E and
+	replace with array reference to match existing coding style.
+	Add new static variable machine with value 286 or 386 to
+	correctly decode mod/rm field in either 16 or 32 bit modes.
+	Set it in print_insn_i{2,3}86.  In OP_E use it to decide how
+	to decode mod/rm.  While the code was correct for 16 bit code,
+	it was improperly decoding mod/rm fields on word prefixed
+	32 bit instructions.
+
+	* [debugger/debug.l]
+	Recognize new token ABORT.   Recognize single letters 'p'
+	and 'q' as tokens.
+
+	* [debugger/dbg.y]
+	Add new token ABORT.  Allow print command to be invoked by
+	'p' and quit command by 'q', ala GDB.  Change lots of '};'
+	to just '}'.  Add static dummy_regs to wine_debug so that
+	wine_debug(0, NULL) doesn't core dump with qmagic.
+
+	* [debugger/info.c]
+	Correct syntax of break command in helptext and omit former
+	comment about probable bugginess of the disassembly since it
+	is now correct.  Change fprintf of first backtrace stack
+	frame to match that of the second and subsequent frames.
+
+	* [loader/selector.c]
+	Change construction of command line in CreatePSP from creating
+	a string that looks like "arg1 arg2 \r" to "arg1 arg2".  A DOS
+	PSP command line looks like " arg1 arg2\r" with the length not
+	including the trailing "\r" but that is not how Windows does it.
+
+	* [loader/library.c]
+	Change uses of %s to print strings in GetModuleHandle to %x so
+	that string IDs don't cause a core dump with qmagic.  Handle
+	converting a string id to a literal module handle.  For
+	example, GetModuleHandle((LPSTR) 0x57) now returns 0x57 if
+	it is a real module handle.
+
+	* [misc/message.c]
+	In MessageBox, translate a NULL title argument to the string "Error".
+
+	* [misc/profile.c]
+	In GetSetProfile translate a NULL Default argument to "".  Any
+	caller whose Default argument is NULL is buggy, but CHARMAP does it
+	anyway.
+
+	* [objects/font.c]
+	Add NULL pointer checks in EnumFontFamilies to prevent core dumps.
+
+Sat May 28 20:01:51 1994 Jon Tombs (jon@gtex02.us.es) 
+
+	* New options/resourses nosaveunders and nobackingstore.  By 
+	default backingstore and saveunders are now enabled, these use 
+	more memory but avoids those slow (sometimes multiple) redraws 
+	caused be exposure events.
+
+May 30, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [misc/driver.c] New file
+	Skeleton for 'Installable Wine Drivers' functions. :-)
+	* [misc/audio.c] New file
+	Skeleton for basic 'Audio Driver' functions.
+	* [misc/network.c] New file
+	Stubs for few networking functions.
+
+	* [misc/mmsystem.c]
+	More coding ... a dust in a galaxy ...
+	* [misc/shell.c]
+	Some coding for 'RegXXX' functions ... a dust in the wind ...
+
+	* [misc/profile.c]
+	Bug fix in GetSetProfile(), bad enumeration if KeyName == NULL.
+
+	* [objects/gdi.c]
+	New function CreateDiscardableBitmap(), it just calling 
+	CreateCompatibleBitmap() for now. It's get 'clock.exe' running ! :-)
+
+	* [controls/listbox.c]
+	* [controls/combo.c]
+	New font member assigned to SYSTEM_FONT as default.
+	Added processing for WM_SETFONT message;
+
+
+Tue May 31 20:34:25 EDT 1994  John Richardson <jrichard@cs.uml.edu>
+
+        * [windows/event.c]
+        Added AsyncMouseButtonsStates array for GetAsyncKeyState.
+
+        * [windows/keyboard.c]
+        Implemented beginning of GetAsyncKeyState.
+
+Wed May 25 23:35:03 1994  David Metcalfe <david@prism.demon.co.uk>
+
+        * [objects/metafile.c] [include/metafile.h]
+          [windows/mapping.c] [objects/clipping.c] [objects/bitblt.c]
+          [windows/dc.c]
+        Further metafile support.
+
+----------------------------------------------------------------------
 Mon May 23 15:07:36 1994  Bob Amstadt  (bob@pooh)
 
 	* [loader/selector.c]
@@ -30,7 +167,7 @@
         * [windows/dialog.c]
         Fix inadvertent printing of string IDs as strings.
 
-May 16, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+May 23, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
 
 	* [controls/menu.c]
 	New functions GetMenuItemCount(), GetMenuItemID().
diff --git a/README b/README
index 4df0e04..5432ca5 100644
--- a/README
+++ b/README
@@ -197,6 +197,17 @@
 
 7. WHAT'S NEW
 
+WHAT'S NEW with Wine-940602: (see ChangeLog for details)
+	- CLOCK.EXE runs.
+	- ABORT command added to debugger.
+	- Windows environment is now imported from the UNIX environment.
+	- Use of save unders and backing store are now the default.  Resource
+	  and command line options have been added to disable these things.
+	- Assorted new driver functions
+	- GetAsyncKeyState()
+	- More metafile support
+	- and many many bug fixes!
+
 WHAT'S NEW with Wine-940524: (see ChangeLog for details)
 	- New menu functions
 	- EnumObjects()
diff --git a/controls/edit.c b/controls/edit.c
index 5e43c3b..7ff105f 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -673,7 +673,7 @@
     int col, off = 0;
     int sbl, sel, sbc, sec;
     RECT rc;
-    div_t num;
+
     BOOL trunc = FALSE;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
diff --git a/controls/listbox.c b/controls/listbox.c
index cb5f14c..d18e785 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -78,6 +78,7 @@
 			lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
 		else
 			lphl->hWndLogicParent = GetParent(hwnd);
+		lphl->hFont = GetStockObject(SYSTEM_FONT);
 		lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
 		if (wndPtr->dwStyle & WS_VSCROLL) {
 			SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
@@ -330,6 +331,14 @@
 		InvalidateRect(hwnd, NULL, TRUE);
 		UpdateWindow(hwnd);
 		break;
+	case WM_SETFONT:
+		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+		if (lphl == NULL) return 0;
+		if (wParam == 0)
+			lphl->hFont = GetStockObject(SYSTEM_FONT);
+		else
+			lphl->hFont = wParam;
+		if (wParam == 0) break;
 	case WM_PAINT:
 		wndPtr = WIN_FindWndPtr(hwnd);
 		if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
@@ -514,6 +523,7 @@
 	    }
 	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
 	if (lphl == NULL) goto EndOfPaint;
+	SelectObject(hdc, lphl->hFont);
 	hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
 		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
 	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
@@ -986,8 +996,9 @@
 #ifdef DEBUG_LISTBOX
 	    printf("ResetContent #%u\n", i);
 #endif
-	    if (lpls2->hData != 0) USER_HEAP_FREE(lpls->hData);
-	    if (lpls2->hMem != 0) USER_HEAP_FREE(lpls->hMem);
+	    if (lpls2->hData != 0 && lpls2->hData != lpls2->hMem)
+		USER_HEAP_FREE(lpls2->hData);
+	    if (lpls2->hMem != 0) USER_HEAP_FREE(lpls2->hMem);
 	    }  
 	if (lpls == NULL)  break;
     }
@@ -1093,6 +1104,7 @@
 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
 {
 	struct dosdirent *dp;
+	struct dosdirent *newdp;
 	struct stat	st;
 	int	x, wRet;
 	char 	temp[256];
@@ -1100,9 +1112,8 @@
 	fprintf(stderr,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
 #endif
 	if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL) return 0;
-	while (1) {
-		dp = (struct dosdirent *)DOS_readdir(dp);
-		if (!dp->inuse)	break;
+	while (dp = (struct dosdirent *)DOS_readdir(dp)) {
+		if (!dp->inuse) break;
 #ifdef DEBUG_LISTBOX
 		printf("ListBoxDirectory %08X '%s' !\n", dp->filename, dp->filename);
 #endif
diff --git a/debugger/dbg.y b/debugger/dbg.y
index e99e218..b478308 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -43,6 +43,7 @@
 %token NO_SYMBOL
 %token SYMBOLFILE
 %token DEFINE
+%token ABORT
 
 %%
 
@@ -52,17 +53,20 @@
  line:		'\n'
 	| infocmd '\n'
 	| error '\n'       { yyerrok; }
-	| QUIT  '\n'       { exit(0); };
-	| HELP  '\n'       { dbg_help(); };
-	| CONT '\n'        { return; };
-	| SYMBOLFILE IDENTIFIER '\n' { read_symboltable($2); };
-	| DEFINE IDENTIFIER expr '\n'  { add_hash($2, $3); };
-	| MODE NUM	   { mode_command($2); };
-	| ENABLE NUM	   { enable_break($2); };
-	| DISABLE NUM	   { disable_break($2); };
-	| BREAK '*' expr   { add_break($3); };
+	| QUIT  '\n'       { exit(0); }
+	| 'q' '\n'         { exit(0); }
+	| HELP  '\n'       { dbg_help(); }
+	| CONT '\n'        { return; }
+	| 'c' '\n'         { return; }
+	| ABORT '\n'       { kill(getpid(), SIGABRT); }
+	| SYMBOLFILE IDENTIFIER '\n' { read_symboltable($2); }
+	| DEFINE IDENTIFIER expr '\n'  { add_hash($2, $3); }
+	| MODE NUM	   { mode_command($2); }
+	| ENABLE NUM	   { enable_break($2); }
+	| DISABLE NUM	   { disable_break($2); }
+	| BREAK '*' expr   { add_break($3); }
 	| x_command
-	| BACKTRACE '\n'   { dbg_bt(); };
+	| BACKTRACE '\n'   { dbg_bt(); }
 	| print_command
 	| deposit_command
 
@@ -73,12 +77,18 @@
 
 
 x_command:
-	  'x' expr  '\n' { examine_memory($2, 1, 'x'); };
-	| 'x' '/' fmt expr  '\n' { examine_memory($4, 1, $3); };
-	| 'x' '/' NUM fmt expr  '\n' { examine_memory($5, $3, $4); };
+	  'x' expr  '\n' { examine_memory($2, 1, 'x'); }
+	| 'x' '/' fmt expr  '\n' { examine_memory($4, 1, $3); }
+	| 'x' '/' NUM fmt expr  '\n' { examine_memory($5, $3, $4); }
 
+print:
+	  'p'
+	| print
+	
  print_command:
-	PRINT expr  '\n' { examine_memory(((unsigned int) &$2 ), 1, 'x'); };
+	  print expr '\n' { examine_memory(((unsigned int) &$2 ), 1, 'x'); }
+	| print '/' fmt expr '\n' { examine_memory((unsigned int) &$4, 1, $3); }
+	| print '/' NUM fmt expr '\n' { examine_memory((unsigned int) &$5, $3, $4); }
 
  fmt:  'x'     { $$ = 'x'; }
 	| 'd'  { $$ = 'd'; }
@@ -92,20 +102,20 @@
 			           if($$ == 0xffffffff) {
 					   fprintf(stderr,"Symbol %s not found\n", $1);
 					   YYERROR;
-				   };
-			        }; 
+				   }
+			        } 
 
  expr:  NUM			{ $$ = $1;	}
 	| REG			{ if(regval) $$ = regval[$1]; else application_not_running();}
 	| symbol   		{ $$ = *((unsigned int *) $1); }
 	| expr '+' NUM		{ $$ = $1 + $3; }
-	| expr '-' NUM		{ $$ = $1 - $3; };
-	| '(' expr ')'		{ $$ = $2; };
-	| '*' expr		{ $$ = *((unsigned int *) $2); };
+	| expr '-' NUM		{ $$ = $1 - $3; }
+	| '(' expr ')'		{ $$ = $2; }
+	| '*' expr		{ $$ = *((unsigned int *) $2); }
 	
  infocmd: INFO REGS { info_reg(); }
-	| INFO STACK  { info_stack(); };
-	| INFO BREAK  { info_break(); };
+	| INFO STACK  { info_stack(); }
+	| INFO BREAK  { info_break(); }
 
 
 %%
@@ -141,8 +151,10 @@
 #ifdef YYDEBUG
 	yydebug = 0;
 #endif
+	static int dummy_regs[32];
+
 	yyin = stdin;
-	regval = regs;
+	regval = regs ? regs : dummy_regs;
 
 #ifdef linux        
 	if((SC_CS & 7) != 7) {
@@ -151,7 +163,7 @@
 	} else {
 		dbg_mask = 0xffff;
 		dbg_mode = 16;
-	};
+	}
 #endif
 #ifdef __NetBSD__
 	if(SC_CS == 0x1f) {
@@ -160,7 +172,7 @@
 	} else {
 		dbg_mask = 0xffff;
 		dbg_mode = 16;
-	};
+	}
 #endif
 	fprintf(stderr,"In %d bit mode.\n", dbg_mode);
 
@@ -170,7 +182,7 @@
 	if(!loaded_symbols){
 		loaded_symbols++;
 		load_entrypoints();
-	};
+	}
 #endif
 
 	/* Remove the breakpoints from memory... */
@@ -187,7 +199,7 @@
 	  }
 
 	/* Show where we crashed */
-	if(regval)
+	if(regs)
 	  examine_memory(SC_EIP(dbg_mask), 1, 'i');
 
 	issue_prompt();
diff --git a/debugger/debug.l b/debugger/debug.l
index 90effe0..4713516 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -98,6 +98,7 @@
 symbolfile|symbolfil|symbolfi|symbolf|symbol|symbo|symb { return SYMBOLFILE; }
 
 define|defin|defi|def|de        { return DEFINE; }
+abort|abor|abo         	        { return ABORT; }
 print|prin|pri|pr		{ return PRINT; }
 
 mode				{ return MODE; }
@@ -106,13 +107,15 @@
 
 stack|stac|sta|st     	{ return STACK; }
 
-x		{ return 'x'; }
+p  		{ return 'p'; }
+x  		{ return 'x'; }
 d		{ return 'd'; }
 i		{ return 'i'; }
 w		{ return 'w'; }
 b		{ return 'b'; }
 s		{ return 's'; }
 c		{ return 'c'; }
+q		{ return 'q'; }
 
 {IDENTIFIER}	{yylval = (int) make_symbol(yytext); 
 	          return IDENTIFIER;
diff --git a/debugger/info.c b/debugger/info.c
index b4b2358..8df409e 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -222,7 +222,7 @@
 "of the commands that gdb would accept.  The commands currently",
 "are:\n",
 "  info [reg,stack,break]",
-"  break <addr>",
+"  break *<addr>",
 "  enable bpnum",
 "  disable bpnum",
 "  help",
@@ -246,10 +246,6 @@
 " symbolfile command.  Symbols can also be defined individually with",
 " the define command.",
 "",
-"The disassembly code seems to work most of the time, but it does get",
-"a little confused at times.  The 16 bit mode probably has not been used",
-"much so there are probably bugs.",
-"",
 NULL};
 
 void dbg_help(){
@@ -286,7 +282,7 @@
   }
 
   fprintf(stderr,"Backtrace:\n");
-  fprintf(stderr,"%d: %4.4x:%4.4x\n", frameno++, SC_CS, SC_EIP(dbg_mask));
+  fprintf(stderr,"%d %4.4x:%4.4x\n", frameno++, SC_CS, SC_EIP(dbg_mask));
   cs = SC_CS;
 
   frame = (struct frame *) ((SC_EBP(dbg_mask) & ~1) | (SC_SS << 16));
diff --git a/debugger/opcodes/i386-dis.c b/debugger/opcodes/i386-dis.c
index 9d5e179..409a756 100644
--- a/debugger/opcodes/i386-dis.c
+++ b/debugger/opcodes/i386-dis.c
@@ -703,6 +703,9 @@
 static char *names_seg[] = {
   "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
 };
+static char *names_rmw[] = {
+  "%bx,%si","%bx,%di","%bp,%si","%bp,%di","%si","%di","%bp","%bx", 
+};
 
 struct dis386 grps[][8] = {
   /* GRP1b */
@@ -950,8 +953,9 @@
     }
 }
 
+static int machine;
 static int dflag;
-static int aflag;		
+static int aflag;
 
 static char op1out[100], op2out[100], op3out[100];
 static int op_address[3], op_ad, op_index[3];
@@ -1140,6 +1144,7 @@
      bfd_vma pc;
      disassemble_info *info;
 {
+  machine = 286;
   dflag = 0;
   aflag = 0;
   return print_insn_i286_or_i386 (pc, info);
@@ -1150,6 +1155,7 @@
      bfd_vma pc;
      disassemble_info *info;
 {
+  machine = 386;
   dflag = 1;
   aflag = 1;
   return print_insn_i286_or_i386 (pc, info, 36);
@@ -1555,7 +1561,7 @@
   
   append_prefix ();
 
-  if (bytemode == w_mode || (bytemode == v_mode && !dflag))
+  if (machine == 286)
     {
       if (mod == 0 && rm == 6)
 	{
@@ -1579,33 +1585,8 @@
 	  oappend (scratchbuf);
 	}
 
-      switch (rm)
-	{
-	case 0:
-	  oappend ("(%bx,%si)");
-	  break;
-	case 1:
-	  oappend ("(%bx,%di)");
-	  break;
-	case 2:
-	  oappend ("(%bp,%si)");
-	  break;
-	case 3:
-	  oappend ("(%bp,%di)");
-	  break;
-	case 4:
-	  oappend ("(%si)");
-	  break;
-	case 5:
-	  oappend ("(%di)");
-	  break;
-	case 6:
-	  oappend ("(%bp)");
-	  break;
-	case 7:
-	  oappend ("(%bx)");
-	  break;
-	}	  
+      sprintf (scratchbuf, "(%s)", names_rmw[rm]);
+      oappend (scratchbuf);
       return 0;
     }
 
diff --git a/if1632/callback.c b/if1632/callback.c
index 02f5cda..a4bd586 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -155,7 +155,7 @@
 	    user_tab = FindDLLTable("USER");
 
 	/* DefWindowProc */
-	if (user_tab[104].address == address)
+	if (user_tab[107].address == address)
 	    return DefWindowProc(hwnd, message, wParam, lParam);
 	
 	/* DefDlgProc */
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 82247c5..7c7e1d4 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -127,7 +127,7 @@
 117 pascal SetDCOrg(word s_word s_word) SetDCOrg(1 2 3)
 #121 pascal Death
 #122 pascal ReSurRection
-#123 pascal PlayMetaFile
+123 pascal PlayMetaFile(word word) PlayMetaFile(1 2)
 #124 pascal GetMetaFile
 125 pascal CreateMetaFile(ptr) CreateMetaFile(1)
 126 pascal CloseMetaFile(word) CloseMetaFile(1)
@@ -148,7 +148,8 @@
 153 pascal CreateIC(ptr ptr ptr ptr) CreateIC(1 2 3 4)
 154 pascal GetNearestColor(word long) GetNearestColor(1 2)
 #155 pascal QueryAbort
-#156 pascal CreateDiscardableBitmap
+156 pascal CreateDiscardableBitmap(word word word) 
+	   CreateDiscardableBitmap(1 2 3)
 #159 pascal GetMetaFileBits
 #160 pascal SetMetaFileBits
 161 pascal PtInRegion(word s_word s_word) PtInRegion(1 2 3)
@@ -159,6 +160,7 @@
 172 pascal SetRectRgn(word s_word s_word s_word s_word) SetRectRgn(1 2 3 4 5)
 173 pascal GetClipRgn(word) GetClipRgn(1)
 #175 pascal EnumMetaFile
+176 pascal PlayMetaFileRecord(word ptr ptr word) PlayMetaFileRecord(1 2 3 4)
 179 pascal GetDCState(word) GetDCState(1)
 180 pascal SetDCState(word word) SetDCState(1 2)
 181 pascal RectInRegionOld(word ptr) RectInRegion(1 2)
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 2f00be8..dc3076e 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -18,7 +18,7 @@
 12  pascal LocalFlags(word) WIN16_LocalFlags(1)
 13  pascal LocalCompact(word) WIN16_LocalCompact(1)
 14  return LocalNotify 4 0
-15  pascal GlobalAlloc(word long) GlobalAlloc(1 2)
+15  pascal GlobalAlloc(word long) WIN16_GlobalAlloc(1 2)
 16  pascal GlobalReAlloc(word long word) GlobalReAlloc(1 2 3)
 17  pascal GlobalFree(word) GlobalFree(1)
 18  pascal GlobalLock(word) GlobalLock(1)
@@ -203,7 +203,7 @@
 #204 SWAPRECORDING
 #205 CVWBREAK
 #206 ALLOCSELECTORARRAY
-#207 ISDBCSLEADBYTE
+207 return IsDBCSLeadByte 2 0
 #310 LOCALHANDLEDELTA
 #311 GETSETKERNELDOSPROC
 #314 DEBUGDEFINESEGMENT
diff --git a/if1632/pop.h b/if1632/pop.h
index ff2d961..3694b33 100644
--- a/if1632/pop.h
+++ b/if1632/pop.h
@@ -12,5 +12,7 @@
 	popl	%ecx
 	popl	%eax
 	add	$16,%esp
-	popfl
+	popl	%gs:return_value
 	add	$20,%esp
+	pushl	%gs:return_value
+	popfl
diff --git a/if1632/user.spec b/if1632/user.spec
index 2b4c0ee..259f377 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -258,7 +258,7 @@
 #246 EXITWINDOWSEXEC
 247 pascal GetCursor() GetCursor()
 248 pascal GetOpenClipboardWindow() GetOpenClipboardWindow()
-#249 GETASYNCKEYSTATE
+249 pascal GetAsyncKeyState(word) GetAsyncKeyState(1)
 #250 GETMENUSTATE
 #251 SENDDRIVERMESSAGE
 #252 OPENDRIVER
@@ -413,13 +413,13 @@
 #509 WNETUNWATCHQUEUE
 #510 WNETLOCKQUEUEDATA
 #511 WNETUNLOCKQUEUEDATA
-#512 WNETGETCONNECTION
+512 pascal WNetGetConnection(ptr ptr ptr) WNetGetConnection(1 2 3)
 #513 WNETGETCAPS
 #514 WNETDEVICEMODE
 #515 WNETBROWSEDIALOG
-#516 WNETGETUSER
-#517 WNETADDCONNECTION
-#518 WNETCANCELCONNECTION
+516 pascal WNetGetUser(ptr ptr ptr) WNetGetUser(1 2 3)
+517 pascal WNetAddConnection(ptr ptr ptr) WNetAddConnection(1 2 3)
+518 pascal WNetCancelConnection(ptr word) WNetCancelConnection(1 2)
 #519 WNETGETERROR
 #520 WNETGETERRORTEXT
 #521 WNETENABLE
diff --git a/include/listbox.h b/include/listbox.h
index 5d89f9e..874d69e 100644
--- a/include/listbox.h
+++ b/include/listbox.h
@@ -26,6 +26,7 @@
     void	*lpFirst; 
     DWORD	dwStyle;
     HWND	hWndLogicParent;
+	HFONT	hFont;
 } HEADLIST;
 typedef HEADLIST FAR* LPHEADLIST;
 
diff --git a/include/metafile.h b/include/metafile.h
index 0a3e5e9..a3cd796 100644
--- a/include/metafile.h
+++ b/include/metafile.h
@@ -19,13 +19,16 @@
     char   Filename[80];    /* metafile name, if disk based */
     int    hFile;           /* MSDOS file handle for metafile */
     HANDLE hMetaHdr;	    /* handle of metafile header */
-    int    MetaOffset;	    /* offset of current record in metafile */
+    int    MetaOffset;      /* offset of current record in metafile */
     HANDLE hBuffer;	    /* handle of buffer for disk based metafiles */
 } METAFILE;
 typedef METAFILE *LPMETAFILE;
 
 
 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen);
+int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj);
+int MF_AddHandleInternal(HANDLE hobj);
+BOOL MF_MetaParam0(DC *dc, short func);
 BOOL MF_MetaParam1(DC *dc, short func, short param1);
 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2);
 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2, 
@@ -35,9 +38,9 @@
 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2, 
 		   short param3, short param4, short param5,
 		   short param6, short param7, short param8);
-BOOL MF_CreateBrushIndirect(DC *dc, LOGBRUSH *logbrush);
-BOOL MF_CreatePatternBrush(DC *dc, LOGBRUSH *logbrush);
-BOOL MF_CreatePenIndirect(DC *dc, LOGPEN *logpen);
+BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush);
+BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush);
+BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen);
 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count);
 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count);
 
diff --git a/include/mmsystem.h b/include/mmsystem.h
index ac6dd22..de39b93 100644
--- a/include/mmsystem.h
+++ b/include/mmsystem.h
@@ -251,7 +251,7 @@
 UINT WINAPI waveOutGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
 UINT WINAPI waveGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
 UINT WINAPI waveOutOpen(HWAVEOUT FAR* lphWaveOut, UINT uDeviceID,
-    const WAVEFORMAT FAR* lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags);
+    const LPWAVEFORMAT lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags);
 UINT WINAPI waveOutClose(HWAVEOUT hWaveOut);
 UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut,
      WAVEHDR FAR* lpWaveOutHdr, UINT uSize);
@@ -278,7 +278,7 @@
     UINT uSize);
 UINT WINAPI waveInGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
 UINT WINAPI waveInOpen(HWAVEIN FAR* lphWaveIn, UINT uDeviceID,
-    const WAVEFORMAT FAR* lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags);
+    const LPWAVEFORMAT lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags);
 UINT WINAPI waveInClose(HWAVEIN hWaveIn);
 UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn,
     WAVEHDR FAR* lpWaveInHdr, UINT uSize);
@@ -1385,6 +1385,32 @@
 typedef MCI_OVLY_LOAD_PARMS FAR * LPMCI_OVLY_LOAD_PARMS;
 
 
+/**************************************************************
+ * 		Linux MMSYSTEM Internals & Sample Audio Drivers
+ */
+
+typedef struct {
+	DWORD   	dwCallback;
+	DWORD   	dwInstance;
+	HMIDIOUT	hMidi;
+	DWORD   	dwFlags;
+	}	PORTALLOC;
+typedef PORTALLOC FAR *LPPORTALLOC;
+
+BOOL DriverCallback(DWORD dwCallBack, UINT uFlags, HANDLE hDev, 
+		WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2);
+DWORD auxMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
+					DWORD dwParam1, DWORD dwParam2);
+DWORD midMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
+					DWORD dwParam1, DWORD dwParam2);
+DWORD modMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
+					DWORD dwParam1, DWORD dwParam2);
+DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
+					DWORD dwParam1, DWORD dwParam2);
+DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
+					DWORD dwParam1, DWORD dwParam2);
+
 #endif /* MMSYSTEM_H */
 
 
+
diff --git a/include/options.h b/include/options.h
index da5b598..5003b9f 100644
--- a/include/options.h
+++ b/include/options.h
@@ -14,6 +14,8 @@
     char * programName;     /* To use when loading resources */
     int    usePrivateMap;
     int    synchronous;
+    int    nobackingstore;
+    int    nosaveunders;
     short  cmdShow;
     int    relay_debug;
     int    debug;
diff --git a/include/prototypes.h b/include/prototypes.h
index a972176..a264ed5 100644
--- a/include/prototypes.h
+++ b/include/prototypes.h
@@ -82,7 +82,7 @@
 
 extern char *GetFilenameFromInstance(unsigned short instance);
 extern struct w_files *GetFileInfo(unsigned short instance);
-extern HINSTANCE LoadImage(char *modulename, int filetype);
+extern HINSTANCE LoadImage(char *modulename, int filetype, int change_dir);
 extern int _WinMain(int argc, char **argv);
 extern void InitializeLoadedDLLs();
 extern int FixupSegment(struct w_files * wpnt, int segment_num);
diff --git a/loader/library.c b/loader/library.c
index c53f003..e99dd6e 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -46,11 +46,18 @@
 {
 	register struct w_files *w = wine_files;
 	int 	i;
- 	printf("GetModuleHandle('%s');\n", lpModuleName);
+ 	printf("GetModuleHandle('%x');\n", lpModuleName);
  	printf("GetModuleHandle // searching in loaded modules\n");
 	while (w) {
-/*		printf("GetModuleHandle // '%s' \n", w->name);  */
-		if (strcasecmp(w->name, lpModuleName) == 0) {
+/*		printf("GetModuleHandle // '%x' \n", w->name);  */
+		if (((int) lpModuleName & 0xffff0000) == 0) {
+			if (w->hinstance == (int) lpModuleName) {
+				printf("GetModuleHandle('%x') return %04X \n",
+				       lpModuleName, w->hinstance);
+				return w->hinstance;
+				}
+			}
+		else if (strcasecmp(w->name, lpModuleName) == 0) {
 			printf("GetModuleHandle('%s') return %04X \n", 
 							lpModuleName, w->hinstance);
 			return w->hinstance;
@@ -60,13 +67,20 @@
  	printf("GetModuleHandle // searching in builtin libraries\n");
     for (i = 0; i < N_BUILTINS; i++) {
 		if (dll_builtin_table[i].dll_name == NULL) break;
-		if (strcasecmp(dll_builtin_table[i].dll_name, lpModuleName) == 0) {
-			printf("GetModuleHandle('%s') return %04X \n", 
+		if (((int) lpModuleName & 0xffff0000) == 0) {
+			if (0xFF00 + i == (int) lpModuleName) {
+				printf("GetModuleHandle('%s') return %04X \n",
+				       lpModuleName, w->hinstance);
+				return 0xFF + i;
+				}
+			}
+		else if (strcasecmp(dll_builtin_table[i].dll_name, lpModuleName) == 0) {
+			printf("GetModuleHandle('%x') return %04X \n", 
 							lpModuleName, 0xFF00 + i);
 			return (0xFF00 + i);
 			}
 		}
-	printf("GetModuleHandle('%s') not found !\n", lpModuleName);
+	printf("GetModuleHandle('%x') not found !\n", lpModuleName);
 	return 0;
 }
 
@@ -192,7 +206,7 @@
     lpNewMod->FileName = (LPSTR) malloc(strlen(libname));
     if (lpNewMod->FileName != NULL)	
 	strcpy(lpNewMod->FileName, libname);
-    lpNewMod->hInst = LoadImage(libname, DLL);
+    lpNewMod->hInst = LoadImage(libname, DLL, 0);
     lpNewMod->Count = 1;
     printf("LoadLibrary returned Library hInst=%04X\n", lpNewMod->hInst);
     GlobalUnlock(hModule);	
@@ -315,7 +329,7 @@
 		break;
 	    }
 	    cpnt += len + 2;
-	};
+	}
 	if (ordinal == 0) 
 	{
 	    printf("GetProcAddress // function '%s' not found !\n", proc_name);
diff --git a/loader/selector.c b/loader/selector.c
index fea7a6f..9573c7a 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -60,9 +60,12 @@
 
 extern void KERNEL_Ordinal_102();
 extern void UNIXLIB_Ordinal_0();
+extern char *WIN_ProgramName;
+extern char WindowsPath[256];
 
 extern char **Argv;
 extern int Argc;
+extern char **environ;
 
 /**********************************************************************
  *					FindUnusedSelectors
@@ -709,7 +712,9 @@
 static SEGDESC *
 CreateEnvironment(void)
 {
+    char **e;
     char *p;
+    unsigned short *w;
     SEGDESC * s;
 
     s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
@@ -717,15 +722,36 @@
 	return NULL;
 
     /*
-     * Fill environment with meaningless babble.
+     * Fill environment with Windows path, the Unix environment,
+     * and program name.
      */
     p = (char *) s->base_addr;
-    strcpy(p, "PATH=C:\\WINDOWS");
+    strcpy(p, "PATH=");
+    strcat(p, WindowsPath);
     p += strlen(p) + 1;
+
+    for (e = environ; *e; e++)
+    {
+	if (strncasecmp(*e, "path", 4))
+	{
+	    strcpy(p, *e);
+	    p += strlen(p) + 1;
+	}
+    }
+
     *p++ = '\0';
-    *p++ = 11;
-    *p++ = 0;
-    strcpy(p, "C:\\TEST.EXE");
+    w = (unsigned short *) p;
+    *w = strlen(WIN_ProgramName);
+    strcpy(p + 2, WIN_ProgramName);
+
+    /*
+     * Display environment
+     */
+    fprintf(stderr, "Environment at %08.8x\n", s->base_addr);
+    for (p = s->base_addr; *p; p += strlen(p) + 1)
+	fprintf(stderr, "    %s\n", p);
+    p += 3;
+    fprintf(stderr, "    Program: %s\n", p);
 
     return  s;
 }
@@ -769,12 +795,13 @@
 	    strlen(Argv[i]) > 124)
 	    break;
 	
+	if (i != 1)
+	    *p1++ = ' ';
+
 	for (p2 = Argv[i]; *p2 != '\0'; )
 	    *p1++ = *p2++;
 	
-	*p1++ = ' ';
     }
-    *p1++ = '\r';
     *p1 = '\0';
     psp->pspCommandTailCount = strlen(psp->pspCommandTail);
 
@@ -903,7 +930,8 @@
 	Segments[s->selector >> 3].owner = auto_data_sel;
 	if (s->selector == auto_data_sel)
 	    HEAP_LocalInit(auto_data_sel, s->base_addr + saved_old_length, 
-			   ne_header->local_heap_length);
+			   0x10000 - 2 - saved_old_length 
+			   - ne_header->stack_length);
     }
 
     if(!EnvironmentSelector) {
diff --git a/loader/wine.c b/loader/wine.c
index 896ed06..b88f985 100644
--- a/loader/wine.c
+++ b/loader/wine.c
@@ -34,6 +34,8 @@
 char * GetModuleName(struct w_files * wpnt, int index, char *buffer);
 extern unsigned char ran_out;
 extern char WindowsPath[256];
+char *WIN_ProgramName;
+
 unsigned short WIN_StackSize;
 unsigned short WIN_HeapSize;
 
@@ -124,24 +126,46 @@
  *					LoadImage
  * Load one NE format executable into memory
  */
-HINSTANCE LoadImage(char *modulename, int filetype)
+HINSTANCE LoadImage(char *modulename, int filetype, int change_dir)
 {
     unsigned int read_size;
     int i;
     struct w_files * wpnt, *wpnt1;
     unsigned int status;
     char buffer[256];
+    char *fullname;
 
     /*
      * search file
      */
-    if (FindFile(buffer, sizeof(buffer), modulename, (filetype == EXE ? 
-    	EXE_Extensions : DLL_Extensions), WindowsPath) ==NULL)
+    fullname = FindFile(buffer, sizeof(buffer), modulename, 
+			(filetype == EXE ? EXE_Extensions : DLL_Extensions), 
+			WindowsPath);
+    if (fullname == NULL)
     {
-    	fprintf(stderr, "LoadImage: I can't find %s.dll | %s.exe !\n",modulename, modulename);
+    	fprintf(stderr, "LoadImage: I can't find %s.dll | %s.exe !\n",
+		modulename, modulename);
 	return (HINSTANCE) NULL;
     }
-    fprintf(stderr,"LoadImage: loading %s (%s)\n", modulename, buffer);
+
+    fullname = GetDosFileName(fullname);
+    WIN_ProgramName = strdup(fullname);
+    
+    fprintf(stderr,"LoadImage: loading %s (%s)\n           [%s]\n", 
+	    modulename, buffer, WIN_ProgramName);
+
+    if (change_dir && fullname)
+    {
+	char dirname[256];
+	char *p;
+
+	strcpy(dirname, fullname);
+	p = strrchr(dirname, '\\');
+	*p = '\0';
+
+	DOS_SetDefaultDrive(dirname[0] - 'A');
+	DOS_ChangeDir(dirname[0] - 'A', dirname + 2);
+    }
 
     /* First allocate a spot to store the info we collect, and add it to
      * our linked list.
@@ -257,7 +281,7 @@
       if(FindDLLTable(buff)) continue;  /* This module already loaded */
 #endif
 
-      LoadImage(buff, DLL);
+      LoadImage(buff, DLL, 0);
 /*
       fprintf(stderr,"Unable to load:%s\n",  buff);
 */
@@ -297,7 +321,7 @@
 		strcat(WinePath, p);
 	}
 	
-	if ((hInstMain = LoadImage(Argv[0], EXE)) == (HINSTANCE) NULL ) {
+	if ((hInstMain = LoadImage(Argv[0], EXE, 1)) == (HINSTANCE) NULL ) {
 		fprintf(stderr, "wine: can't find %s!.\n", Argv[0]);
 		exit(1);
 	}
diff --git a/memory/global.c b/memory/global.c
index 0a21566..ef4e170 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -1,6 +1,7 @@
 static char RCSId[] = "$Id: global.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
+/* #define DEBUG_HEAP /* */
 #define GLOBAL_SOURCE
 
 #include <stdio.h>
@@ -406,21 +407,23 @@
 unsigned int
 GlobalSize(unsigned int block)
 {
-    GDESC *g;
-
-    if (block == 0)
+    GDESC *g = GlobalGetGDesc(block);
+    
+    if (g == NULL)
 	return 0;
 
-    /*
-     * Find GDESC for this block.
-     */
-    for (g = GlobalList; g != NULL; g = g->next)
+    if (g->sequence == 0)
     {
-	if (g->handle == block)
-	    return g->length;
+	MDESC *m = (MDESC *) g->addr - 1;
+	
+	return m->length;
     }
-
-    return 0;
+    else if (g->sequence >= 1)
+    {
+	return g->length * 0x10000;
+    }
+    
+    return g->length;
 }
 
 /**********************************************************************
diff --git a/memory/heap.c b/memory/heap.c
index c54c0ee..d6535f3 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -9,7 +9,7 @@
 #include "heap.h"
 #include "regfunc.h"
 
-/* #define DEBUG_HEAP */
+/* #define DEBUG_HEAP /* */
 
 LHEAP *LocalHeaps = NULL;
 
diff --git a/misc/Imakefile b/misc/Imakefile
index dffb628..6cfa02f 100644
--- a/misc/Imakefile
+++ b/misc/Imakefile
@@ -3,11 +3,13 @@
 MODULE = misc
 
 SRCS = \
+	audio.c \
 	atom.c \
 	clipboard.c \
 	comm.c \
 	cursor.c \
 	dos_fs.c \
+	driver.c \
 	exec.c \
 	file.c \
 	keyboard.c \
@@ -15,6 +17,7 @@
 	main.c \
 	message.c \
 	mmsystem.c \
+	network.c \
 	profile.c \
 	property.c \
 	rect.c \
diff --git a/misc/comm.c b/misc/comm.c
index 0a51b77..8f7f9bc 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -19,7 +19,7 @@
 #include "wine.h"
 #include "windows.h"
 
-#define DEBUG_COMM
+/* #define DEBUG_COMM /* */
 
 #define MAX_PORTS	16
 
@@ -155,7 +155,7 @@
 #endif
 	commerror = 0;
 
-	if (!strncmp(device,"COM",3)) {
+	if (!strncasecmp(device,"COM",3)) {
 		port = device[3] - '0';
 	
 
@@ -170,8 +170,7 @@
 		}
 		
 		if (!COM[port].fd) {
-			commerror = IE_NOPEN;
-			return -1;
+		    OpenComm(device, 0, 0);
 		}
 		lpdcb->Id = COM[port].fd;
 		
@@ -246,7 +245,7 @@
 	
 	commerror = 0;
 
-	if (!strncmp(device,"COM",3)) {
+	if (!strncasecmp(device,"COM",3)) {
 		port = device[3] - '0';
 
 		if (port-- == 0) {
@@ -259,8 +258,7 @@
 			return -1;
 		}
 		if (COM[port].fd) {
-			commerror = IE_OPEN;
-			return -1;
+			return COM[port].fd;
 		}
 
 		fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK, 0);
@@ -273,7 +271,7 @@
 		}
 	} 
 	else 
-	if (!strncmp(device,"LPT",3)) {
+	if (!strncasecmp(device,"LPT",3)) {
 		port = device[3] - '0';
 	
 		if (!ValidLPTPort(port)) {
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index 77b2429..83ed2b5 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -28,7 +28,7 @@
 #include "prototypes.h"
 #include "autoconf.h"
 
-/* #define DEBUG */
+/* #define DEBUG /* */
 
 #define WINE_INI_USER "~/.winerc"
 #define MAX_OPEN_DIRS 16
@@ -363,7 +363,7 @@
 { 
 	/*   a:\windows\system.ini  =>  /dos/windows/system.ini */
 	
-	char temp[256];
+	static char temp[256];
 	int drive;
 
 	if (dosfilename[1] == ':') 
@@ -393,7 +393,7 @@
 char *GetDosFileName(char *unixfilename)
 { 
 	int i;
-	char temp[256];
+	static char temp[256];
 	/*   /dos/windows/system.ini => c:\windows\system.ini */
 	
 	for (i = 0 ; i != MAX_DOS_DRIVES; i++) {
diff --git a/misc/exec.c b/misc/exec.c
index daccb03..a53550e 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -45,7 +45,7 @@
 			unsigned short ds);
 HANDLE CreateNewTask(HINSTANCE hInst);
 
-
+#ifndef WINELIB
 void InitializeLoadedNewDLLs(HINSTANCE hInst)
 {
     struct w_files * w;
@@ -127,7 +127,12 @@
 
 }
 
-
+#else
+void StartNewTask (HINSTANCE hInst)
+{
+    printf ("Not yet implemented\n");
+}
+#endif
 
 /**********************************************************************
  *				LoadModule	[KERNEL.45]
@@ -172,7 +177,7 @@
 			printf("Can't 'fork' process !\n");
 			break;
 		case 0:
-			if ((hInst = LoadImage(ArgV[0], EXE)) == (HINSTANCE) NULL ) {
+			if ((hInst = LoadImage(ArgV[0], EXE, 1)) == (HINSTANCE) NULL ) {
 				fprintf(stderr, "wine: can't find %s!.\n", ArgV[0]);
 				printf("Child process died !\n");
 				exit(1);
diff --git a/misc/file.c b/misc/file.c
index 3348f75..e5d7271 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -17,8 +17,6 @@
  *
  ************************************************************************/
 
-/* #define DEBUG_FILE */
-
 #include <stdio.h>
 #include <fcntl.h>
 #include <limits.h>
@@ -27,7 +25,7 @@
 #include <windows.h>
 #include "prototypes.h"
 
-/* #define DEBUG_FILE */
+/* #define DEBUG_FILE /* */
 
 char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256];
 
@@ -87,10 +85,12 @@
 {
 	int result;
 
+#if 0
 #ifdef DEBUG_FILE
   fprintf(stderr, "_lwrite: handle %d, buffer = %ld, length = %d\n",
 	  		hFile, (int) lpBuffer, wBytes);
 #endif
+#endif
 	result = write (hFile, lpBuffer, wBytes);
 
 	if (result == -1)
@@ -121,38 +121,61 @@
  **************************************************************************/
 INT OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle)
 {
-	int 	base,flags;
-	int		handle;
-#ifdef DEBUG_FILE
-	fprintf(stderr,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
-#endif
-	base=wStyle&0xF;
-	flags=wStyle&0xFFF0;
-  
-	flags&=0xFF0F;  /* strip SHARE bits for now */
-	flags&=0xD7FF;  /* strip PROMPT & CANCEL bits for now */
-	flags&=0x7FFF;  /* strip REOPEN bit for now */
-	flags&=0xFBFF;  /* strib VERIFY bit for now */
-  
-	if(flags&OF_CREATE) { base |=O_CREAT; flags &=0xEFFF; }
+    int 	base, flags;
+    int		handle;
 
 #ifdef DEBUG_FILE
-	fprintf(stderr,"now %d,%d\n",base,flags);
+    fprintf(stderr,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
 #endif
 
-	if (flags & OF_EXIST) {
-		printf("OpenFile // OF_EXIST '%s' !\n", lpFileName);
-		handle = _lopen (lpFileName, wStyle);
-		close(handle);
-		return handle;
-		}
-	if (flags & OF_DELETE) {
-		printf("OpenFile // OF_DELETE '%s' !\n", lpFileName);
-		return unlink(lpFileName);
-		}
-	else {
-		return _lopen (lpFileName, wStyle);
-		}
+    base   = wStyle & 0xF;
+    flags  = wStyle & 0xFFF0;
+  
+    flags &= 0xFF0F;  /* strip SHARE bits for now */
+    flags &= 0xD7FF;  /* strip PROMPT & CANCEL bits for now */
+    flags &= 0x7FFF;  /* strip REOPEN bit for now */
+    flags &= 0xFBFF;  /* strib VERIFY bit for now */
+  
+    if (flags & OF_CREATE) 
+    { 
+	base  |= O_CREAT; 
+	flags &= 0xEFFF; 
+    }
+
+#ifdef DEBUG_FILE
+    fprintf(stderr,"now %d,%d\n",base,flags);
+#endif
+
+    if (flags & OF_EXIST) 
+    {
+	printf("OpenFile // OF_EXIST '%s' !\n", lpFileName);
+	handle = _lopen (lpFileName, wStyle);
+	close(handle);
+	return handle;
+    }
+    if (flags & OF_DELETE) 
+    {
+	printf("OpenFile // OF_DELETE '%s' !\n", lpFileName);
+	return unlink(lpFileName);
+    }
+    else 
+    {
+	int  handle;
+	char *UnixFileName;
+
+	if ((UnixFileName = GetUnixFileName(lpFileName)) == NULL)
+	    return HFILE_ERROR;
+	handle = open(UnixFileName, base, 0666);
+
+#ifdef DEBUG_FILE
+	fprintf(stderr, "OpenFile: returning %04.4x\n", handle);
+#endif
+
+	if (handle == -1)
+	    return HFILE_ERROR;
+	else
+	    return handle;
+    }
 }
 
 /**************************************************************************
diff --git a/misc/main.c b/misc/main.c
index 245b5c9..fca16e6 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -40,6 +40,8 @@
     NULL,           /* programName */
     FALSE,          /* usePrivateMap */
     FALSE,          /* synchronous */
+    FALSE,          /* no backing store */
+    FALSE,          /* no save unders */
     SW_SHOWNORMAL,  /* cmdShow */
     FALSE
 };
@@ -47,16 +49,18 @@
 
 static XrmOptionDescRec optionsTable[] =
 {
-    { "-desktop",     ".desktop",     XrmoptionSepArg, (caddr_t)NULL },
-    { "-depth",       ".depth",       XrmoptionSepArg, (caddr_t)NULL },
-    { "-display",     ".display",     XrmoptionSepArg, (caddr_t)NULL },
-    { "-iconic",      ".iconic",      XrmoptionNoArg,  (caddr_t)"on" },
-    { "-name",        ".name",        XrmoptionSepArg, (caddr_t)NULL },
-    { "-privatemap",  ".privatemap",  XrmoptionNoArg,  (caddr_t)"on" },
-    { "-synchronous", ".synchronous", XrmoptionNoArg,  (caddr_t)"on" },
-    { "-spy",         ".spy",         XrmoptionSepArg, (caddr_t)NULL },
-    { "-debug",       ".debug",       XrmoptionNoArg,  (caddr_t)"on" },
-    { "-relaydbg",    ".relaydbg",    XrmoptionNoArg,  (caddr_t)"on" }
+    { "-desktop",       ".desktop",         XrmoptionSepArg, (caddr_t)NULL },
+    { "-depth",         ".depth",           XrmoptionSepArg, (caddr_t)NULL },
+    { "-display",       ".display",         XrmoptionSepArg, (caddr_t)NULL },
+    { "-iconic",        ".iconic",          XrmoptionNoArg,  (caddr_t)"on" },
+    { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
+    { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
+    { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
+    { "-nobackingstore",".nobackingstore",  XrmoptionNoArg,  (caddr_t)"on" },
+    { "-nosaveunders",  ".nosaveunders",    XrmoptionNoArg,  (caddr_t)"on" },
+    { "-spy",           ".spy",             XrmoptionSepArg, (caddr_t)NULL },
+    { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
+    { "-relaydbg",      ".relaydbg",        XrmoptionNoArg,  (caddr_t)"on" }
 };
 
 #define NB_OPTIONS  (sizeof(optionsTable) / sizeof(optionsTable[0]))
@@ -73,6 +77,8 @@
   "    -name name      Set the application name\n" \
   "    -privatemap     Use a private color map\n" \
   "    -synchronous    Turn on synchronous display mode\n" \
+  "    -nobackingstore Turn off backing store\n" \
+  "    -nosaveunders   Turn off saveunders\n" \
   "    -spy file       Turn on message spying to the specified file\n" \
   "    -relaydbg       Display call relay information\n"
 
@@ -177,6 +183,10 @@
 	Options.usePrivateMap = TRUE;
     if (MAIN_GetResource( db, ".synchronous", &value ))
 	Options.synchronous = TRUE;
+    if (MAIN_GetResource( db, ".nosaveunders", &value ))
+	Options.nosaveunders = TRUE;
+    if (MAIN_GetResource( db, ".nobackingstore", &value ))
+	Options.nobackingstore = TRUE;	
     if (MAIN_GetResource( db, ".relaydbg", &value ))
 	Options.relay_debug = TRUE;
     if (MAIN_GetResource( db, ".debug", &value ))
@@ -217,10 +227,21 @@
 			 StructureNotifyMask;
     win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow );
 
+    if (Options.nobackingstore)
+       win_attr.backing_store = NotUseful;
+    else
+       win_attr.backing_store = Always;
+
+    if (Options.nosaveunders)
+       win_attr.save_under = FALSE;
+    else
+       win_attr.save_under = TRUE;        
+
     rootWindow = XCreateWindow( display, DefaultRootWindow(display),
 			        desktopX, desktopY, width, height, 0,
 			        CopyFromParent, InputOutput, CopyFromParent,
-			        CWEventMask | CWCursor, &win_attr );
+			        CWEventMask | CWCursor | CWSaveUnder |
+				CWBackingStore, &win_attr );
 
       /* Set window manager properties */
 
@@ -324,14 +345,12 @@
     
 #ifndef sunos
     atexit(called_at_exit);
+#else
+    on_exit (called_at_exit, 0);
 #endif
 
     ret_val = _WinMain( argc, argv );
 
-#ifdef sunos
-    called_at_exit();
-#endif
-
     return ret_val;
 }
 
diff --git a/misc/message.c b/misc/message.c
index 0a8da32..9d754e3 100644
--- a/misc/message.c
+++ b/misc/message.c
@@ -54,6 +54,9 @@
 	DWORD		dwStyle;
 	HINSTANCE	hInst;
 	int			nRet;
+
+	if (title == NULL)
+		title = "Error";
 	wndPtr = WIN_FindWndPtr(hWnd);
 	if (wndPtr == NULL) {
 		hInst = hSysRes;
diff --git a/misc/mmsystem.c b/misc/mmsystem.c
index e4c6a2e..09304df 100644
--- a/misc/mmsystem.c
+++ b/misc/mmsystem.c
@@ -24,7 +24,9 @@
 	return(TRUE);
 }
 
-
+/**************************************************************************
+* 				sndPlaySound		[MMSYSTEM.2]
+*/
 BOOL WINAPI sndPlaySound(LPCSTR lpszSoundName, UINT uFlags)
 {
 	printf("sndPlaySound // lpszSoundName='%s' uFlags=%04X !\n", 
@@ -32,58 +34,68 @@
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				mmsystemGetVersion	[MMSYSTEM.5]
+*/
 WORD WINAPI mmsystemGetVersion()
 {
 	printf("mmsystemGetVersion // 0.4.0 ...?... :-) !\n");
 	return(0x0040);
 }
 
-
+/**************************************************************************
+* 				OutputDebugStr		[MMSYSTEM.30]
+*/
 void WINAPI OutputDebugStr(LPCSTR str)
 {
 	printf("OutputDebugStr('%s');\n", str);
 }
 
-
+/**************************************************************************
+* 				auxGetNumDevs		[MMSYSTEM.350]
+*/
 UINT WINAPI auxGetNumDevs()
 {
 	printf("auxGetNumDevs !\n");
 	return 0;
 }
 
-
+/**************************************************************************
+* 				auxGetDevCaps		[MMSYSTEM.351]
+*/
 UINT WINAPI auxGetDevCaps(UINT uDeviceID, AUXCAPS FAR* lpCaps, UINT uSize)
 {
 	printf("auxGetDevCaps !\n");
 	return 0;
 }
 
-
+/**************************************************************************
+* 				auxGetVolume		[MMSYSTEM.352]
+*/
 UINT WINAPI auxGetVolume(UINT uDeviceID, DWORD FAR* lpdwVolume)
 {
 	printf("auxGetVolume !\n");
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				auxSetVolume		[MMSYSTEM.353]
+*/
 UINT WINAPI auxSetVolume(UINT uDeviceID, DWORD dwVolume)
 {
 	printf("auxSetVolume !\n");
 	return 0;
 }
 
-
+/**************************************************************************
+* 				auxOutMessage		[MMSYSTEM.354]
+*/
 DWORD WINAPI auxOutMessage(UINT uDeviceID, UINT uMessage, DWORD dw1, DWORD dw2)
 {
 	printf("auxOutMessage !\n");
 	return 0L;
 }
 
-
-
 /**************************************************************************
 * 				mciGetErrorString		[MMSYSTEM.706]
 */
@@ -402,8 +414,7 @@
 				return MCIERR_DEVICE_NOT_INSTALLED;
 			case MCI_DEVTYPE_SEQUENCER:
 				printf("MCI_OPEN // No SEQUENCER yet !\n");
-				break;
-/*				return MCIERR_DEVICE_NOT_INSTALLED; */
+				return MCIERR_DEVICE_NOT_INSTALLED;
 			case MCI_DEVTYPE_ANIMATION:
 				printf("MCI_OPEN // No ANIMATION yet !\n");
 				return MCIERR_DEVICE_NOT_INSTALLED;
@@ -540,7 +551,6 @@
 	return MCIERR_DEVICE_NOT_INSTALLED;
 }
 
-
 /**************************************************************************
 * 				mciGetDeviceID			[MMSYSTEM.703]
 */
@@ -550,8 +560,6 @@
 	return 0;
 }
 
-
-
 /**************************************************************************
 * 				mciSendString			[MMSYSTEM.702]
 */
@@ -564,16 +572,47 @@
 	return MCIERR_MISSING_COMMAND_STRING;
 }
 
+/**************************************************************************
+* 				mciSetYieldProc		[MMSYSTEM.714]
+*/
+BOOL WINAPI mciSetYieldProc (UINT uDeviceID, 
+		YIELDPROC fpYieldProc, DWORD dwYieldData)
+{
+}
 
+/**************************************************************************
+* 				mciGetDeviceIDFromElementID	[MMSYSTEM.715]
+*/
+UINT WINAPI mciGetDeviceIDFromElementID(DWORD dwElementID, LPCSTR lpstrType)
+{
+}
 
+/**************************************************************************
+* 				mciGetYieldProc		[MMSYSTEM.716]
+*/
+YIELDPROC WINAPI mciGetYieldProc(UINT uDeviceID, DWORD FAR* lpdwYieldData)
+{
+}
+
+/**************************************************************************
+* 				mciGetCreatorTask	[MMSYSTEM.717]
+*/
+HTASK WINAPI mciGetCreatorTask(UINT uDeviceID)
+{
+}
+
+/**************************************************************************
+* 				midiOutGetNumDevs	[MMSYSTEM.201]
+*/
 UINT WINAPI midiOutGetNumDevs(void)
 {
 	printf("midiOutGetNumDevs\n");
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				midiOutGetDevCaps	[MMSYSTEM.202]
+*/
 UINT WINAPI midiOutGetDevCaps(UINT uDeviceID,
     MIDIOUTCAPS FAR* lpCaps, UINT uSize)
 {
@@ -581,23 +620,8 @@
 	return 0;
 }
 
-
-UINT WINAPI midiOutGetVolume(UINT uDeviceID, DWORD FAR* lpdwVolume)
-{
-	printf("midiOutGetVolume\n");
-	return 0;
-}
-
-
-UINT WINAPI midiOutSetVolume(UINT uDeviceID, DWORD dwVolume)
-{
-	printf("midiOutSetVolume\n");
-	return 0;
-}
-
-
 /**************************************************************************
-* 				midiOutGetErrorText 		[MMSYSTEM.203]
+* 				midiOutGetErrorText 	[MMSYSTEM.203]
 */
 UINT WINAPI midiOutGetErrorText(UINT uError, LPSTR lpText, UINT uSize)
 {
@@ -654,7 +678,9 @@
 	return(TRUE);
 }
 
-
+/**************************************************************************
+* 				midiOutOpen			[MMSYSTEM.204]
+*/
 UINT WINAPI midiOutOpen(HMIDIOUT FAR* lphMidiOut, UINT uDeviceID,
     DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
 {
@@ -663,14 +689,18 @@
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutClose		[MMSYSTEM.205]
+*/
 UINT WINAPI midiOutClose(HMIDIOUT hMidiOut)
 {
 	printf("midiOutClose\n");
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutPrepareHeader	[MMSYSTEM.206]
+*/
 UINT WINAPI midiOutPrepareHeader(HMIDIOUT hMidiOut,
     MIDIHDR FAR* lpMidiOutHdr, UINT uSize)
 {
@@ -678,7 +708,9 @@
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutUnprepareHeader	[MMSYSTEM.207]
+*/
 UINT WINAPI midiOutUnprepareHeader(HMIDIOUT hMidiOut,
     MIDIHDR FAR* lpMidiOutHdr, UINT uSize)
 {
@@ -686,14 +718,18 @@
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutShortMsg		[MMSYSTEM.208]
+*/
 UINT WINAPI midiOutShortMsg(HMIDIOUT hMidiOut, DWORD dwMsg)
 {
 	printf("midiOutShortMsg\n");
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutLongMsg		[MMSYSTEM.209]
+*/
 UINT WINAPI midiOutLongMsg(HMIDIOUT hMidiOut,
     MIDIHDR FAR* lpMidiOutHdr, UINT uSize)
 {
@@ -701,14 +737,36 @@
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutReset		[MMSYSTEM.210]
+*/
 UINT WINAPI midiOutReset(HMIDIOUT hMidiOut)
 {
 	printf("midiOutReset\n");
 	return 0;
 }
 
+/**************************************************************************
+* 				midiOutGetVolume	[MMSYSTEM.211]
+*/
+UINT WINAPI midiOutGetVolume(UINT uDeviceID, DWORD FAR* lpdwVolume)
+{
+	printf("midiOutGetVolume\n");
+	return 0;
+}
 
+/**************************************************************************
+* 				midiOutSetVolume	[MMSYSTEM.212]
+*/
+UINT WINAPI midiOutSetVolume(UINT uDeviceID, DWORD dwVolume)
+{
+	printf("midiOutSetVolume\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				midiOutCachePatches		[MMSYSTEM.213]
+*/
 UINT WINAPI midiOutCachePatches(HMIDIOUT hMidiOut,
     UINT uBank, WORD FAR* lpwPatchArray, UINT uFlags)
 {
@@ -716,7 +774,9 @@
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutCacheDrumPatches	[MMSYSTEM.214]
+*/
 UINT WINAPI midiOutCacheDrumPatches(HMIDIOUT hMidiOut,
     UINT uPatch, WORD FAR* lpwKeyArray, UINT uFlags)
 {
@@ -724,31 +784,36 @@
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutGetID		[MMSYSTEM.215]
+*/
 UINT WINAPI midiOutGetID(HMIDIOUT hMidiOut, UINT FAR* lpuDeviceID)
 {
 	printf("midiOutGetID\n");
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutMessage		[MMSYSTEM.216]
+*/
 DWORD WINAPI midiOutMessage(HMIDIOUT hMidiOut, UINT uMessage, DWORD dw1, DWORD dw2)
 {
 	printf("midiOutMessage\n");
 	return 0;
 }
 
-
-
-
+/**************************************************************************
+* 				midiInGetNumDevs	[MMSYSTEM.301]
+*/
 UINT WINAPI midiInGetNumDevs(void)
 {
 	printf("midiInGetNumDevs\n");
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				midiInGetDevCaps	[MMSYSTEM.302]
+*/
 UINT WINAPI midiInGetDevCaps(UINT uDeviceID,
     LPMIDIINCAPS lpCaps, UINT uSize)
 {
@@ -756,8 +821,6 @@
 	return 0;
 }
 
-
-
 /**************************************************************************
 * 				midiInGetErrorText 		[MMSYSTEM.303]
 */
@@ -767,8 +830,9 @@
 	return (midiGetErrorText(uError, lpText, uSize));
 }
 
-
-
+/**************************************************************************
+* 				midiInOpen		[MMSYSTEM.304]
+*/
 UINT WINAPI midiInOpen(HMIDIIN FAR* lphMidiIn, UINT uDeviceID,
     DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
 {
@@ -777,25 +841,18 @@
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				midiInClose		[MMSYSTEM.305]
+*/
 UINT WINAPI midiInClose(HMIDIIN hMidiIn)
 {
 	printf("midiInClose\n");
 	return 0;
 }
 
-
-
-
-UINT WINAPI midiInGetID(HMIDIIN hMidiIn, UINT FAR* lpuDeviceID)
-{
-	printf("midiInGetID\n");
-	return 0;
-}
-
-
-
+/**************************************************************************
+* 				midiInPrepareHeader	[MMSYSTEM.306]
+*/
 UINT WINAPI midiInPrepareHeader(HMIDIIN hMidiIn,
     MIDIHDR FAR* lpMidiInHdr, UINT uSize)
 {
@@ -803,8 +860,9 @@
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				midiInUnprepareHeader	[MMSYSTEM.307]
+*/
 UINT WINAPI midiInUnprepareHeader(HMIDIIN hMidiIn,
     MIDIHDR FAR* lpMidiInHdr, UINT uSize)
 {
@@ -812,8 +870,9 @@
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				midiInAddBuffer		[MMSYSTEM.308]
+*/
 UINT WINAPI midiInAddBuffer(HMIDIIN hMidiIn,
     MIDIHDR FAR* lpMidiInHdr, UINT uSize)
 {
@@ -821,45 +880,71 @@
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiInStart			[MMSYSTEM.309]
+*/
 UINT WINAPI midiInStart(HMIDIIN hMidiIn)
 {
 	printf("midiInStart\n");
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiInStop			[MMSYSTEM.310]
+*/
 UINT WINAPI midiInStop(HMIDIIN hMidiIn)
 {
 	printf("midiInStop\n");
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				midiInReset			[MMSYSTEM.311]
+*/
 UINT WINAPI midiInReset(HMIDIIN hMidiIn)
 {
 	printf("midiInReset\n");
 	return 0;
 }
 
-
-
-UINT WINAPI waveOutGetNumDevs()
+/**************************************************************************
+* 				midiInGetID			[MMSYSTEM.312]
+*/
+UINT WINAPI midiInGetID(HMIDIIN hMidiIn, UINT FAR* lpuDeviceID)
 {
-	printf("waveOutGetNumDevs\n");
+	printf("midiInGetID\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				midiInMessage		[MMSYSTEM.313]
+*/
+DWORD WINAPI midiInMessage(HMIDIIN hMidiIn, UINT uMessage, 
+							DWORD dwParam1, DWORD dwParam2)
+{
+	printf("midiInMessage\n");
 	return 0;
 }
 
 
+/**************************************************************************
+* 				waveOutGetNumDevs		[MMSYSTEM.401]
+*/
+UINT WINAPI waveOutGetNumDevs()
+{
+	printf("waveOutGetNumDevs\n");
+	return 1;
+}
 
+/**************************************************************************
+* 				waveOutGetDevCaps		[MMSYSTEM.402]
+*/
 UINT WINAPI waveOutGetDevCaps(UINT uDeviceID, WAVEOUTCAPS FAR* lpCaps, UINT uSize)
 {
 	printf("waveOutGetDevCaps\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
 /**************************************************************************
 * 				waveOutGetErrorText 	[MMSYSTEM.403]
 */
@@ -939,25 +1024,40 @@
 	return(TRUE);
 }
 
-
+/**************************************************************************
+* 				waveOutOpen			[MMSYSTEM.404]
+*/
 UINT WINAPI waveOutOpen(HWAVEOUT FAR* lphWaveOut, UINT uDeviceID,
-    const WAVEFORMAT FAR* lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
+    const LPWAVEFORMAT lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
 {
-	printf("waveOutOpen\n");
+	printf("waveOutOpen(%08X, %d, %08X, %08X, %08X, %08X);\n", 
+		lphWaveOut, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
+	if (dwFlags & WAVE_FORMAT_QUERY) {
+		printf("waveOutOpen	// WAVE_FORMAT_QUERY !\n");
+		if (uDeviceID == (UINT)WAVE_MAPPER) {
+			printf("waveOutOpen	// No WAVE_MAPPER supported yet !\n");
+			return MMSYSERR_BADDEVICEID;
+			}
+		}
+	if (lpFormat == NULL) return WAVERR_BADFORMAT;
 	if (lphWaveOut != NULL) *lphWaveOut = 0;
-	return MMSYSERR_BADDEVICEID;
+	if (lphWaveOut != NULL) *lphWaveOut = ++mciActiveDev;
+	return 0;
+/*	return MMSYSERR_BADDEVICEID;*/
 }
 
-
-
+/**************************************************************************
+* 				waveOutClose		[MMSYSTEM.405]
+*/
 UINT WINAPI waveOutClose(HWAVEOUT hWaveOut)
 {
 	printf("waveOutClose\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
+/**************************************************************************
+* 				waveOutPrepareHeader	[MMSYSTEM.406]
+*/
 UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut,
      WAVEHDR FAR* lpWaveOutHdr, UINT uSize)
 {
@@ -965,8 +1065,9 @@
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
+/**************************************************************************
+* 				waveOutUnprepareHeader	[MMSYSTEM.407]
+*/
 UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut,
     WAVEHDR FAR* lpWaveOutHdr, UINT uSize)
 {
@@ -974,115 +1075,144 @@
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
+/**************************************************************************
+* 				waveOutWrite		[MMSYSTEM.408]
+*/
 UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, WAVEHDR FAR* lpWaveOutHdr,  UINT uSize)
 {
 	printf("waveOutWrite\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
+/**************************************************************************
+* 				waveOutPause		[MMSYSTEM.409]
+*/
 UINT WINAPI waveOutPause(HWAVEOUT hWaveOut)
 {
 	printf("waveOutPause\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
+/**************************************************************************
+* 				waveOutRestart		[MMSYSTEM.410]
+*/
 UINT WINAPI waveOutRestart(HWAVEOUT hWaveOut)
 {
 	printf("waveOutRestart\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
+/**************************************************************************
+* 				waveOutReset		[MMSYSTEM.411]
+*/
 UINT WINAPI waveOutReset(HWAVEOUT hWaveOut)
 {
 	printf("waveOutReset\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
+/**************************************************************************
+* 				waveOutGetPosition	[MMSYSTEM.412]
+*/
 UINT WINAPI waveOutGetPosition(HWAVEOUT hWaveOut, MMTIME FAR* lpInfo, UINT uSize)
 {
 	printf("waveOutGetPosition\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
-UINT WINAPI waveOutGetVolume(UINT uDeviceID, DWORD FAR* lpdwVolume)
-{
-	printf("waveOutGetVolume\n");
-	return MMSYSERR_INVALHANDLE;
-}
-
-
-UINT WINAPI waveOutSetVolume(UINT uDeviceID, DWORD dwVolume)
-{
-	printf("waveOutSetVolume\n");
-	return MMSYSERR_INVALHANDLE;
-}
-
-
-
-UINT WINAPI waveOutGetID(HWAVEOUT hWaveOut, UINT FAR* lpuDeviceID)
-{
-	printf("waveOutGetID\n");
-	return MMSYSERR_INVALHANDLE;
-}
-
-
-
+/**************************************************************************
+* 				waveOutGetPitch		[MMSYSTEM.413]
+*/
 UINT WINAPI waveOutGetPitch(HWAVEOUT hWaveOut, DWORD FAR* lpdwPitch)
 {
 	printf("waveOutGetPitch\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
+/**************************************************************************
+* 				waveOutSetPitch		[MMSYSTEM.414]
+*/
 UINT WINAPI waveOutSetPitch(HWAVEOUT hWaveOut, DWORD dwPitch)
 {
 	printf("waveOutSetPitch\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
+/**************************************************************************
+* 				waveOutGetVolume	[MMSYSTEM.415]
+*/
+UINT WINAPI waveOutGetVolume(UINT uDeviceID, DWORD FAR* lpdwVolume)
+{
+	printf("waveOutGetVolume\n");
+	return MMSYSERR_INVALHANDLE;
+}
 
+/**************************************************************************
+* 				waveOutSetVolume	[MMSYSTEM.416]
+*/
+UINT WINAPI waveOutSetVolume(UINT uDeviceID, DWORD dwVolume)
+{
+	printf("waveOutSetVolume\n");
+	return MMSYSERR_INVALHANDLE;
+}
+
+/**************************************************************************
+* 				waveOutGetPlaybackRate	[MMSYSTEM.417]
+*/
 UINT WINAPI waveOutGetPlaybackRate(HWAVEOUT hWaveOut, DWORD FAR* lpdwRate)
 {
 	printf("waveOutGetPlaybackRate\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
+/**************************************************************************
+* 				waveOutSetPlaybackRate	[MMSYSTEM.418]
+*/
 UINT WINAPI waveOutSetPlaybackRate(HWAVEOUT hWaveOut, DWORD dwRate)
 {
 	printf("waveOutSetPlaybackRate\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
-
+/**************************************************************************
+* 				waveOutBreakLoop 	[MMSYSTEM.419]
+*/
 UINT WINAPI waveOutBreakLoop(HWAVEOUT hWaveOut)
 {
 	printf("waveOutBreakLoop\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
+/**************************************************************************
+* 				waveOutGetID	 	[MMSYSTEM.420]
+*/
+UINT WINAPI waveOutGetID(HWAVEOUT hWaveOut, UINT FAR* lpuDeviceID)
+{
+	printf("waveOutGetID\n");
+	return MMSYSERR_INVALHANDLE;
+}
 
+/**************************************************************************
+* 				waveOutMessage 		[MMSYSTEM.421]
+*/
+DWORD WINAPI waveOutMessage(HWAVEOUT hWaveOut, UINT uMessage, 
+							DWORD dwParam1, DWORD dwParam2)
+{
+}
 
+/**************************************************************************
+* 				waveInGetNumDevs 		[MMSYSTEM.501]
+*/
 UINT WINAPI waveInGetNumDevs()
 {
-/*	printf("waveInGetNumDevs\n"); */
+	printf("waveInGetNumDevs\n");
 	return 0;
 }
 
 
+/**************************************************************************
+* 				waveInGetDevCaps 		[MMSYSTEM.502]
+*/
 UINT WINAPI waveInGetDevCaps(UINT uDeviceID, WAVEINCAPS FAR* lpCaps, UINT uSize)
 {
 	printf("waveInGetDevCaps\n");
@@ -1104,10 +1234,19 @@
 * 				waveInOpen			[MMSYSTEM.504]
 */
 UINT WINAPI waveInOpen(HWAVEIN FAR* lphWaveIn, UINT uDeviceID,
-    const WAVEFORMAT FAR* lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
+    const LPWAVEFORMAT lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
 {
-	printf("waveInOpen\n");
+	printf("waveInOpen(%08X, %d, %08X, %08X, %08X, %08X);\n", 
+		lphWaveIn, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
+	if (dwFlags & WAVE_FORMAT_QUERY) {
+		printf("waveInOpen	// WAVE_FORMAT_QUERY !\n");
+		if (uDeviceID == (UINT)WAVE_MAPPER) {
+			printf("waveInOpen	// No WAVE_MAPPER supported yet !\n");
+			return MMSYSERR_BADDEVICEID;
+			}
+		}
 	if (lphWaveIn != NULL) *lphWaveIn = 0;
+	if (lpFormat == NULL) return WAVERR_BADFORMAT;
 	return MMSYSERR_BADDEVICEID;
 }
 
@@ -1207,6 +1346,16 @@
 
 
 /**************************************************************************
+* 				waveInMessage 		[MMSYSTEM.514]
+*/
+DWORD WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage,
+							DWORD dwParam1, DWORD dwParam2)
+{
+}
+
+
+
+/**************************************************************************
 * 				mmioOpen			[MMSYSTEM.1210]
 */
 HMMIO WINAPI mmioOpen(LPSTR szFileName, MMIOINFO FAR* lpmmioinfo, DWORD dwOpenFlags)
@@ -1248,7 +1397,6 @@
 	return 0;
 }
 
-
 /**************************************************************************
 * 				mmioSeek			[MMSYSTEM.1214]
 */
@@ -1258,7 +1406,6 @@
 	return 0;
 }
 
-
 /**************************************************************************
 * 				mmioGetInfo			[MMSYSTEM.1215]
 */
@@ -1268,7 +1415,6 @@
 	return 0;
 }
 
-
 /**************************************************************************
 * 				mmioGetInfo			[MMSYSTEM.1216]
 */
@@ -1278,45 +1424,139 @@
 	return 0;
 }
 
-
-/*
-#1100   pascal  DRVOPEN
-#1101   pascal  DRVCLOSE
-#1102   pascal  DRVSENDMESSAGE
-#1103   pascal  DRVGETMODULEHANDLE
-#1104   pascal  DRVDEFDRIVERPROC
-UINT WINAPI mciGetDeviceIDFromElementID (DWORD dwElementID,
-    LPCSTR lpstrType);
-
-BOOL WINAPI mciSetYieldProc (UINT uDeviceID, YIELDPROC fpYieldProc,
-    DWORD dwYieldData);
-
-HTASK WINAPI mciGetCreatorTask(UINT uDeviceID);
-YIELDPROC WINAPI mciGetYieldProc (UINT uDeviceID, DWORD FAR* lpdwYieldData);
-
-
-FOURCC WINAPI mmioStringToFOURCC(LPCSTR sz, UINT uFlags);
-LPMMIOPROC WINAPI mmioInstallIOProc(FOURCC fccIOProc, LPMMIOPROC pIOProc,
-    DWORD dwFlags);
-UINT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer,
-    UINT uFlags);
-UINT WINAPI mmioFlush(HMMIO hmmio, UINT uFlags);
-UINT WINAPI mmioAdvance(HMMIO hmmio, MMIOINFO FAR* lpmmioinfo, UINT uFlags);
-LRESULT WINAPI mmioSendMessage(HMMIO hmmio, UINT uMessage,
-    LPARAM lParam1, LPARAM lParam2);
-UINT WINAPI mmioDescend(HMMIO hmmio, MMCKINFO FAR* lpck,
-    const MMCKINFO FAR* lpckParent, UINT uFlags);
-UINT WINAPI mmioAscend(HMMIO hmmio, MMCKINFO FAR* lpck, UINT uFlags);
-UINT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO FAR* lpck, UINT uFlags);
-
-DWORD WINAPI midiInMessage(HMIDIIN hMidiIn, UINT uMessage, DWORD dw1, DWORD dw2);
-
-
-DWORD WINAPI waveOutMessage(HWAVEOUT hWaveOut, UINT uMessage, DWORD dw1, DWORD dw2);
-
-UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn,
-    WAVEHDR FAR* lpWaveInHdr, UINT uSize);
-DWORD WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage, DWORD dw1, DWORD dw2);
-
+/**************************************************************************
+* 				mmioSetBuffer		[MMSYSTEM.1217]
 */
+UINT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer, 
+						LONG cchBuffer, UINT uFlags)
+{
+	printf("mmioSetBuffer\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioFlush			[MMSYSTEM.1218]
+*/
+UINT WINAPI mmioFlush(HMMIO hmmio, UINT uFlags)
+{
+	printf("mmioFlush\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioAdvance			[MMSYSTEM.1219]
+*/
+UINT WINAPI mmioAdvance(HMMIO hmmio, MMIOINFO FAR* lpmmioinfo, UINT uFlags)
+{
+	printf("mmioAdvance\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioStringToFOURCC	[MMSYSTEM.1220]
+*/
+FOURCC WINAPI mmioStringToFOURCC(LPCSTR sz, UINT uFlags)
+{
+	printf("mmioStringToFOURCC\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioInstallIOProc	[MMSYSTEM.1221]
+*/
+LPMMIOPROC WINAPI mmioInstallIOProc(FOURCC fccIOProc, 
+				LPMMIOPROC pIOProc, DWORD dwFlags)
+{
+	printf("mmioInstallIOProc\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioSendMessage		[MMSYSTEM.1222]
+*/
+LRESULT WINAPI mmioSendMessage(HMMIO hmmio, UINT uMessage,
+					    LPARAM lParam1, LPARAM lParam2)
+{
+	printf("mmioSendMessage\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioDescend			[MMSYSTEM.1223]
+*/
+UINT WINAPI mmioDescend(HMMIO hmmio, MMCKINFO FAR* lpck,
+		    const MMCKINFO FAR* lpckParent, UINT uFlags)
+{
+	printf("mmioDescend\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioAscend			[MMSYSTEM.1224]
+*/
+UINT WINAPI mmioAscend(HMMIO hmmio, MMCKINFO FAR* lpck, UINT uFlags)
+{
+	printf("mmioAscend\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioCreateChunk		[MMSYSTEM.1225]
+*/
+UINT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO FAR* lpck, UINT uFlags)
+{
+	printf("mmioCreateChunk\n");
+	return 0;
+}
+
+
+/**************************************************************************
+* 				DrvOpen				[MMSYSTEM.1100]
+*/
+HDRVR DrvOpen(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
+{
+	printf("DrvOpen('%s', '%s', %08X);\n",
+		lpDriverName, lpSectionName, lParam);
+	return OpenDriver(lpDriverName, lpSectionName, lParam);
+}
+
+
+/**************************************************************************
+* 				DrvClose			[MMSYSTEM.1101]
+*/
+LRESULT DrvClose(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
+{
+	printf("DrvClose(%04X, %08X, %08X);\n", hDrvr, lParam1, lParam2);
+	return CloseDriver(hDrvr, lParam1, lParam2);
+}
+
+
+/**************************************************************************
+* 				DrvSendMessage		[MMSYSTEM.1102]
+*/
+LRESULT WINAPI DrvSendMessage(HDRVR hDriver, WORD msg, LPARAM lParam1, LPARAM lParam2)
+{
+	printf("DrvSendMessage(%04X, %04X, %08X, %08X);\n",
+					hDriver, msg, lParam1, lParam2);
+}
+
+/**************************************************************************
+* 				DrvGetModuleHandle	[MMSYSTEM.1103]
+*/
+HANDLE DrvGetModuleHandle(HDRVR hDrvr)
+{
+	printf("DrvGetModuleHandle(%04X);\n", hDrvr);
+}
+
+
+/**************************************************************************
+* 				DrvDefDriverProc	[MMSYSTEM.1104]
+*/
+LRESULT DrvDefDriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
+						DWORD dwParam1, DWORD dwParam2)
+{
+	return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
+}
+
+
 
diff --git a/misc/profile.c b/misc/profile.c
index 3fac219..29e6508 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -220,6 +220,10 @@
     TSecHeader *section;
     TKeys      *key;
     
+    /* Supposedly Default should NEVER be NULL.  But sometimes it is.  */
+    if (Default == NULL)
+	Default = "";
+
     if (!(section = is_loaded (FileName))){
 	New = (TProfile *) xmalloc (sizeof (TProfile));
 	New->link = Base;
@@ -237,16 +241,31 @@
 	/* If no key value given, then list all the keys */
 	if ((!KeyName) && (!set)){
 	    char *p = ReturnedString;
-	    int left = Size - 1;
+	    int left = Size - 2;
 	    int slen;
-	    
+#ifdef DEBUG_PROFILE
+		printf("GetSetProfile // KeyName == NULL, Enumeration !\n");
+#endif
 	    for (key = section->Keys; key; key = key->link){
-		strncpy (p, key->KeyName, left);
-		slen = strlen (key->KeyName) + 1;
-		left -= slen+1;
+		if (left < 1) {
+			printf("GetSetProfile // No more storage for enum !\n");
+			return (Size - 2);
+			}
+		slen = min(strlen(key->KeyName) + 1, left);
+#ifdef DEBUG_PROFILE
+		printf("GetSetProfile // strncpy(%08X, %08X, %d);\n", 
+				ReturnedString, key->Value, slen);
+#endif
+		strncpy (p, key->KeyName, slen);
+#ifdef DEBUG_PROFILE
+		printf("GetSetProfile // enum '%s' !\n", p);
+#endif
+		left -= slen;
 		p += slen;
 	    }
-	    return left;
+		*p = '\0';
+		printf("GetSetProfile // normal end of enum !\n");
+	    return (Size - 2 - left);
 	}
 	for (key = section->Keys; key; key = key->link){
 	    if (strcasecmp (key->KeyName, KeyName))
@@ -291,7 +310,11 @@
 			       short Size, LPSTR FileName)
 {
     int v;
-    
+
+#ifdef DEBUG_PROFILE
+	printf("GetPrivateProfileString ('%s', '%s', '%s', %08X, %d, %s\n", 
+			AppName, KeyName, Default, ReturnedString, Size, FileName);
+#endif
     v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
     if (AppName)
 	return strlen (ReturnedString);
diff --git a/misc/shell.c b/misc/shell.c
index 779c595..19977ca 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -1,14 +1,19 @@
 /*
  * 				Shell Library Functions
  */
-
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include "windows.h"
+#include "shell.h"
 
-typedef DWORD HKEY;
+/*
+#define DEBUG_REG
+*/
+
+LPKEYSTRUCT	lphRootKey = NULL;
+
 typedef FAR LONG *LPWORD;
 DECLARE_HANDLE(HDROP);
 
@@ -17,63 +22,270 @@
 /*************************************************************************
  *				RegOpenKey		[SHELL.1]
  */
-LONG RegOpenKey(HKEY k, LPCSTR s, HKEY FAR *p)
+LONG RegOpenKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
 {
-	fprintf(stderr, "RegOpenKey : Empty Stub !!!\n");
+	LPKEYSTRUCT	lpKey = lphRootKey;
+	LPSTR		ptr;
+	char		str[128];
+	int			size;
+#ifdef DEBUG_REG
+	fprintf(stderr, "RegOpenKey(%04X, %08X='%s', %08X)\n",
+						hKey, lpSubKey, lpSubKey, lphKey);
+#endif
+	if (lpKey == NULL) return ERROR_BADKEY;
+	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
+	if (lphKey == NULL) return ERROR_INVALID_PARAMETER;
+	if (hKey != HKEY_CLASSES_ROOT) {
+#ifdef DEBUG_REG
+		printf("RegOpenKey // specific key = %04X !\n", hKey);
+#endif
+		lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
+		}
+	while ( (ptr = strchr(lpSubKey, '\\')) != NULL ) {
+		strncpy(str, lpSubKey, (LONG)ptr - (LONG)lpSubKey);
+		str[(LONG)ptr - (LONG)lpSubKey] = '\0';
+		lpSubKey = ptr + 1;
+#ifdef DEBUG_REG
+		printf("RegOpenKey // next level '%s' !\n", str);
+#endif
+		while(TRUE) {
+#ifdef DEBUG_REG
+			printf("RegOpenKey // '%s' <-> '%s' !\n", str, lpKey->lpSubKey);
+#endif
+			if (lpKey->lpSubKey != NULL && lpKey->lpSubKey[0] != '\0' &&
+				strcmp(lpKey->lpSubKey, str) == 0) {
+				lpKey = lpKey->lpSubLvl;
+				if (lpKey == NULL) {
+					printf("RegOpenKey // can't find subkey '%s' !\n", str);
+					return ERROR_BADKEY;
+					}
+				break;
+				}
+			if (lpKey->lpNextKey == NULL) {
+				printf("RegOpenKey // can't find subkey '%s' !\n", str);
+				return ERROR_BADKEY;
+				}
+			lpKey = lpKey->lpNextKey;
+			}
+		}
+	while(TRUE) {
+		if (lpKey->lpSubKey != NULL && 
+			strcmp(lpKey->lpSubKey, lpSubKey) == 0)	break;
+		if (lpKey->lpNextKey == NULL) {
+			printf("RegOpenKey // can't find subkey '%s' !\n", str);
+			return ERROR_BADKEY;
+			}
+		lpKey = lpKey->lpNextKey;
+		}
+	*lphKey = lpKey->hKey;
+#ifdef DEBUG_REG
+	printf("RegOpenKey // return hKey=%04X !\n", lpKey->hKey);
+#endif
+	return ERROR_SUCCESS;
 }
 
 
 /*************************************************************************
  *				RegCreateKey		[SHELL.2]
  */
-LONG RegCreateKey(HKEY k, LPCSTR s, HKEY FAR *p)
+LONG RegCreateKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
 {
-	fprintf(stderr, "RegCreateKey : Empty Stub !!!\n");
+	HKEY		hNewKey;
+	LPKEYSTRUCT	lpNewKey;
+	LPKEYSTRUCT	lpKey = lphRootKey;
+	LPKEYSTRUCT	lpPrevKey;
+	LONG		dwRet;
+	LPSTR		ptr;
+	char		str[128];
+#ifdef DEBUG_REG
+	fprintf(stderr, "RegCreateKey(%04X, '%s', %08X)\n",	hKey, lpSubKey, lphKey);
+#endif
+	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
+	if (lphKey == NULL) return ERROR_INVALID_PARAMETER;
+	if (hKey != HKEY_CLASSES_ROOT) {
+#ifdef DEBUG_REG
+		printf("RegCreateKey // specific key = %04X !\n", hKey);
+#endif
+		lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
+		}
+	while ( (ptr = strchr(lpSubKey, '\\')) != NULL ) {
+		strncpy(str, lpSubKey, (LONG)ptr - (LONG)lpSubKey);
+		str[(LONG)ptr - (LONG)lpSubKey] = '\0';
+		lpSubKey = ptr + 1;
+#ifdef DEBUG_REG
+		printf("RegCreateKey // next level '%s' !\n", str);
+#endif
+		lpPrevKey = lpKey;
+		while(TRUE) {
+#ifdef DEBUG_REG
+			printf("RegCreateKey // '%s' <-> '%s' !\n", str, lpKey->lpSubKey);
+#endif
+			if (lpKey->lpSubKey != NULL &&
+				strcmp(lpKey->lpSubKey, str) == 0) {
+				if (lpKey->lpSubLvl == NULL) {
+#ifdef DEBUG_REG
+					printf("RegCreateKey // '%s' found !\n", str);
+#endif
+					if ( (ptr = strchr(lpSubKey, '\\')) != NULL ) {
+						strncpy(str, lpSubKey, (LONG)ptr - (LONG)lpSubKey);
+						str[(LONG)ptr - (LONG)lpSubKey] = '\0';
+						lpSubKey = ptr + 1;
+						}
+					else
+						strcpy(str, lpSubKey);
+					dwRet = RegCreateKey(lpKey->hKey, str, &hNewKey);
+					if (dwRet != ERROR_SUCCESS) {
+						printf("RegCreateKey // can't create subkey '%s' !\n", str);
+						return dwRet;
+						}
+					lpKey->lpSubLvl = (LPKEYSTRUCT)GlobalLock(hNewKey);
+					}
+				lpKey = lpKey->lpSubLvl;
+				break;
+				}
+			if (lpKey->lpNextKey == NULL) {
+				dwRet = RegCreateKey(lpPrevKey->hKey, str, &hNewKey);
+				if (dwRet != ERROR_SUCCESS) {
+					printf("RegCreateKey // can't create subkey '%s' !\n", str);
+					return dwRet;
+					}
+				lpKey = (LPKEYSTRUCT)GlobalLock(hNewKey);
+				break;
+				}
+			lpKey = lpKey->lpNextKey;
+			}
+		}
+	hNewKey = GlobalAlloc(GMEM_MOVEABLE, sizeof(KEYSTRUCT));
+	lpNewKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
+	if (lpNewKey == NULL) {
+		printf("RegCreateKey // Can't alloc new key !\n");
+		return ERROR_OUTOFMEMORY;
+		}
+	if (lphRootKey == NULL) {
+		lphRootKey = lpNewKey;
+		lpNewKey->lpPrevKey = NULL;
+		}
+	else {
+		lpKey->lpNextKey = lpNewKey;
+		lpNewKey->lpPrevKey = lpKey;
+		}
+	lpNewKey->hKey = hNewKey;
+	lpNewKey->lpSubKey = malloc(strlen(lpSubKey) + 1);
+	if (lpNewKey->lpSubKey == NULL) {
+		printf("RegCreateKey // Can't alloc key string !\n");
+		return ERROR_OUTOFMEMORY;
+		}
+	strcpy(lpNewKey->lpSubKey, lpSubKey);
+	lpNewKey->dwType = 0;
+	lpNewKey->lpValue = NULL;
+	lpNewKey->lpNextKey = NULL;
+	lpNewKey->lpSubLvl = NULL;
+	*lphKey = hNewKey;
+#ifdef DEBUG_REG
+	printf("RegCreateKey // successful '%s' key=%04X !\n", lpSubKey, hNewKey);
+#endif
+	return ERROR_SUCCESS;
 }
 
 
 /*************************************************************************
  *				RegCloseKey		[SHELL.3]
  */
-LONG RegCloseKey(HKEY k)
+LONG RegCloseKey(HKEY hKey)
 {
-	fprintf(stderr, "RegCloseKey : Empty Stub !!!\n");
+	fprintf(stderr, "EMPTY STUB !!! RegCloseKey(%04X);\n", hKey);
+	return ERROR_INVALID_PARAMETER;
 }
 
 
 /*************************************************************************
  *				RegDeleteKey		[SHELL.4]
  */
-LONG RegDeleteKey(HKEY k, LPCSTR s)
+LONG RegDeleteKey(HKEY hKey, LPCSTR lpSubKey)
 {
-	fprintf(stderr, "RegDeleteKey : Empty Stub !!!\n");
+	fprintf(stderr, "EMPTY STUB !!! RegDeleteKey(%04X, '%s');\n", 
+												hKey, lpSubKey);
+	return ERROR_INVALID_PARAMETER;
 }
 
 
 /*************************************************************************
  *				RegSetValue		[SHELL.5]
  */
-LONG RegSetValue(HKEY k, LPCSTR s1, DWORD dw, LPCSTR s2, DWORD dw2)
+LONG RegSetValue(HKEY hKey, LPCSTR lpSubKey, DWORD dwType, 
+					LPCSTR lpVal, DWORD dwIgnored)
 {
-	fprintf(stderr, "RegSetValue : Empty Stub !!!\n");
+	HKEY		hRetKey;
+	LPKEYSTRUCT	lpKey;
+	LONG		dwRet;
+#ifdef DEBUG_REG
+	fprintf(stderr, "RegSetValue(%04X, '%s', %08X, '%s', %08X);\n",
+						hKey, lpSubKey, dwType, lpVal, dwIgnored);
+#endif
+	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
+	if (lpVal == NULL) return ERROR_INVALID_PARAMETER;
+	if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
+#ifdef DEBUG_REG
+		fprintf(stderr, "RegSetValue // key not found ... so create it !\n");
+#endif
+		if ((dwRet = RegCreateKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
+			fprintf(stderr, "RegSetValue // key creation error %04X !\n", dwRet);
+			return dwRet;
+			}
+		}
+	lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
+	if (lpKey == NULL) return ERROR_BADKEY;
+	if (lpKey->lpValue != NULL) free(lpKey->lpValue);
+	lpKey->lpValue = malloc(strlen(lpVal) + 1);
+	strcpy(lpKey->lpValue, lpVal);
+#ifdef DEBUG_REG
+	printf("RegSetValue // successful key='%s' val='%s' !\n", lpSubKey, lpVal);
+#endif
+	return ERROR_SUCCESS;
 }
 
 
 /*************************************************************************
  *				RegQueryValue		[SHELL.6]
  */
-LONG RegQueryValue(HKEY k, LPCSTR s, LPSTR s2, LONG FAR *p)
+LONG RegQueryValue(HKEY hKey, LPCSTR lpSubKey, LPSTR lpVal, LONG FAR *lpcb)
 {
-	fprintf(stderr, "RegQueryValue : Empty Stub !!!\n");
+	HKEY		hRetKey;
+	LPKEYSTRUCT	lpKey;
+	LONG		dwRet;
+	int			size;
+	fprintf(stderr, "RegQueryValue(%04X, '%s', %08X, %08X);\n",
+							hKey, lpSubKey, lpVal, lpcb);
+	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
+	if (lpVal == NULL) return ERROR_INVALID_PARAMETER;
+	if (lpcb == NULL) return ERROR_INVALID_PARAMETER;
+	if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
+		fprintf(stderr, "RegQueryValue // key not found !\n");
+		return dwRet;
+		}
+	lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
+	if (lpKey == NULL) return ERROR_BADKEY;
+	if (lpKey->lpValue != NULL) {
+		size = min(strlen(lpKey->lpValue), *lpcb);
+		strncpy(lpVal, lpKey->lpValue, size);
+		*lpcb = (LONG)size;
+		}
+	else {
+		lpVal[0] = '\0';
+		*lpcb = (LONG)0;
+		}
+	printf("RegQueryValue // return '%s' !\n", lpVal);
+	return ERROR_SUCCESS;
 }
 
 
 /*************************************************************************
  *				RegEnumKey		[SHELL.7]
  */
-LONG RegEnumKey(HKEY k, DWORD dw, LPSTR s, DWORD dw2)
+LONG RegEnumKey(HKEY hKey, DWORD dwSubKey, LPSTR lpBuf, DWORD dwSize)
 {
 	fprintf(stderr, "RegEnumKey : Empty Stub !!!\n");
+	return ERROR_INVALID_PARAMETER;
 }
 
 /*************************************************************************
@@ -118,9 +330,15 @@
 /*************************************************************************
  *				ShellExecute		[SHELL.20]
  */
-HINSTANCE ShellExecute(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, int iShowCmd)
+HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, int iShowCmd)
 {
-	fprintf(stderr, "ShellExecute : Empty Stub !!!\n");
+	fprintf(stderr, "ShellExecute // hWnd=%04X\n", hWnd);
+	fprintf(stderr, "ShellExecute // lpOperation='%s'\n", lpOperation);
+	fprintf(stderr, "ShellExecute // lpFile='%s'\n", lpFile);
+	fprintf(stderr, "ShellExecute // lpParameters='%s'\n", lpParameters);
+	fprintf(stderr, "ShellExecute // lpDirectory='%s'\n", lpDirectory);
+	fprintf(stderr, "ShellExecute // iShowCmd=%04X\n", iShowCmd);
+	return 2; /* file not found */
 }
 
 
@@ -198,6 +416,7 @@
 int RegisterShellHook(void *ptr) 
 {
 	fprintf(stderr, "RegisterShellHook : Empty Stub !!!\n");
+	return 0;
 }
 
 
diff --git a/misc/winsocket.c b/misc/winsocket.c
index 4d9d5c0..cd7fb53 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -878,7 +878,9 @@
 	return WSASYSNOTREADY;
 
     heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
+#ifndef WINELIB
     HEAP_Init(&MyHeap, heap, sizeof(struct WinSockHeap));
+#endif
     bcopy(&Winsock_data, lpWSAData, sizeof(Winsock_data));
 
     /* ipc stuff */
diff --git a/miscemu/int21.c b/miscemu/int21.c
index cefe3ae..865bd49 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -15,6 +15,8 @@
 #include "msdos.h"
 #include "options.h"
 
+/* #define DEBUG_FIND /* */
+
 static char Copyright[] = "copyright Erik Bos, 1993";
 
 WORD ExtendedError, CodePage = 437;
@@ -366,20 +368,34 @@
 
 static void ioctlGetDeviceInfo(struct sigcontext_struct *context)
 {
-	WORD handle = EBX & 0xffff;
-
-	switch (handle) {
-		case 0:
-		case 1:
-		case 2:
-			EDX = (EDX & 0xffff0000) | 0x80d3;
-			break;
-
-		default:
-			Barf(context);
-			EDX = (EDX & 0xffff0000) | 0x50;
+    WORD handle = EBX & 0xffff;
+    
+    switch (handle) 
+    {
+      case 0:
+      case 1:
+      case 2:
+	EDX = (EDX & 0xffff0000) | 0x80d3;
+	break;
+	
+      default:
+	{
+	    struct stat sbuf;
+	    
+	    if (fstat(handle, &sbuf) < 0)
+	    {
+		Barf(context);
+		EDX = (EDX & 0xffff0000) | 0x50;
+		SetCflag;
+		return;
+	    }
+	    
+	    /* This isn't the right answer, but should be close enough. */
+	    EDX = (EDX & 0xffff0000) | 0x0943;
 	}
-	ResetCflag;
+    }
+    
+    ResetCflag;
 }
 
 static void ioctlGenericBlkDevReq(struct sigcontext_struct *context)
@@ -542,8 +558,7 @@
 		return;
 	}		
 	Error (0,0,0);
-	EBX = (EBX & 0xffff0000L) | handle;
-	EAX = (EAX & 0xffffff00L) | NoError;
+	EAX = (EAX & 0xffff0000L) | handle;
 	ResetCflag;
 }
 
@@ -705,13 +720,20 @@
 {
 	struct dosdirent *dp;
 	
-	dp = (struct dosdirent *)(dta + 0x0d);
+#ifdef DEBUG_FIND
+	fprintf(stderr, "FindNext: ");
+#endif
+	
+	dp = *(struct dosdirent **)(dta + 0x0d);
 
 	do {
 		if ((dp = DOS_readdir(dp)) == NULL) {
 			Error(NoMoreFiles, EC_MediaError , EL_Disk);
 			EAX = (EAX & 0xffffff00L) | NoMoreFiles;
 			SetCflag;
+#ifdef DEBUG_FIND
+			fprintf(stderr, "\n");
+#endif
 			return;
 		}
 	} while (*(dta + 0x0c) != dp->attribute);
@@ -723,6 +745,12 @@
 
 	EAX = (EAX & 0xffffff00L);
 	ResetCflag;
+
+#ifdef DEBUG_FIND
+	fprintf(stderr, 
+		"DTA: drive %c, template %11.11s, size %d, name %-13.13s\n",
+		dta[0] + 'A', &dta[1], *(LONG *)(&dta[0x1a]), &dta[0x1e]);
+#endif
 	return;
 }
 
@@ -764,13 +792,8 @@
 		SetCflag;
 		return;
 	}
-/*	strncpy(dta + 1, AsciizToFCB(dp->filemask), 11); */
 
-/*	*((BYTE *) ((void*)dta + 0x0d)) = (BYTE *) dp; */
-
-	*((struct dosdirent *)(dta + 0x0d))
-	 =
-	  *dp;
+	memcpy(dta + 0x0d, &dp, sizeof(dp));
 	FindNext(context);
 }
 
diff --git a/objects/bitblt.c b/objects/bitblt.c
index 4302362..c90b9e2 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -12,6 +12,7 @@
 #include <X11/Intrinsic.h>
 
 #include "gdi.h"
+#include "metafile.h"
 
 extern const int DC_XROPfunction[];
 
@@ -28,7 +29,15 @@
     int x1, x2, y1, y2;
     
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return FALSE;
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam6(dc, META_PATBLT, left, top, width, height,
+		      HIWORD(rop), LOWORD(rop));
+	return TRUE;
+    }
+
 #ifdef DEBUG_GDI
     printf( "PatBlt: %d %d,%d %dx%d %06x\n",
 	    hdc, left, top, width, height, rop );
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 38fabec..6e8c1b0 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -251,6 +251,16 @@
     return prevHandle;
 }
 
+/***********************************************************************
+ *           CreateDiscardableBitmap    (GDI.156)
+ */
+HBITMAP CreateDiscardableBitmap(HDC hdc, short width, short height)
+{
+    printf("CreateDiscardableBitmap(%04X, %d, %d); "
+	   "// call CreateCompatibleBitmap() for now!\n",
+	   hdc, width, height);
+    return CreateCompatibleBitmap(hdc, width, height);
+}
 
 /***********************************************************************
  *           GetBitmapDimensionEx    (GDI.468)
diff --git a/objects/brush.c b/objects/brush.c
index 563617f..a12c455 100644
--- a/objects/brush.c
+++ b/objects/brush.c
@@ -237,13 +237,13 @@
 	case BS_SOLID:
 	case BS_HATCHED:
 	case BS_HOLLOW:
-	    if (!MF_CreateBrushIndirect(dc, &(brush->logbrush)))
+	    if (!MF_CreateBrushIndirect(dc, hbrush, &(brush->logbrush)))
 		return 0;
 	    break;
 
 	case BS_PATTERN:
 	case BS_DIBPATTERN:
-	    if (!MF_CreatePatternBrush(dc, &(brush->logbrush)))
+	    if (!MF_CreatePatternBrush(dc, hbrush, &(brush->logbrush)))
 		return 0;
 	    break;
 	}
diff --git a/objects/clipping.c b/objects/clipping.c
index 7504b12..a5240ff 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -8,6 +8,7 @@
 
 #include <stdio.h>
 #include "gdi.h"
+#include "metafile.h"
 
 
 /***********************************************************************
@@ -131,7 +132,14 @@
 int OffsetClipRgn( HDC hdc, short x, short y )
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return ERROR;    
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return ERROR;
+	MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
+	return NULLREGION;   /* ?? */
+    }
+
 #ifdef DEBUG_CLIPPING
     printf( "OffsetClipRgn: %d %d,%d\n", hdc, x, y );
 #endif
@@ -219,7 +227,14 @@
 		     short right, short bottom )
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return ERROR;    
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return ERROR;
+	MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
+	return NULLREGION;   /* ?? */
+    }
+
 #ifdef DEBUG_CLIPPING
     printf( "ExcludeClipRect: %d %dx%d,%dx%d\n",
 	    hdc, left, top, right, bottom );
@@ -236,7 +251,14 @@
 		       short right, short bottom )
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return ERROR;    
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return ERROR;
+	MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
+	return NULLREGION;   /* ?? */
+    }
+
 #ifdef DEBUG_CLIPPING
     printf( "IntersectClipRect: %d %dx%d,%dx%d\n",
 	    hdc, left, top, right, bottom );
diff --git a/objects/font.c b/objects/font.c
index 6129981..07e4d21 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -663,8 +663,10 @@
 	while (TRUE) {
 		if (lpLogFontList[i] == NULL) break;
 		if (lpszFamily == NULL) {
+			if (lpLogFontList[i] == NULL) break;
 			for (j = 0; j < MAX_FONTS; j++)	{
 				if (lpFaceList[j] == NULL) break;
+				if (lpLogFontList[i] == NULL) break;
 				if (strcmp(lpFaceList[j], lpLogFontList[i]->lfFaceName) == 0) {
 					i++; j = 0;
 					}
diff --git a/objects/metafile.c b/objects/metafile.c
index 903cfa7..5ff49ed 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -13,6 +13,11 @@
 
 #define DEBUG_METAFILE
 
+#define HTINCR  10      /* handle table allocation size increment */
+
+static HANDLE hHT;      /* handle of the handle table */
+static int HTLen;       /* allocated length of handle table */
+
 /******************************************************************
  *         CreateMetafile         GDI.125
  */
@@ -22,6 +27,7 @@
     HANDLE handle;
     METAFILE *mf;
     METAHEADER *mh;
+    HANDLETABLE *ht;
 
 #ifdef DEBUG_METAFILE
     printf("CreateMetaFile: %s\n", lpFilename);
@@ -64,6 +70,12 @@
     else                     /* memory based metafile */
 	mh->mtType = 0;
 
+    /* create the handle table */
+    HTLen = HTINCR;
+    hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 
+		      sizeof(HANDLETABLE) * HTLen);
+    ht = (HANDLETABLE *)GlobalLock(hHT);
+
     GlobalUnlock(mf->hMetaHdr);
     GlobalUnlock(dc->w.hMetaFile);
     return handle;
@@ -94,9 +106,12 @@
     /* Construct the end of metafile record - this is undocumented
      * but is created by MS Windows 3.1.
      */
-    mr->rdSize = 3;
-    mr->rdFunction = META_EOF;
-    MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    if (!MF_MetaParam0(dc, META_EOF))
+    {
+	GlobalFree(mf->hMetaHdr);
+	GlobalFree(dc->w.hMetaFile);
+	return 0;
+    }	
 
     if (mh->mtType == 1)        /* disk based metafile */
     {
@@ -115,8 +130,12 @@
 	_lclose(mf->hFile);
     }
 
+    /* delete the handle table */
+    GlobalFree(hHT);
+
     GlobalUnlock(mf->hMetaHdr);
     hmf = dc->w.hMetaFile;
+    GlobalUnlock(hmf);
     GDI_FreeObject(hdc);
     return hmf;
 }
@@ -139,6 +158,292 @@
 
 
 /******************************************************************
+ *         PlayMetafile         GDI.123
+ */
+BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
+{
+    METAFILE *mf = (METAFILE *)GlobalLock(hmf);
+    METAHEADER *mh;
+    METARECORD *mr;
+    HANDLETABLE *ht;
+    char *buffer;
+
+    if (mf->wMagic != METAFILE_MAGIC)
+	return FALSE;
+
+    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    if (mh->mtType == 1)       /* disk based metafile */
+    {
+	mf->hFile = _lopen(mf->Filename, OF_READ);
+	mf->hBuffer = GlobalAlloc(GMEM_MOVEABLE, mh->mtMaxRecord * 2);
+	buffer = (char *)GlobalLock(mf->hBuffer);
+	_llseek(mf->hFile, mh->mtHeaderSize * 2, 0);
+	mf->MetaOffset = mh->mtHeaderSize * 2;
+    }
+    else if (mh->mtType == 0)   /* memory based metafile */
+	mf->MetaOffset = mh->mtHeaderSize * 2;
+    else                       /* not a valid metafile type */
+	return FALSE;
+
+    /* create the handle table */
+    hHT = GlobalAlloc(GMEM_MOVEABLE, sizeof(HANDLETABLE) * mh->mtNoObjects);
+    ht = (HANDLETABLE *)GlobalLock(hHT);
+
+    /* loop through metafile playing records */
+    while (mf->MetaOffset < mh->mtSize * 2)
+    {
+	if (mh->mtType == 1)   /* disk based metafile */
+	{
+	    _lread(mf->hFile, buffer, sizeof(METARECORD));
+	    mr = (METARECORD *)&buffer;
+	    _lread(mf->hFile, (char *)(mr->rdParam + 1), (mr->rdSize * 2) -
+		                                       sizeof(METARECORD));
+	    mf->MetaOffset += mr->rdSize * 2;
+	}
+	else                   /* memory based metafile */
+	{
+	    mr = (METARECORD *)((char *)mh + mf->MetaOffset);
+	    mf->MetaOffset += mr->rdSize * 2;
+	}
+	PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
+    }
+
+    /* close disk based metafile and free buffer */
+    if (mh->mtType == 1)
+    {
+	GlobalFree(mf->hBuffer);
+	_lclose(mf->hFile);
+    }
+
+    /* free handle table */
+    GlobalFree(hHT);
+
+    return TRUE;
+}
+
+
+/******************************************************************
+ *         PlayMetaFileRecord      GDI.176
+ */
+void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
+			                           WORD nHandles)
+{
+    short s1;
+    HANDLE hndl;
+    char *ptr;
+    BITMAPINFOHEADER *infohdr;
+
+    switch (mr->rdFunction)
+    {
+    case META_SETBKCOLOR:
+	SetBkColor(hdc, *(mr->rdParam));
+	break;
+
+    case META_SETBKMODE:
+	SetBkMode(hdc, *(mr->rdParam));
+	break;
+
+    case META_SETMAPMODE:
+	SetMapMode(hdc, *(mr->rdParam));
+	break;
+
+    case META_SETROP2:
+	SetROP2(hdc, *(mr->rdParam));
+	break;
+
+    case META_SETRELABS:
+	SetRelAbs(hdc, *(mr->rdParam));
+	break;
+
+    case META_SETPOLYFILLMODE:
+	SetPolyFillMode(hdc, *(mr->rdParam));
+	break;
+
+    case META_SETSTRETCHBLTMODE:
+	SetStretchBltMode(hdc, *(mr->rdParam));
+	break;
+
+    case META_SETTEXTCOLOR:
+	SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
+	break;
+
+    case META_SETWINDOWORG:
+	SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_SETWINDOWEXT:
+	SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_SETVIEWPORTORG:
+	SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_SETVIEWPORTEXT:
+	SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_OFFSETWINDOWORG:
+	OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_SCALEWINDOWEXT:
+	ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
+		       *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_OFFSETVIEWPORTORG:
+	OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_SCALEVIEWPORTEXT:
+	ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
+			 *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_LINETO:
+	LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_MOVETO:
+	MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_EXCLUDECLIPRECT:
+	ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
+			*(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_INTERSECTCLIPRECT:
+	IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
+			*(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_ARC:
+	Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
+	    *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
+	    *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_ELLIPSE:
+	Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
+		*(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_FLOODFILL:
+	FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
+		  MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
+	break;
+
+    case META_PIE:
+	Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
+	    *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
+	    *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_RECTANGLE:
+	Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
+		*(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_ROUNDRECT:
+	RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
+		  *(mr->rdParam + 3), *(mr->rdParam + 2),
+		  *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_PATBLT:
+	PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4),
+	       *(mr->rdParam + 3), *(mr->rdParam + 2),
+	       MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
+	break;
+
+    case META_SAVEDC:
+	SaveDC(hdc);
+	break;
+
+    case META_SETPIXEL:
+	SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2),
+		 MAKELONG(*(mr->rdParam + 1), *(mr->rdParam)));
+	break;
+
+    case META_OFFSETCLIPRGN:
+	OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_TEXTOUT:
+	s1 = *(mr->rdParam);
+	TextOut(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2),
+		*(mr->rdParam + ((s1 + 1) >> 1) + 1), 
+		(char *)(mr->rdParam + 1), s1);
+	break;
+
+    case META_POLYGON:
+	Polygon(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_POLYLINE:
+	Polyline(hdc, (LPPOINT)(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_RESTOREDC:
+	RestoreDC(hdc, *(mr->rdParam));
+	break;
+
+    case META_SELECTOBJECT:
+	SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam)));
+	break;
+
+    case META_CHORD:
+	Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5),
+	      *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2),
+	      *(mr->rdParam + 1), *(mr->rdParam));
+	break;
+
+    case META_CREATEPATTERNBRUSH:
+	switch (*(mr->rdParam))
+	{
+	case BS_PATTERN:
+	    infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
+	    MF_AddHandle(ht, nHandles,
+			 CreatePatternBrush(CreateBitmap(infohdr->biWidth, 
+				      infohdr->biHeight, 
+				      infohdr->biPlanes, 
+				      infohdr->biBitCount,
+				      (LPSTR)(mr->rdParam + 
+				      (sizeof(BITMAPINFOHEADER) / 2) + 4))));
+	    break;
+
+	case BS_DIBPATTERN:
+	    s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
+	    hndl = GlobalAlloc(GMEM_MOVEABLE, s1);
+	    ptr = GlobalLock(hndl);
+	    memcpy(ptr, mr->rdParam + 2, s1);
+	    GlobalUnlock(hndl);
+	    MF_AddHandle(ht, nHandles,
+			 CreateDIBPatternBrush(hndl, *(mr->rdParam + 1)));
+	    GlobalFree(hndl);
+	}
+	break;
+	
+    case META_CREATEPENINDIRECT:
+	MF_AddHandle(ht, nHandles, 
+		     CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
+	break;
+
+    case META_CREATEBRUSHINDIRECT:
+	MF_AddHandle(ht, nHandles, 
+		     CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
+	break;
+
+    default:
+	printf("PlayMetaFileRecord: Unknown record type %x\n",
+	                                      mr->rdFunction);
+    }
+}
+
+
+/******************************************************************
  *         MF_WriteRecord
  */
 BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
@@ -177,6 +482,71 @@
 
 
 /******************************************************************
+ *         MF_AddHandle
+ *
+ *    Add a handle to an external handle table and return the index
+ */
+int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
+{
+    int i;
+
+    for (i = 0; i < htlen; i++)
+    {
+	if (*(ht->objectHandle + i) == 0)
+	{
+	    *(ht->objectHandle + i) = hobj;
+	    return i;
+	}
+    }
+    return -1;
+}
+
+
+/******************************************************************
+ *         MF_AddHandleInternal
+ *
+ *    Add a handle to the internal handle table and return the index
+ */
+int MF_AddHandleInternal(HANDLE hobj)
+{
+    int i;
+    HANDLETABLE *ht = (HANDLETABLE *)GlobalLock(hHT);
+
+    for (i = 0; i < HTLen; i++)
+    {
+	if (*(ht->objectHandle + i) == 0)
+	{
+	    *(ht->objectHandle + i) = hobj;
+	    GlobalUnlock(hHT);
+	    return i;
+	}
+    }
+    GlobalUnlock(hHT);
+    if (!(hHT = GlobalReAlloc(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT)))
+	return -1;
+    HTLen += HTINCR;
+    ht = (HANDLETABLE *)GlobalLock(hHT);
+    *(ht->objectHandle + i) = hobj;
+    GlobalUnlock(hHT);
+    return i;
+}
+
+
+/******************************************************************
+ *         MF_MetaParam0
+ */
+BOOL MF_MetaParam0(DC *dc, short func)
+{
+    char buffer[8];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = 3;
+    mr->rdFunction = func;
+    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+}
+
+
+/******************************************************************
  *         MF_MetaParam1
  */
 BOOL MF_MetaParam1(DC *dc, short func, short param1)
@@ -274,16 +644,15 @@
 /******************************************************************
  *         MF_CreateBrushIndirect
  */
-BOOL MF_CreateBrushIndirect(DC *dc, LOGBRUSH *logbrush)
+BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
 {
+    int index;
+    BOOL rc;
     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
     METARECORD *mr = (METARECORD *)&buffer;
-    METAFILE *mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    METAFILE *mf;
+    METAHEADER *mh;
 
-#ifdef DEBUG_METAFILE
-    printf("MF_CreateBrushIndirect\n");
-#endif
     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
     mr->rdFunction = META_CREATEBRUSHINDIRECT;
     memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
@@ -292,24 +661,37 @@
 
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
-    *(mr->rdParam) = mh->mtNoObjects++;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    if ((index = MF_AddHandleInternal(hBrush)) == -1)
+	return FALSE;
+
+    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
+    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    *(mr->rdParam) = index;
+    if (index >= mh->mtNoObjects)
+	mh->mtNoObjects++;
+    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    GlobalUnlock(mf->hMetaHdr);
+    GlobalUnlock(dc->w.hMetaFile);
+    return rc;
 }
 
 
 /******************************************************************
  *         MF_CreatePatternBrush
  */
-BOOL MF_CreatePatternBrush(DC *dc, LOGBRUSH *logbrush)
+BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
 {
     DWORD len, bmSize, biSize;
     HANDLE hmr;
     METARECORD *mr;
     BITMAPOBJ *bmp;
     BITMAPINFO *info;
+    BITMAPINFOHEADER *infohdr;
+    int index;
+    BOOL rc;
     char buffer[sizeof(METARECORD)];
-    METAFILE *mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    METAFILE *mf;
+    METAHEADER *mh;
 
     switch (logbrush->lbStyle)
     {
@@ -317,7 +699,7 @@
 	bmp = (BITMAPOBJ *)GDI_GetObjPtr(logbrush->lbHatch, BITMAP_MAGIC);
 	if (!bmp) return FALSE;
 	len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) + 
-	      (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 2;
+	      (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6;
 	if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
 	    return FALSE;
 	mr = (METARECORD *)GlobalLock(hmr);
@@ -325,7 +707,14 @@
 	mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
 	mr->rdSize = len / 2;
 	*(mr->rdParam) = logbrush->lbStyle;
-	memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 2, 
+	*(mr->rdParam + 1) = DIB_RGB_COLORS;
+	infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2);
+	infohdr->biSize = sizeof(BITMAPINFOHEADER);
+	infohdr->biWidth = bmp->bitmap.bmWidth;
+	infohdr->biHeight = bmp->bitmap.bmHeight;
+	infohdr->biPlanes = bmp->bitmap.bmPlanes;
+	infohdr->biBitCount = bmp->bitmap.bmBitsPixel;
+	memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4,
 	       bmp->bitmap.bmBits, 
 	       bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes);
 	break;
@@ -359,24 +748,33 @@
     mr = (METARECORD *)&buffer;
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
-    (WORD)(*(mr->rdParam)) = mh->mtNoObjects++;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    if ((index = MF_AddHandleInternal(hBrush)) == -1)
+	return FALSE;
+
+    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
+    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    *(mr->rdParam) = index;
+    if (index >= mh->mtNoObjects)
+	mh->mtNoObjects++;
+    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    GlobalUnlock(mf->hMetaHdr);
+    GlobalUnlock(dc->w.hMetaFile);
+    return rc;
 }
 
 
 /******************************************************************
  *         MF_CreatePenIndirect
  */
-BOOL MF_CreatePenIndirect(DC *dc, LOGPEN *logpen)
+BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
 {
+    int index;
+    BOOL rc;
     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
     METARECORD *mr = (METARECORD *)&buffer;
-    METAFILE *mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    METAFILE *mf;
+    METAHEADER *mh;
 
-#ifdef DEBUG_METAFILE
-    printf("MF_CreatePenIndirect\n");
-#endif
     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
     mr->rdFunction = META_CREATEPENINDIRECT;
     memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
@@ -385,8 +783,18 @@
 
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
-    (WORD)(*(mr->rdParam)) = mh->mtNoObjects++;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    if ((index = MF_AddHandleInternal(hPen)) == -1)
+	return FALSE;
+
+    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
+    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    *(mr->rdParam) = index;
+    if (index >= mh->mtNoObjects)
+	mh->mtNoObjects++;
+    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    GlobalUnlock(mf->hMetaHdr);
+    GlobalUnlock(dc->w.hMetaFile);
+    return rc;
 }
 
 
@@ -400,7 +808,7 @@
     HANDLE hmr;
     METARECORD *mr;
 
-    len = sizeof(METARECORD) + count + 4;
+    len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
     if (!(hmr = GlobalAlloc(GMEM_MOVEABLE, len)))
 	return FALSE;
     mr = (METARECORD *)GlobalLock(hmr);
@@ -410,8 +818,8 @@
     mr->rdFunction = META_TEXTOUT;
     *(mr->rdParam) = count;
     memcpy(mr->rdParam + 1, str, count);
-    *(mr->rdParam + (count / 2) + 1) = y;
-    *(mr->rdParam + (count / 2) + 2) = x;
+    *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
+    *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
     rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
     GlobalFree(hmr);
     return rc;
diff --git a/objects/pen.c b/objects/pen.c
index cf3089f..61e1f16 100644
--- a/objects/pen.c
+++ b/objects/pen.c
@@ -64,7 +64,7 @@
     HPEN prevHandle = dc->w.hPen;
 
     if (dc->header.wMagic == METAFILE_DC_MAGIC)
-	return MF_CreatePenIndirect(dc, &(pen->logpen));
+	return MF_CreatePenIndirect(dc, hpen, &(pen->logpen));
 
     dc->w.hPen = hpen;
 
diff --git a/toolkit/sup.c b/toolkit/sup.c
index e1c4c0e..e420c8f 100644
--- a/toolkit/sup.c
+++ b/toolkit/sup.c
@@ -18,6 +18,16 @@
     (*back)(x, y, lParam);
 }
 
+DWORD CallHookProc (HOOKPROC func, short code, WPARAM wParam, LPARAM lParam)
+{
+    (*func)(code, wParam, lParam);
+}
+
+BOOL CallGrayStringProc (FARPROC func, HDC hdc, LPARAM lParam, INT cch)
+{
+    return (*func) (hdc, lParam, cch);
+}
+
 /*
  * Header loading routines for WineLib.
  */
diff --git a/tools/build.c b/tools/build.c
index 176dca0..85a4b20 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -50,7 +50,7 @@
 #define POP_0		"\tadd\t$4,%%esp\n"
 #define POP_SS		"\tpopw\t%%ss\n\tadd\t$2,%%esp\n"
 #define POP_ESP		"\tpopl\t%%esp\n"
-#define POP_EFL		"\tpopfl\n"
+#define POP_EFL		"\tpopl\t%%gs:return_value\n"
 #define POP_CS		"\tpopw\t%%cs\n\tadd\t$2,%%esp\n"
 #define POP_EIP		"\tpopl\t$0\n"
 #define POP_DS		"\tpopw\t%%ds\n\tadd\t$2,%%esp\n"
@@ -728,6 +728,8 @@
     
 	if (add_count > 0)
 	    fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
+
+	fprintf(fp, "\tpushl\t%%gs:return_value\n\tpopfl\n");
 		
 	fclose(fp);
 	exit(0);
diff --git a/windows/dc.c b/windows/dc.c
index c5cc0c7..947372d 100644
--- a/windows/dc.c
+++ b/windows/dc.c
@@ -293,7 +293,14 @@
     HDC hdcs;
     DC * dc, * dcs;
 
-    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return 0;
+	MF_MetaParam0(dc, META_SAVEDC);
+	return 1;  /* ?? */
+    }
     if (!(hdcs = GetDCState( hdc ))) return 0;
     dcs = (DC *) GDI_HEAP_ADDR( hdcs );
     dcs->header.hNext = dc->header.hNext;
@@ -315,7 +322,15 @@
 #ifdef DEBUG_DC
     printf( "RestoreDC: %d %d\n", hdc, level );
 #endif    
-    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
+    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	if (level != -1) return FALSE;
+	MF_MetaParam1(dc, META_RESTOREDC, level);
+	return TRUE;
+    }
     if (level == -1) level = dc->saveLevel;
     if ((level < 1) || (level > (short)dc->saveLevel)) return FALSE;
     
diff --git a/windows/dialog.c b/windows/dialog.c
index 2e5b6e3..7edc656 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -4,7 +4,7 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#define DEBUG_DIALOG /* */
+/* #define DEBUG_DIALOG /* */
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
diff --git a/windows/event.c b/windows/event.c
index f2402b3..861f95f 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -34,6 +34,7 @@
 
   /* State variables */
 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
+BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
 static WORD ALTKeyState;
 static HWND captureWnd = 0;
 Window winHasCursor = 0;
@@ -381,6 +382,7 @@
 
     if (buttonNum >= NB_BUTTONS) return;
     MouseButtonsStates[buttonNum] = TRUE;
+    AsyncMouseButtonsStates[buttonNum] = TRUE;
     winHasCursor = event->window;
     hardware_event( messages[buttonNum],
 		    EVENT_XStateToKeyState( event->state ), 0L,
diff --git a/windows/keyboard.c b/windows/keyboard.c
index 3738a41..ffa5777 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -7,8 +7,10 @@
 static char Copyright[] = "Copyright  Bob Amstadt, 1993";
 
 #include "win.h"
+#include "windows.h"
 
 extern BOOL MouseButtonsStates[3];
+extern BOOL AsyncMouseButtonsStates[3];
 
 /**********************************************************************
  *		GetKeyState	(USER.106)
@@ -26,3 +28,48 @@
 		    return 0;
 		}
 }
+
+
+/**********************************************************************
+ *
+ *            GetAsyncKeyState        (USER.249)
+ *
+ *	Determine if a key is or was pressed.  retval has high-order 
+ * byte set to 1 if currently pressed, low-order byte 1 if key has
+ * been pressed.
+ *
+ *	This uses the variable AsyncMouseButtonsStates (set in event.c)
+ * which have the mouse button number set to true if the mouse had been
+ * depressed since the last call to GetAsyncKeyState.
+ *
+ *   	There should also be some keyboard stuff here... it isn't here
+ * yet.
+ */
+int GetAsyncKeyState(int nKey)
+{
+	short 	retval;	
+
+	switch (nKey) {
+
+           case VK_LBUTTON:
+		retval = AsyncMouseButtonsStates[0] | 
+                              (MouseButtonsStates[0] << 8);
+		break;
+           case VK_MBUTTON:
+                retval = AsyncMouseButtonsStates[1] |
+                              (MouseButtonsStates[1] << 8);
+		break;
+           case VK_RBUTTON:
+                retval = AsyncMouseButtonsStates[2] |
+                              MouseButtonsStates[2] << 8;
+		break;
+           default:
+                retval = 0;
+		break;
+        }
+
+	bzero(AsyncMouseButtonsStates, 3);	/* all states to false */
+
+	return retval;
+}
+
diff --git a/windows/mapping.c b/windows/mapping.c
index b7a4753..f1b9d37 100644
--- a/windows/mapping.c
+++ b/windows/mapping.c
@@ -163,7 +163,23 @@
 DWORD SetViewportExt( HDC hdc, short x, short y )
 {
     SIZE size;
-    if (!SetViewportExtEx( hdc, x, y, &size )) return 0;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam2(dc, META_SETVIEWPORTEXT, x, y);
+	return 0;
+    }
+
+    size.cx = dc->w.VportExtX;
+    size.cy = dc->w.VportExtY;
+    if ((dc->w.MapMode != MM_ISOTROPIC) && (dc->w.MapMode != MM_ANISOTROPIC))
+	return size.cx | (size.cy << 16);
+    if (!x || !y) return 0;
+    dc->w.VportExtX = x;
+    dc->w.VportExtY = y;
+    if (dc->w.MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     return size.cx | (size.cy << 16);
 }
 
@@ -196,7 +212,19 @@
 DWORD SetViewportOrg( HDC hdc, short x, short y )
 {
     POINT pt;
-    if (!SetViewportOrgEx( hdc, x, y, &pt )) return 0;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam2(dc, META_SETVIEWPORTORG, x, y);
+	return 0;
+    }
+
+    pt.x = dc->w.VportOrgX;
+    pt.y = dc->w.VportOrgY;
+    dc->w.VportOrgX = x;
+    dc->w.VportOrgY = y;
     return pt.x | (pt.y << 16);
 }
 
@@ -225,7 +253,23 @@
 DWORD SetWindowExt( HDC hdc, short x, short y )
 {
     SIZE size;
-    if (!SetWindowExtEx( hdc, x, y, &size )) return 0;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam2(dc, META_SETWINDOWEXT, x, y);
+	return 0;
+    }
+
+    size.cx = dc->w.WndExtX;
+    size.cy = dc->w.WndExtY;
+    if ((dc->w.MapMode != MM_ISOTROPIC) && (dc->w.MapMode != MM_ANISOTROPIC))
+	return size.cx | (size.cy << 16);
+    if (!x || !y) return 0;
+    dc->w.WndExtX = x;
+    dc->w.WndExtY = y;
+    if (dc->w.MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     return size.cx | (size.cy << 16);
 }
 
@@ -258,7 +302,19 @@
 DWORD SetWindowOrg( HDC hdc, short x, short y )
 {
     POINT pt;
-    if (!SetWindowOrgEx( hdc, x, y, &pt )) return 0;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam2(dc, META_SETWINDOWORG, x, y);
+	return 0;
+    }
+
+    pt.x = dc->w.WndOrgX;
+    pt.y = dc->w.WndOrgY;
+    dc->w.WndOrgX = x;
+    dc->w.WndOrgY = y;
     return pt.x | (pt.y << 16);
 }
 
@@ -287,7 +343,19 @@
 DWORD OffsetViewportOrg( HDC hdc, short x, short y )
 {
     POINT pt;
-    if (!OffsetViewportOrgEx( hdc, x, y, &pt )) return 0;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam2(dc, META_OFFSETVIEWPORTORG, x, y);
+	return 0;
+    }
+
+    pt.x = dc->w.VportOrgX;
+    pt.y = dc->w.VportOrgY;
+    dc->w.VportOrgX += x;
+    dc->w.VportOrgY += y;
     return pt.x | (pt.y << 16);
 }
 
@@ -316,7 +384,19 @@
 DWORD OffsetWindowOrg( HDC hdc, short x, short y )
 {
     POINT pt;
-    if (!OffsetWindowOrgEx( hdc, x, y, &pt )) return 0;
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam2(dc, META_OFFSETWINDOWORG, x, y);
+	return 0;
+    }
+
+    pt.x = dc->w.WndOrgX;
+    pt.y = dc->w.WndOrgY;
+    dc->w.WndOrgX += x;
+    dc->w.WndOrgY += y;
     return pt.x | (pt.y << 16);
 }
 
@@ -346,8 +426,25 @@
 		      short yNum, short yDenom )
 {
     SIZE size;
-    if (!ScaleViewportExtEx( hdc, xNum, xDenom, yNum, yDenom, &size ))
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam4(dc, META_SCALEVIEWPORTEXT, xNum, xDenom, yNum, yDenom);
 	return 0;
+    }
+
+    size.cx = dc->w.VportExtX;
+    size.cy = dc->w.VportExtY;
+    if ((dc->w.MapMode != MM_ISOTROPIC) && (dc->w.MapMode != MM_ANISOTROPIC))
+	return size.cx | (size.cy << 16);
+    if (!xNum || !xDenom || !xNum || !yDenom) return 0;
+    dc->w.VportExtX = (dc->w.VportExtX * xNum) / xDenom;
+    dc->w.VportExtY = (dc->w.VportExtY * yNum) / yDenom;
+    if (dc->w.VportExtX == 0) dc->w.VportExtX = 1;
+    if (dc->w.VportExtY == 0) dc->w.VportExtY = 1;
+    if (dc->w.MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     return size.cx | (size.cy << 16);
 }
 
@@ -384,8 +481,25 @@
 		      short yNum, short yDenom )
 {
     SIZE size;
-    if (!ScaleWindowExtEx( hdc, xNum, xDenom, yNum, yDenom, &size ))
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) 
+    {
+	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
+	if (!dc) return FALSE;
+	MF_MetaParam4(dc, META_SCALEWINDOWEXT, xNum, xDenom, yNum, yDenom);
 	return 0;
+    }
+
+    size.cx = dc->w.WndExtX;
+    size.cy = dc->w.WndExtY;
+    if ((dc->w.MapMode != MM_ISOTROPIC) && (dc->w.MapMode != MM_ANISOTROPIC))
+	return size.cx | (size.cy << 16);
+    if (!xNum || !xDenom || !xNum || !yDenom) return FALSE;
+    dc->w.WndExtX = (dc->w.WndExtX * xNum) / xDenom;
+    dc->w.WndExtY = (dc->w.WndExtY * yNum) / yDenom;
+    if (dc->w.WndExtX == 0) dc->w.WndExtX = 1;
+    if (dc->w.WndExtY == 0) dc->w.WndExtY = 1;
+    if (dc->w.MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     return size.cx | (size.cy << 16);
 }
 
diff --git a/windows/win.c b/windows/win.c
index cbd72f2..73b5ac1 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "options.h"
 #include "class.h"
 #include "win.h"
 #include "user.h"
@@ -370,12 +371,23 @@
 	  /* Only select focus events on top-level override-redirect windows */
 	if (win_attr.override_redirect) win_attr.event_mask |= FocusChangeMask;
     }
+    if (Options.nobackingstore)
+       win_attr.backing_store = NotUseful;
+    else
+       win_attr.backing_store = Always;
+
+    if (Options.nosaveunders)
+       win_attr.save_under = FALSE;
+    else
+       win_attr.save_under = TRUE;        
+    
     wndPtr->window = XCreateWindow( display, parentPtr->window,
 		   x + parentPtr->rectClient.left - parentPtr->rectWindow.left,
 		   y + parentPtr->rectClient.top - parentPtr->rectWindow.top,
 		   width, height, 0,
 		   CopyFromParent, InputOutput, CopyFromParent,
-		   CWEventMask | CWOverrideRedirect | CWColormap, &win_attr );
+		   CWEventMask | CWOverrideRedirect | CWColormap |
+		   CWSaveUnder | CWBackingStore, &win_attr );
     XStoreName( display, wndPtr->window, windowName );
 
       /* Send the WM_CREATE message */