diff --git a/ChangeLog b/ChangeLog
index 1d124764314f8626c6d731976af3ccbf6465e20e..5b0424f55359052d2f05288b28fcebf939ddc455 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,140 @@
+----------------------------------------------------------------------
+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)
 
@@ -30,7 +167,7 @@ Mon May 23 00:48:25 1994  Rick Sladkey  (jrs@world.std.com)
         * [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 4df0e0419376d527f024ef3e6d157560d9c60ab3..5432ca5b9327f7eae54fce63e6c27010c25ef8b8 100644
--- a/README
+++ b/README
@@ -197,6 +197,17 @@ bob@amscons.com
 
 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 5e43c3b01e7494d2d03d324562c994abd72c63f5..7ff105fb297406d032d5ec8b1c605baaa11a1294 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -673,7 +673,7 @@ void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
     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 cb5f14c1d4be6ba47c1510d3aa249d132d57e3b9..d18e7857a57a8530a3df64713a195cd48dd4889a 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -78,6 +78,7 @@ LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 			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 @@ LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 		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 @@ void StdDrawListBox(HWND hwnd)
 	    }
 	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 @@ int ListBoxResetContent(HWND hwnd)
 #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 ListBoxGetSel(HWND hwnd, WORD wIndex)
 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 @@ int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
 	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 e99e2187300f89c56419bc86ae65da11551a0b83..b4783089382af6e6645a94826698abe5dcb911d1 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -43,6 +43,7 @@ void mode_command(int);
 %token NO_SYMBOL
 %token SYMBOLFILE
 %token DEFINE
+%token ABORT
 
 %%
 
@@ -52,17 +53,20 @@ void mode_command(int);
  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 @@ deposit_command:
 
 
 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 @@ x_command:
 			           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 @@ wine_debug(int signal, int * regs)
 #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 @@ wine_debug(int signal, int * regs)
 	} else {
 		dbg_mask = 0xffff;
 		dbg_mode = 16;
-	};
+	}
 #endif
 #ifdef __NetBSD__
 	if(SC_CS == 0x1f) {
@@ -160,7 +172,7 @@ wine_debug(int signal, int * regs)
 	} else {
 		dbg_mask = 0xffff;
 		dbg_mode = 16;
-	};
+	}
 #endif
 	fprintf(stderr,"In %d bit mode.\n", dbg_mode);
 
@@ -170,7 +182,7 @@ wine_debug(int signal, int * regs)
 	if(!loaded_symbols){
 		loaded_symbols++;
 		load_entrypoints();
-	};
+	}
 #endif
 
 	/* Remove the breakpoints from memory... */
@@ -187,7 +199,7 @@ wine_debug(int signal, int * regs)
 	  }
 
 	/* 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 90effe0241b10f137855335b5f2a6ac1f8dc24cd..47135160fa24786b53917114d415bd86acf52611 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -98,6 +98,7 @@ cont|con|co		{ return CONT; }
 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 @@ regs|reg|re	{ return REGS; }
 
 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 b4b2358b3477f7ed69e0c588291775ff7508421a..8df409e08feecb850b459bb28e35e1678dc5f9dc 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -222,7 +222,7 @@ char * helptext[] = {
 "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 @@ char * helptext[] = {
 " 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 @@ void dbg_bt(){
   }
 
   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 9d5e1792e1b169b23047e67f41e68b9b8152a5d6..409a7569760949c752b945643b88ae09f2d939a2 100644
--- a/debugger/opcodes/i386-dis.c
+++ b/debugger/opcodes/i386-dis.c
@@ -703,6 +703,9 @@ static char *names8[] = {
 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 @@ ckprefix ()
     }
 }
 
+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 @@ print_insn_i286 (pc, info)
      bfd_vma pc;
      disassemble_info *info;
 {
+  machine = 286;
   dflag = 0;
   aflag = 0;
   return print_insn_i286_or_i386 (pc, info);
@@ -1150,6 +1155,7 @@ print_insn_i386 (pc, info)
      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 @@ OP_E (bytemode)
   
   append_prefix ();
 
-  if (bytemode == w_mode || (bytemode == v_mode && !dflag))
+  if (machine == 286)
     {
       if (mod == 0 && rm == 6)
 	{
@@ -1579,33 +1585,8 @@ OP_E (bytemode)
 	  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 02f5cda195203eacfab169f0045c386e7bf007ac..a4bd586a1bf74f34bbe1c7ba28b4cdf94a4b2173 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -155,7 +155,7 @@ LONG CallWindowProc( FARPROC func, HWND hwnd, WORD message,
 	    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 82247c51ac5ddd362d59249ed91bf01176efc023..7c7e1d4a51d5af90169a91d7c0bd8300a1ef571e 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -127,7 +127,7 @@ length	490
 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 @@ length	490
 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 @@ length	490
 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 2f00be8faf1f5ec03b19328bccf89eb2270d904b..dc3076ea1ceb56c1ef5d4aa7dd9ca0638c33f974 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -18,7 +18,7 @@ length	415
 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 @@ length	415
 #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 ff2d96106e2273b49027a87da1eec09aa27e62f9..3694b33aaac57ee016dc76b483d567f51bbd2ff6 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 2b4c0eeded60d9d0d13e75c529b3dce881157779..259f377d85728019ec54544d5264840d2e048d61 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -258,7 +258,7 @@ length	540
 #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 @@ length	540
 #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 5d89f9eba229739c4cc7fbe609bdd5fdd5ee4f60..874d69e1f990349c83a6b68b68c1eab89595f018 100644
--- a/include/listbox.h
+++ b/include/listbox.h
@@ -26,6 +26,7 @@ typedef struct tagHEADLIST {
     void	*lpFirst; 
     DWORD	dwStyle;
     HWND	hWndLogicParent;
+	HFONT	hFont;
 } HEADLIST;
 typedef HEADLIST FAR* LPHEADLIST;
 
diff --git a/include/metafile.h b/include/metafile.h
index 0a3e5e91c2427135999a010af3d078a7b7ce48f4..a3cd796d7a5ef576e5ca6e38a4781d541b753db1 100644
--- a/include/metafile.h
+++ b/include/metafile.h
@@ -19,13 +19,16 @@ typedef struct tagMETAFILE
     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_MetaParam6(DC *dc, short func, short param1, short param2,
 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 ac6dd229da71690664d69da4b10f37f4f2c6daec..de39b93874eaf68e803edef12ceb980a26a7f77f 100644
--- a/include/mmsystem.h
+++ b/include/mmsystem.h
@@ -251,7 +251,7 @@ UINT WINAPI waveOutSetVolume(UINT uDeviceID, DWORD dwVolume);
 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 WINAPI waveInGetDevCaps(UINT uDeviceID, WAVEINCAPS FAR* lpCaps,
     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 struct {
 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 da5b598b95f72a967c7f3fe5f381c2d85de23578..5003b9fa283e58a5f9149bbbb03d6239789d4a24 100644
--- a/include/options.h
+++ b/include/options.h
@@ -14,6 +14,8 @@ struct options
     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 a972176f4e3b72392ca7da019107e732ae5ebff7..a264ed5522c2844899c6d3b0aa8466506b588bed 100644
--- a/include/prototypes.h
+++ b/include/prototypes.h
@@ -82,7 +82,7 @@ extern void load_ne_header (int, struct ne_header_s *);
 
 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 c53f00383c81d0e05d358eabbc94688b53fbf296..e99dd6ea0e6aafcdf185331a897c9269c2789316 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -46,11 +46,18 @@ HANDLE GetModuleHandle(LPSTR lpModuleName)
 {
 	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 @@ HANDLE GetModuleHandle(LPSTR lpModuleName)
  	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 @@ HANDLE LoadLibrary(LPSTR libname)
     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 @@ FARPROC GetProcAddress(HANDLE hModule, char *proc_name)
 		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 fea7a6f881c5d8e54317deda92fa53c5b9caf4f3..9573c7a159dfc80f6558b00fd7db33c41bbe3e88 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -60,9 +60,12 @@ SEGDESC Segments[MAX_SELECTORS];
 
 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 @@ LPSTR GetDOSEnvironment(void)
 static SEGDESC *
 CreateEnvironment(void)
 {
+    char **e;
     char *p;
+    unsigned short *w;
     SEGDESC * s;
 
     s = CreateNewSegments(0, 0, PAGE_SIZE, 1);
@@ -717,15 +722,36 @@ CreateEnvironment(void)
 	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 @@ CreatePSP(void)
 	    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 @@ CreateSelectors(struct  w_files * wpnt)
 	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 896ed0608ad201f6b8408d76884e1f349cc7bdee..b88f985a9147b58d838f5fcfd22fd2502efa3ef1 100644
--- a/loader/wine.c
+++ b/loader/wine.c
@@ -34,6 +34,8 @@ extern void CallTo32();
 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 @@ void load_ne_header (int fd, struct ne_header_s *ne_header)
  *					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 @@ HINSTANCE LoadImage(char *modulename, int filetype)
       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 @@ _WinMain(int argc, char **argv)
 		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 0a21566a638a7a7bf59ab0cda02fd01c9bafed35..ef4e17036b045fb3a7f18e0ba1297b7d506a542a 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 @@ GlobalFlags(unsigned int block)
 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 c54c0eee2ba808848a9b3ed032fd47b2abe513eb..d6535f37ae7f1cedac4a4c72f5d1a037d9ce0989 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -9,7 +9,7 @@ static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 #include "heap.h"
 #include "regfunc.h"
 
-/* #define DEBUG_HEAP */
+/* #define DEBUG_HEAP /* */
 
 LHEAP *LocalHeaps = NULL;
 
diff --git a/misc/Imakefile b/misc/Imakefile
index dffb6288d4ddfbf86e737fbf0b91de609ce3459d..6cfa02fac9e29cfa8e8d5efe1fe04d6c7fd3110d 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 @@ SRCS = \
 	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 0a51b77d60043e2e8bedce23c27bd7563f7db68c..8f7f9bc3ed9c8ccca01899d40b2e52af0ee102e3 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 @@ fprintf(stderr,"BuildCommDCB: (%s), ptr %d\n", device, (long) lpdcb);
 #endif
 	commerror = 0;
 
-	if (!strncmp(device,"COM",3)) {
+	if (!strncasecmp(device,"COM",3)) {
 		port = device[3] - '0';
 	
 
@@ -170,8 +170,7 @@ fprintf(stderr,"BuildCommDCB: (%s), ptr %d\n", device, (long) lpdcb);
 		}
 		
 		if (!COM[port].fd) {
-			commerror = IE_NOPEN;
-			return -1;
+		    OpenComm(device, 0, 0);
 		}
 		lpdcb->Id = COM[port].fd;
 		
@@ -246,7 +245,7 @@ fprintf(stderr,"OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
 	
 	commerror = 0;
 
-	if (!strncmp(device,"COM",3)) {
+	if (!strncasecmp(device,"COM",3)) {
 		port = device[3] - '0';
 
 		if (port-- == 0) {
@@ -259,8 +258,7 @@ fprintf(stderr,"OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
 			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 @@ fprintf(stderr,"OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
 		}
 	} 
 	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 77b24290613642ef16699ed5d8c71c8f6ddcecef..83ed2b570e364da88f1d0a6016126509725ca825 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 @@ char *GetUnixFileName(char *dosfilename)
 { 
 	/*   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 *GetUnixFileName(char *dosfilename)
 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 daccb03443e0c388533ce26ca5f4659f83c58aae..a53550e3ded6c4db6313a5e92777c0d2f97d2063 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -45,7 +45,7 @@ extern int CallToInit16(unsigned long csip, unsigned long sssp,
 			unsigned short ds);
 HANDLE CreateNewTask(HINSTANCE hInst);
 
-
+#ifndef WINELIB
 void InitializeLoadedNewDLLs(HINSTANCE hInst)
 {
     struct w_files * w;
@@ -127,7 +127,12 @@ void StartNewTask(HINSTANCE hInst)
 
 }
 
-
+#else
+void StartNewTask (HINSTANCE hInst)
+{
+    printf ("Not yet implemented\n");
+}
+#endif
 
 /**********************************************************************
  *				LoadModule	[KERNEL.45]
@@ -172,7 +177,7 @@ WORD WinExec(LPSTR lpCmdLine, WORD nCmdShow)
 			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 3348f758ccfa19b0e0526cc08f726a522b57884c..e5d72713ce0e73ff1e5a67e3ce00a980b83e2364 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,9 +85,11 @@ INT _lwrite (INT hFile, LPSTR lpBuffer, INT wBytes)
 {
 	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);
 
@@ -121,38 +121,61 @@ INT _lclose (INT hFile)
  **************************************************************************/
 INT OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle)
 {
-	int 	base,flags;
-	int		handle;
+    int 	base, flags;
+    int		handle;
+
 #ifdef DEBUG_FILE
-	fprintf(stderr,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
+    fprintf(stderr,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
 #endif
-	base=wStyle&0xF;
-	flags=wStyle&0xFFF0;
+
+    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 */
+    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; }
+    if (flags & OF_CREATE) 
+    { 
+	base  |= O_CREAT; 
+	flags &= 0xEFFF; 
+    }
 
 #ifdef DEBUG_FILE
-	fprintf(stderr,"now %d,%d\n",base,flags);
+    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 {
-		return _lopen (lpFileName, wStyle);
-		}
+    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 245b5c92d20edca3c33c1838bade3d44529a6bec..fca16e634175c68bca3a38c137d84f15a554a991 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -40,6 +40,8 @@ struct options Options =
     NULL,           /* programName */
     FALSE,          /* usePrivateMap */
     FALSE,          /* synchronous */
+    FALSE,          /* no backing store */
+    FALSE,          /* no save unders */
     SW_SHOWNORMAL,  /* cmdShow */
     FALSE
 };
@@ -47,16 +49,18 @@ struct options Options =
 
 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 @@ static XrmOptionDescRec optionsTable[] =
   "    -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 @@ static void MAIN_ParseOptions( int *argc, char *argv[] )
 	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 @@ static void MAIN_CreateDesktop( int argc, char *argv[] )
 			 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 @@ int main( int argc, char *argv[] )
     
 #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 0a8da32818fbd333fa2b85599785ddc98df9d860..9d754e3bbfc63937108b0706cc72debbc2b2fd98 100644
--- a/misc/message.c
+++ b/misc/message.c
@@ -54,6 +54,9 @@ int MessageBox(HWND hWnd, LPSTR str, LPSTR title, WORD type)
 	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 e4c6a2e629f977ddf96b04ea489bae2207a451ee..09304dfc221cfe2865d3b51c95b9d2c430fa0431 100644
--- a/misc/mmsystem.c
+++ b/misc/mmsystem.c
@@ -24,7 +24,9 @@ int MCI_LibMain(HANDLE hInstance, WORD wDataSeg,
 	return(TRUE);
 }
 
-
+/**************************************************************************
+* 				sndPlaySound		[MMSYSTEM.2]
+*/
 BOOL WINAPI sndPlaySound(LPCSTR lpszSoundName, UINT uFlags)
 {
 	printf("sndPlaySound // lpszSoundName='%s' uFlags=%04X !\n", 
@@ -32,58 +34,68 @@ BOOL WINAPI sndPlaySound(LPCSTR lpszSoundName, UINT uFlags)
 	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 @@ DWORD mciOpen(UINT wDevID, DWORD dwParam, LPMCI_OPEN_PARMS lpParms)
 				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 @@ DWORD mciSendCommand(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2)
 	return MCIERR_DEVICE_NOT_INSTALLED;
 }
 
-
 /**************************************************************************
 * 				mciGetDeviceID			[MMSYSTEM.703]
 */
@@ -550,8 +560,6 @@ UINT mciGetDeviceID (LPCSTR lpstrName)
 	return 0;
 }
 
-
-
 /**************************************************************************
 * 				mciSendString			[MMSYSTEM.702]
 */
@@ -564,40 +572,56 @@ DWORD WINAPI mciSendString (LPCSTR lpstrCommand,
 	return MCIERR_MISSING_COMMAND_STRING;
 }
 
-
-
-UINT WINAPI midiOutGetNumDevs(void)
+/**************************************************************************
+* 				mciSetYieldProc		[MMSYSTEM.714]
+*/
+BOOL WINAPI mciSetYieldProc (UINT uDeviceID, 
+		YIELDPROC fpYieldProc, DWORD dwYieldData)
 {
-	printf("midiOutGetNumDevs\n");
-	return 0;
 }
 
+/**************************************************************************
+* 				mciGetDeviceIDFromElementID	[MMSYSTEM.715]
+*/
+UINT WINAPI mciGetDeviceIDFromElementID(DWORD dwElementID, LPCSTR lpstrType)
+{
+}
 
-
-UINT WINAPI midiOutGetDevCaps(UINT uDeviceID,
-    MIDIOUTCAPS FAR* lpCaps, UINT uSize)
+/**************************************************************************
+* 				mciGetYieldProc		[MMSYSTEM.716]
+*/
+YIELDPROC WINAPI mciGetYieldProc(UINT uDeviceID, DWORD FAR* lpdwYieldData)
 {
-	printf("midiOutGetDevCaps\n");
-	return 0;
 }
 
+/**************************************************************************
+* 				mciGetCreatorTask	[MMSYSTEM.717]
+*/
+HTASK WINAPI mciGetCreatorTask(UINT uDeviceID)
+{
+}
 
-UINT WINAPI midiOutGetVolume(UINT uDeviceID, DWORD FAR* lpdwVolume)
+/**************************************************************************
+* 				midiOutGetNumDevs	[MMSYSTEM.201]
+*/
+UINT WINAPI midiOutGetNumDevs(void)
 {
-	printf("midiOutGetVolume\n");
+	printf("midiOutGetNumDevs\n");
 	return 0;
 }
 
-
-UINT WINAPI midiOutSetVolume(UINT uDeviceID, DWORD dwVolume)
+/**************************************************************************
+* 				midiOutGetDevCaps	[MMSYSTEM.202]
+*/
+UINT WINAPI midiOutGetDevCaps(UINT uDeviceID,
+    MIDIOUTCAPS FAR* lpCaps, UINT uSize)
 {
-	printf("midiOutSetVolume\n");
+	printf("midiOutGetDevCaps\n");
 	return 0;
 }
 
-
 /**************************************************************************
-* 				midiOutGetErrorText 		[MMSYSTEM.203]
+* 				midiOutGetErrorText 	[MMSYSTEM.203]
 */
 UINT WINAPI midiOutGetErrorText(UINT uError, LPSTR lpText, UINT uSize)
 {
@@ -654,7 +678,9 @@ msg# 343 : There are no MIDI devices installed on the system. Use the Drivers op
 	return(TRUE);
 }
 
-
+/**************************************************************************
+* 				midiOutOpen			[MMSYSTEM.204]
+*/
 UINT WINAPI midiOutOpen(HMIDIOUT FAR* lphMidiOut, UINT uDeviceID,
     DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
 {
@@ -663,14 +689,18 @@ UINT WINAPI midiOutOpen(HMIDIOUT FAR* lphMidiOut, UINT uDeviceID,
 	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 @@ UINT WINAPI midiOutPrepareHeader(HMIDIOUT hMidiOut,
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutUnprepareHeader	[MMSYSTEM.207]
+*/
 UINT WINAPI midiOutUnprepareHeader(HMIDIOUT hMidiOut,
     MIDIHDR FAR* lpMidiOutHdr, UINT uSize)
 {
@@ -686,14 +718,18 @@ UINT WINAPI midiOutUnprepareHeader(HMIDIOUT hMidiOut,
 	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 @@ UINT WINAPI midiOutLongMsg(HMIDIOUT hMidiOut,
 	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 @@ UINT WINAPI midiOutCachePatches(HMIDIOUT hMidiOut,
 	return 0;
 }
 
-
+/**************************************************************************
+* 				midiOutCacheDrumPatches	[MMSYSTEM.214]
+*/
 UINT WINAPI midiOutCacheDrumPatches(HMIDIOUT hMidiOut,
     UINT uPatch, WORD FAR* lpwKeyArray, UINT uFlags)
 {
@@ -724,31 +784,36 @@ UINT WINAPI midiOutCacheDrumPatches(HMIDIOUT hMidiOut,
 	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 @@ UINT WINAPI midiInGetDevCaps(UINT uDeviceID,
 	return 0;
 }
 
-
-
 /**************************************************************************
 * 				midiInGetErrorText 		[MMSYSTEM.303]
 */
@@ -767,8 +830,9 @@ UINT WINAPI midiInGetErrorText(UINT uError, LPSTR lpText, UINT uSize)
 	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 @@ UINT WINAPI midiInOpen(HMIDIIN FAR* lphMidiIn, UINT uDeviceID,
 	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 @@ UINT WINAPI midiInPrepareHeader(HMIDIIN hMidiIn,
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				midiInUnprepareHeader	[MMSYSTEM.307]
+*/
 UINT WINAPI midiInUnprepareHeader(HMIDIIN hMidiIn,
     MIDIHDR FAR* lpMidiInHdr, UINT uSize)
 {
@@ -812,8 +870,9 @@ UINT WINAPI midiInUnprepareHeader(HMIDIIN hMidiIn,
 	return 0;
 }
 
-
-
+/**************************************************************************
+* 				midiInAddBuffer		[MMSYSTEM.308]
+*/
 UINT WINAPI midiInAddBuffer(HMIDIIN hMidiIn,
     MIDIHDR FAR* lpMidiInHdr, UINT uSize)
 {
@@ -821,45 +880,71 @@ UINT WINAPI midiInAddBuffer(HMIDIIN hMidiIn,
 	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;
 }
 
+/**************************************************************************
+* 				midiInGetID			[MMSYSTEM.312]
+*/
+UINT WINAPI midiInGetID(HMIDIIN hMidiIn, UINT FAR* lpuDeviceID)
+{
+	printf("midiInGetID\n");
+	return 0;
+}
 
-
-UINT WINAPI waveOutGetNumDevs()
+/**************************************************************************
+* 				midiInMessage		[MMSYSTEM.313]
+*/
+DWORD WINAPI midiInMessage(HMIDIIN hMidiIn, UINT uMessage, 
+							DWORD dwParam1, DWORD dwParam2)
 {
-	printf("waveOutGetNumDevs\n");
+	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 @@ UINT WINAPI waveGetErrorText(UINT uError, LPSTR lpText, UINT uSize)
 	return(TRUE);
 }
 
-
+/**************************************************************************
+* 				waveOutOpen			[MMSYSTEM.404]
+*/
 UINT WINAPI waveOutOpen(HWAVEOUT FAR* lphWaveOut, UINT uDeviceID,
-    const WAVEFORMAT FAR* lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
-{
-	printf("waveOutOpen\n");
+    const LPWAVEFORMAT lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
+{
+	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 @@ UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut,
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
+/**************************************************************************
+* 				waveOutUnprepareHeader	[MMSYSTEM.407]
+*/
 UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut,
     WAVEHDR FAR* lpWaveOutHdr, UINT uSize)
 {
@@ -974,115 +1075,144 @@ UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut,
 	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)
+/**************************************************************************
+* 				waveOutGetPitch		[MMSYSTEM.413]
+*/
+UINT WINAPI waveOutGetPitch(HWAVEOUT hWaveOut, DWORD FAR* lpdwPitch)
 {
-	printf("waveOutSetVolume\n");
+	printf("waveOutGetPitch\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
-UINT WINAPI waveOutGetID(HWAVEOUT hWaveOut, UINT FAR* lpuDeviceID)
+/**************************************************************************
+* 				waveOutSetPitch		[MMSYSTEM.414]
+*/
+UINT WINAPI waveOutSetPitch(HWAVEOUT hWaveOut, DWORD dwPitch)
 {
-	printf("waveOutGetID\n");
+	printf("waveOutSetPitch\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
-UINT WINAPI waveOutGetPitch(HWAVEOUT hWaveOut, DWORD FAR* lpdwPitch)
+/**************************************************************************
+* 				waveOutGetVolume	[MMSYSTEM.415]
+*/
+UINT WINAPI waveOutGetVolume(UINT uDeviceID, DWORD FAR* lpdwVolume)
 {
-	printf("waveOutGetPitch\n");
+	printf("waveOutGetVolume\n");
 	return MMSYSERR_INVALHANDLE;
 }
 
-
-
-UINT WINAPI waveOutSetPitch(HWAVEOUT hWaveOut, DWORD dwPitch)
+/**************************************************************************
+* 				waveOutSetVolume	[MMSYSTEM.416]
+*/
+UINT WINAPI waveOutSetVolume(UINT uDeviceID, DWORD dwVolume)
 {
-	printf("waveOutSetPitch\n");
+	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 @@ UINT WINAPI waveInGetErrorText(UINT uError, LPSTR lpText, UINT uSize)
 * 				waveInOpen			[MMSYSTEM.504]
 */
 UINT WINAPI waveInOpen(HWAVEIN FAR* lphWaveIn, UINT uDeviceID,
-    const WAVEFORMAT FAR* lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
-{
-	printf("waveInOpen\n");
+    const LPWAVEFORMAT lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
+{
+	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;
 }
 
@@ -1206,6 +1345,16 @@ UINT WINAPI waveInGetID(HWAVEIN hWaveIn, UINT FAR* lpuDeviceID)
 }
 
 
+/**************************************************************************
+* 				waveInMessage 		[MMSYSTEM.514]
+*/
+DWORD WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage,
+							DWORD dwParam1, DWORD dwParam2)
+{
+}
+
+
+
 /**************************************************************************
 * 				mmioOpen			[MMSYSTEM.1210]
 */
@@ -1248,7 +1397,6 @@ LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
 	return 0;
 }
 
-
 /**************************************************************************
 * 				mmioSeek			[MMSYSTEM.1214]
 */
@@ -1258,7 +1406,6 @@ LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, int iOrigin)
 	return 0;
 }
 
-
 /**************************************************************************
 * 				mmioGetInfo			[MMSYSTEM.1215]
 */
@@ -1268,7 +1415,6 @@ UINT WINAPI mmioGetInfo(HMMIO hmmio, MMIOINFO FAR* lpmmioinfo, UINT uFlags)
 	return 0;
 }
 
-
 /**************************************************************************
 * 				mmioGetInfo			[MMSYSTEM.1216]
 */
@@ -1278,45 +1424,139 @@ UINT WINAPI mmioSetInfo(HMMIO hmmio, const MMIOINFO FAR* lpmmioinfo, UINT uFlags
 	return 0;
 }
 
+/**************************************************************************
+* 				mmioSetBuffer		[MMSYSTEM.1217]
+*/
+UINT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer, 
+						LONG cchBuffer, UINT uFlags)
+{
+	printf("mmioSetBuffer\n");
+	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);
+/**************************************************************************
+* 				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);
+					    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);
-UINT WINAPI mmioAscend(HMMIO hmmio, MMCKINFO FAR* lpck, UINT uFlags);
-UINT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO FAR* lpck, UINT uFlags);
+		    const MMCKINFO FAR* lpckParent, UINT uFlags)
+{
+	printf("mmioDescend\n");
+	return 0;
+}
 
-DWORD WINAPI midiInMessage(HMIDIIN hMidiIn, UINT uMessage, DWORD dw1, DWORD dw2);
+/**************************************************************************
+* 				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;
+}
 
-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);
+/**************************************************************************
+* 				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 3fac219d26a1d803af146354b2725f68a12a178a..29e65080c5c72f7a89cc4be8eb3ab9431288ff59 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -220,6 +220,10 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
     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 @@ static short GetSetProfile (int set, LPSTR AppName, LPSTR KeyName,
 	/* 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 GetPrivateProfileString (LPSTR AppName, LPSTR KeyName,
 			       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 779c5952e2df386c38c0078555b8268b28d64c25..19977ca1f1b9b7b940434b05f00dea9a2119b71f 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"
+
+/*
+#define DEBUG_REG
+*/
+
+LPKEYSTRUCT	lphRootKey = NULL;
 
-typedef DWORD HKEY;
 typedef FAR LONG *LPWORD;
 DECLARE_HANDLE(HDROP);
 
@@ -17,63 +22,270 @@ extern HINSTANCE hSysRes;
 /*************************************************************************
  *				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 @@ BOOL DragQueryPoint(HDROP h, POINT FAR *p)
 /*************************************************************************
  *				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 @@ HICON ExtractAssociatedIcon(HINSTANCE hInst,LPSTR lpIconPath, LPWORD lpiIcon)
 int RegisterShellHook(void *ptr) 
 {
 	fprintf(stderr, "RegisterShellHook : Empty Stub !!!\n");
+	return 0;
 }
 
 
diff --git a/misc/winsocket.c b/misc/winsocket.c
index 4d9d5c04d26502c880446b5c669bcbbecfac21c0..cd7fb53c2a036ba15ba07f4b635756af6d8d87b5 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -878,7 +878,9 @@ INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
 	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 cefe3ae2fba75f37f7ae9173f52ba359dfd8ef08..865bd49d932e634d4b01aa510a805db0368962b3 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 SetFileAttributes(struct sigcontext_struct *context)
 
 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 @@ static void OpenExistingFile(struct sigcontext_struct *context)
 		return;
 	}		
 	Error (0,0,0);
-	EBX = (EBX & 0xffff0000L) | handle;
-	EAX = (EAX & 0xffffff00L) | NoError;
+	EAX = (EAX & 0xffff0000L) | handle;
 	ResetCflag;
 }
 
@@ -705,13 +720,20 @@ static void FindNext(struct sigcontext_struct *context)
 {
 	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 @@ static void FindNext(struct sigcontext_struct *context)
 
 	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 @@ static void FindFirst(struct sigcontext_struct *context)
 		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 43023625bd850a824c4d8145d99033b43dd20c25..c90b9e2158571184100158c443c5584f72915d41 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -12,6 +12,7 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 #include <X11/Intrinsic.h>
 
 #include "gdi.h"
+#include "metafile.h"
 
 extern const int DC_XROPfunction[];
 
@@ -28,7 +29,15 @@ BOOL PatBlt( HDC hdc, short left, short top,
     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 38fabec927b7fcac45f96e96f3f598c2c896116a..6e8c1b0206ed9502472094d3480e3c72f79e2d78 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -251,6 +251,16 @@ HBITMAP BITMAP_SelectObject( HDC hdc, DC * dc, HBITMAP hbitmap,
     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 563617fbfb597045e35551964bb654bc85f10640..a12c4552db099c6ac4740035ebf560e1f684af5b 100644
--- a/objects/brush.c
+++ b/objects/brush.c
@@ -237,13 +237,13 @@ HBRUSH BRUSH_SelectObject( HDC hdc, DC * dc, HBRUSH hbrush, BRUSHOBJ * brush )
 	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 7504b12aeb35160d7febe01d9e7c469a4d965617..a5240ff0bd66870790641e287b2354b6f3d0b4c2 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -8,6 +8,7 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include <stdio.h>
 #include "gdi.h"
+#include "metafile.h"
 
 
 /***********************************************************************
@@ -131,7 +132,14 @@ int SelectVisRgn( HDC hdc, HRGN hrgn )
 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 @@ int ExcludeClipRect( HDC hdc, short left, short top,
 		     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 @@ int IntersectClipRect( HDC hdc, short left, short top,
 		       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 6129981b3e3fd11b87e5adb1a07141ca09580976..07e4d21d9edc16ee67605f01c21e184b34abcf69 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -663,8 +663,10 @@ int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData
 	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 903cfa7cd63428f8d89936f6fca8b641cc61a0f2..5ff49ed3617cbfc7d345f9d0130b9d51c70c0571 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -13,6 +13,11 @@ static char Copyright[] = "Copyright  David W. Metcalfe, 1994";
 
 #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 CreateMetaFile(LPSTR lpFilename)
     HANDLE handle;
     METAFILE *mf;
     METAHEADER *mh;
+    HANDLETABLE *ht;
 
 #ifdef DEBUG_METAFILE
     printf("CreateMetaFile: %s\n", lpFilename);
@@ -64,6 +70,12 @@ HANDLE CreateMetaFile(LPSTR lpFilename)
     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 @@ HMETAFILE CloseMetaFile(HDC hdc)
     /* 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 @@ HMETAFILE CloseMetaFile(HDC hdc)
 	_lclose(mf->hFile);
     }
 
+    /* delete the handle table */
+    GlobalFree(hHT);
+
     GlobalUnlock(mf->hMetaHdr);
     hmf = dc->w.hMetaFile;
+    GlobalUnlock(hmf);
     GDI_FreeObject(hdc);
     return hmf;
 }
@@ -138,6 +157,292 @@ BOOL DeleteMetaFile(HMETAFILE hmf)
 }
 
 
+/******************************************************************
+ *         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
  */
@@ -176,6 +481,71 @@ BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
 }
 
 
+/******************************************************************
+ *         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
  */
@@ -274,16 +644,15 @@ BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2,
 /******************************************************************
  *         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 @@ BOOL MF_CreateBrushIndirect(DC *dc, LOGBRUSH *logbrush)
 
     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 @@ BOOL MF_CreatePatternBrush(DC *dc, LOGBRUSH *logbrush)
 	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 @@ BOOL MF_CreatePatternBrush(DC *dc, LOGBRUSH *logbrush)
 	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 @@ BOOL MF_CreatePatternBrush(DC *dc, LOGBRUSH *logbrush)
     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 @@ BOOL MF_CreatePenIndirect(DC *dc, LOGPEN *logpen)
 
     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 @@ BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
     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 @@ BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
     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 cf3089fee8879f9b2e987b6bb0c9d939873fc82d..61e1f16d4340cf47563625f46317b7ada1a1f761 100644
--- a/objects/pen.c
+++ b/objects/pen.c
@@ -64,7 +64,7 @@ HPEN PEN_SelectObject( DC * dc, HPEN hpen, PENOBJ * pen )
     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 e1c4c0e5f73295a99c74ac2ffd1e53598a631b5a..e420c8f62f29f36515b998bf3c7d5714ba750d67 100644
--- a/toolkit/sup.c
+++ b/toolkit/sup.c
@@ -18,6 +18,16 @@ CallLineDDAProc (FARPROC back, int x, int y, long lParam)
     (*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 176dca07524f7f39208b3c2651befce4ec4c9f8c..85a4b20a6301775872394bc9a6fe68e72e68e3f9 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -50,7 +50,7 @@ static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 #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 @@ main(int argc, char **argv)
     
 	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 c5cc0c72688b1aae69456de6f98b13292b8fd2a6..947372d469b698698443d96047d2432dd21b8e06 100644
--- a/windows/dc.c
+++ b/windows/dc.c
@@ -293,7 +293,14 @@ int SaveDC( HDC hdc )
     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 @@ BOOL RestoreDC( HDC hdc, short level )
 #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 2e5b6e33d3d31f0a209545b8f8f080b4bc0cfd9d..7edc656ffba23fd3aaa989a624ff77fa217a5503 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 f2402b385779bf224e59030fd9db27243c426922..861f95fc2c5ba427d22d24aa85a3c17a3effabe5 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -34,6 +34,7 @@ static XContext winContext = 0;
 
   /* 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 @@ static void EVENT_ButtonPress( XButtonEvent *event )
 
     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 3738a41134792db50e74e2d4f41b40c5f75ce16d..ffa5777944737fea7f5cc904082befa890f2efef 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 @@ int GetKeyState(int keycode)
 		    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 b7a475323ceb1b2bfc014fc6745469a6ba77c07b..f1b9d375ac409162f8c6aaa397196d0bcf7d3184 100644
--- a/windows/mapping.c
+++ b/windows/mapping.c
@@ -163,7 +163,23 @@ WORD SetMapMode( HDC hdc, WORD mode )
 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 @@ BOOL SetViewportExtEx( HDC hdc, short x, short y, LPSIZE size )
 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 @@ BOOL SetViewportOrgEx( HDC hdc, short x, short y, LPPOINT pt )
 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 @@ BOOL SetWindowExtEx( HDC hdc, short x, short y, LPSIZE size )
 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 @@ BOOL SetWindowOrgEx( HDC hdc, short x, short y, LPPOINT pt )
 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 @@ BOOL OffsetViewportOrgEx( HDC hdc, short x, short y, LPPOINT pt )
 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 @@ DWORD ScaleViewportExt( HDC hdc, short xNum, short xDenom,
 		      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 @@ DWORD ScaleWindowExt( HDC hdc, short xNum, short xDenom,
 		      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 cbd72f2b10590e85349cbae671dd7d42e6bf37b7..73b5ac104a1e7c3ce9558f8f658c74d9a748351f 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -10,6 +10,7 @@ static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 #include <stdio.h>
 #include <string.h>
 
+#include "options.h"
 #include "class.h"
 #include "win.h"
 #include "user.h"
@@ -370,12 +371,23 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName,
 	  /* 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 */