Release 970202

Sun Feb  2 12:31:03 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [files/drive.c]
	Fixed SetCurrentDirectory() to also change the current drive.

	* [win32/except.c] [tools/build.c]
	Use Win32 register functions to implement exception handling.
	Fixed UnhandledExceptionFilter.

Fri Jan 31 15:42:41  1997  David Faure  <david.faure@ihamy.insa-lyon.fr>

	* [windows/keyboard.c]
	Added KEYBOARD_GenerateMsg to generate Caps Lock and NumLock events
	Added calls to KEYBOARD_GenerateMsg when the key is pressed/released
	or when the state has changed, out of wine.
	Changed type 3-state 'ToggleKeyState' to boolean. The On/Off is given
	by InputKeyStateTable.

Wed Jan 29 21:53:04 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [loader/*resource.c][if1632/thunk.c]
	EnumResource* added.

	* [loader/pe_resource.] [loader/resource.c]
	SizeofResource32(), LoadAccelerators32() added.

	* [misc/lstr.c]
	FormatMessage %n added.

	* [misc/crtdll.c][include/ctrdll.h][if1632/crtdll.spec]
	_chdrive,_errno,_isctype added.

	* [misc/cpu.c]
	Replaced runtime_cpu by GetSystemInfo().

	* [windows/hook.c][include/hook.h]
	Fixed mapping of hooks to win32/unicode.

	* [windows/keyboard.c] [windows/defwnd.c]
	Updated to win32 standard.
	ALT-<Menukey> fixed.

	* [windows/queue.c]
	GetWindowThreadProcessId() implemented.

Mon Jan 27 16:42:49 1997  John Harvey <john@division.co.uk>

	* [graphics/metafiledrv/*] [graphics/x11drv/*]
	  [objects/bitmap.c] [objects/brush.c] [objects/font.c]
	  [objects/gdiobj.c] [objects/pen.c]
	Moved SelectObject to graphics drivers. Printer support now works
	in a few cases but is definitely not complete. Generic/text driver
	works. The postscript driver works if true type fonts are disabled
	from the control panel. To enable printer support add Printer=on
	to the wine section of your wine.conf file. This causes write not
	to work properly. I know that several other printer drivers do not
	work.

	* [tools/build.c]
	Make .stabs not used for svr4 since it doesn't use GNU assembler.

	* [misc/fontengine.c]
	Make sure a printf doesn't crash the system.

Sat Jan 25 15:53:35 1997  Huw D M Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/metafile.c]
	Fixed some problems with PlayMetaFileRecord().

	* [objects/dc.c]
	hClipRgn gets initialized in GetDCState().

Fri Jan 24 21:22:26 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [debugger/stabs.c]
	Handle file names beginning with '/'.

Fri Jan 24 18:33:04 1997  Robert Pouliot <krynos@clic.net>

	* [*/*]
	Some more patches for OS/2 support.

Fri Jan 24 11:30:41 1997  Bang Jun-Young  <bangjy@nownuri.nowcom.co.kr>

	* [resources/sysres_Ko.rc]
	Updated support for Korean (Ko) language.
diff --git a/loader/pe_resource.c b/loader/pe_resource.c
index 7c7e6af..08655d0 100644
--- a/loader/pe_resource.c
+++ b/loader/pe_resource.c
@@ -8,8 +8,7 @@
  * Based on the Win16 resource handling code in loader/resource.c
  * Copyright 1993 Robert J. Amstadt
  * Copyright 1995 Alexandre Julliard
- *
- * This is not even at ALPHA level yet. Don't expect it to work!
+ * Copyright 1997 Marcus Meissner
  */
 
 #include <sys/types.h>
@@ -18,22 +17,28 @@
 #include "pe_image.h"
 #include "module.h"
 #include "heap.h"
-#include "handle32.h"
 #include "libres.h"
 #include "stackframe.h"
 #include "neexe.h"
-#include "accel.h"
-#include "xmalloc.h"
 #include "stddebug.h"
 #include "debug.h"
 
-#define PrintIdA(name) \
-    if (HIWORD((DWORD)name)) \
-        dprintf_resource( stddeb, "'%s'", name); \
-    else \
-        dprintf_resource( stddeb, "#%04x", LOWORD(name)); 
-#define PrintIdW(name)
-#define PrintId(name)
+/**********************************************************************
+ *  HMODULE32toPE_MODULE 
+ *
+ * small helper function to get a PE_MODULE from a passed HMODULE32
+ */
+static PE_MODULE*
+HMODULE32toPE_MODULE(HMODULE32 hmod) {
+	NE_MODULE	*pModule;
+
+	if (!hmod) hmod = GetTaskDS(); /* FIXME: correct? */
+	hmod = GetExePtr( hmod );  /* In case we were passed an hInstance */
+
+	if (!(pModule = MODULE_GetPtr( hmod ))) return 0;
+	if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;
+	return pModule->pe_module;
+}
 
 /**********************************************************************
  *	    GetResDirEntryW
@@ -87,50 +92,18 @@
 }
 
 /**********************************************************************
- *	    GetResDirEntryA
- *
- *	Helper function - goes down one level of PE resource tree
- *
- */
-LPIMAGE_RESOURCE_DIRECTORY GetResDirEntryA(LPIMAGE_RESOURCE_DIRECTORY resdirptr,
-					   LPCSTR name,
-					   DWORD root)
-{
-	LPWSTR				xname;
-	LPIMAGE_RESOURCE_DIRECTORY	ret;
-
-	if (HIWORD((DWORD)name))
-		xname	= HEAP_strdupAtoW( GetProcessHeap(), 0, name );
-	else
-		xname	= (LPWSTR)name;
-
-	ret=GetResDirEntryW(resdirptr,xname,root);
-	if (HIWORD((DWORD)name))
-            HeapFree( GetProcessHeap(), 0, xname );
-	return ret;
-}
-
-/**********************************************************************
  *	    PE_FindResourceEx32W
  */
 HANDLE32 PE_FindResourceEx32W(
 	HINSTANCE32 hModule,LPCWSTR name,LPCWSTR type,WORD lang
 ) {
-    PE_MODULE *pe;
-    NE_MODULE *pModule;
     LPIMAGE_RESOURCE_DIRECTORY resdirptr;
     DWORD root;
     HANDLE32 result;
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hModule);
 
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
-    dprintf_resource(stddeb, "FindResource: module=%08x type=", hModule );
-    PrintId( type );
-    dprintf_resource( stddeb, " name=" );
-    PrintId( name );
-    dprintf_resource( stddeb, "\n" );
-    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
-    if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;  /* FIXME? */
-    if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0;
+    if (!pe || !pe->pe_resource)
+    	return 0;
 
     resdirptr = pe->pe_resource;
     root = (DWORD) resdirptr;
@@ -151,18 +124,287 @@
  */
 HANDLE32 PE_LoadResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
 {
-    NE_MODULE *pModule;
-    PE_MODULE *pe;
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hModule);
 
-    if (!hModule) hModule = GetTaskDS(); /* FIXME: see FindResource32W */
-    hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
-    dprintf_resource(stddeb, "PE_LoadResource32: module=%04x res=%04x\n",
-                     hModule, hRsrc );
+    if (!pe || !pe->pe_resource)
+    	return 0;
+    if (!hRsrc)
+   	 return 0;
+    return (HANDLE32) (pe->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
+}
+
+
+/**********************************************************************
+ *	    PE_SizeofResource32
+ */
+void
+_check_ptr(DWORD x,DWORD start,LPDWORD lastmax) {
+	if ((x>start) && (x<*lastmax))
+		*lastmax=x;
+}
+
+static void
+walk_resdir(DWORD loadaddr,DWORD rootresdir,DWORD xres,DWORD data,DWORD lvl,LPDWORD max){
+    LPIMAGE_RESOURCE_DIRECTORY		resdir;
+    LPIMAGE_RESOURCE_DATA_ENTRY		dataent;
+    LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
+    int	i;
+
+    if (lvl==3) {
+    	dataent = (LPIMAGE_RESOURCE_DATA_ENTRY)(rootresdir+xres);
+	_check_ptr(loadaddr+dataent->OffsetToData,data,max);
+	return;
+    }
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)(rootresdir+xres);
+    et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
+    for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++)
+	walk_resdir(loadaddr,rootresdir,(lvl==2)?et[i].u2.OffsetToData:et[i].u2.s.OffsetToDirectory,data,lvl+1,max);
+}
+
+DWORD PE_SizeofResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
+{
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hModule);
+    DWORD	max,data;
+    IMAGE_DATA_DIRECTORY	dir;
+
+    if (!pe || !pe->pe_resource)
+    	return 0;
     if (!hRsrc) return 0;
 
-    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
-    if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;  /* FIXME? */
-    if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0;
-    return (HANDLE32) (pe->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
+    max=(DWORD)-1;
+    dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
+    if(dir.Size)
+    	max=(DWORD)pe->pe_resource+dir.Size;
+
+    data=((DWORD)pe->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
+    walk_resdir(pe->load_addr,(DWORD)pe->pe_resource,0,data,0,&max);
+    return max-data;
+}
+
+/**********************************************************************
+ *	    PE_EnumResourceTypes32A
+ */
+BOOL32
+PE_EnumResourceTypes32A(HMODULE32 hmod,ENUMRESTYPEPROC32A lpfun,LONG lparam) {
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    int		i;
+    LPIMAGE_RESOURCE_DIRECTORY		resdir;
+    LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
+    BOOL32	ret;
+    HANDLE32	heap = GetProcessHeap();	
+
+    if (!pe || !pe->pe_resource)
+    	return FALSE;
+
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
+    ret = FALSE;
+    for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
+    	LPSTR	name;
+
+	if (HIWORD(et[i].u1.Name))
+		name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name));
+	else
+		name = (LPSTR)et[i].u1.Name;
+	ret = lpfun(hmod,name,lparam);
+	if (HIWORD(name))
+		HeapFree(heap,0,name);
+	if (!ret)
+		break;
+    }
+    return ret;
+}
+
+/**********************************************************************
+ *	    PE_EnumResourceTypes32W
+ */
+BOOL32
+PE_EnumResourceTypes32W(HMODULE32 hmod,ENUMRESTYPEPROC32W lpfun,LONG lparam) {
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    int		i;
+    LPIMAGE_RESOURCE_DIRECTORY		resdir;
+    LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
+    BOOL32	ret;
+
+    if (!pe || !pe->pe_resource)
+    	return FALSE;
+
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
+    ret = FALSE;
+    for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
+	LPWSTR	type;
+    	if (HIWORD(et[i].u1.Name))
+		type = (LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name);
+	else
+		type = (LPWSTR)et[i].u1.Name;
+
+	ret = lpfun(hmod,type,lparam);
+	if (!ret)
+		break;
+    }
+    return ret;
+}
+
+/**********************************************************************
+ *	    PE_EnumResourceNames32A
+ */
+BOOL32
+PE_EnumResourceNames32A(
+	HMODULE32 hmod,LPCSTR type,ENUMRESNAMEPROC32A lpfun,LONG lparam
+) {
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    int		i;
+    LPIMAGE_RESOURCE_DIRECTORY		resdir;
+    LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
+    BOOL32	ret;
+    HANDLE32	heap = GetProcessHeap();	
+    LPWSTR	typeW;
+
+    if (!pe || !pe->pe_resource)
+    	return FALSE;
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    if (HIWORD(type))
+	typeW = HEAP_strdupAtoW(heap,0,type);
+    else
+	typeW = (LPWSTR)type;
+    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pe->pe_resource);
+    if (HIWORD(typeW))
+    	HeapFree(heap,0,typeW);
+    if (!resdir)
+    	return FALSE;
+    et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
+    ret = FALSE;
+    for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
+    	LPSTR	name;
+
+	if (HIWORD(et[i].u1.Name))
+	    name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name));
+	else
+	    name = (LPSTR)et[i].u1.Name;
+	ret = lpfun(hmod,type,name,lparam);
+	if (HIWORD(name)) HeapFree(heap,0,name);
+	if (!ret)
+		break;
+    }
+    return ret;
+}
+
+/**********************************************************************
+ *	    PE_EnumResourceNames32W
+ */
+BOOL32
+PE_EnumResourceNames32W(
+	HMODULE32 hmod,LPCWSTR type,ENUMRESNAMEPROC32W lpfun,LONG lparam
+) {
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    int		i;
+    LPIMAGE_RESOURCE_DIRECTORY		resdir;
+    LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
+    BOOL32	ret;
+
+    if (!pe || !pe->pe_resource)
+    	return FALSE;
+
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    resdir = GetResDirEntryW(resdir,type,(DWORD)pe->pe_resource);
+    if (!resdir)
+    	return FALSE;
+    et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
+    ret = FALSE;
+    for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
+	LPWSTR	name;
+    	if (HIWORD(et[i].u1.Name))
+		name = (LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name);
+	else
+		name = (LPWSTR)et[i].u1.Name;
+	ret = lpfun(hmod,type,name,lparam);
+	if (!ret)
+		break;
+    }
+    return ret;
+}
+
+/**********************************************************************
+ *	    PE_EnumResourceNames32A
+ */
+BOOL32
+PE_EnumResourceLanguages32A(
+	HMODULE32 hmod,LPCSTR name,LPCSTR type,ENUMRESLANGPROC32A lpfun,
+	LONG lparam
+) {
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    int		i;
+    LPIMAGE_RESOURCE_DIRECTORY		resdir;
+    LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
+    BOOL32	ret;
+    HANDLE32	heap = GetProcessHeap();	
+    LPWSTR	nameW,typeW;
+
+    if (!pe || !pe->pe_resource)
+    	return FALSE;
+
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    if (HIWORD(name))
+	nameW = HEAP_strdupAtoW(heap,0,name);
+    else
+    	nameW = (LPWSTR)name;
+    resdir = GetResDirEntryW(resdir,nameW,(DWORD)pe->pe_resource);
+    if (HIWORD(nameW))
+    	HeapFree(heap,0,nameW);
+    if (!resdir)
+    	return FALSE;
+    if (HIWORD(type))
+	typeW = HEAP_strdupAtoW(heap,0,type);
+    else
+	typeW = (LPWSTR)type;
+    resdir = GetResDirEntryW(resdir,typeW,(DWORD)pe->pe_resource);
+    if (HIWORD(typeW))
+    	HeapFree(heap,0,typeW);
+    if (!resdir)
+    	return FALSE;
+    et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
+    ret = FALSE;
+    for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
+    	/* languages are just ids... I hope */
+	ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
+	if (!ret)
+		break;
+    }
+    return ret;
+}
+
+/**********************************************************************
+ *	    PE_EnumResourceLanguages32W
+ */
+BOOL32
+PE_EnumResourceLanguages32W(
+	HMODULE32 hmod,LPCWSTR name,LPCWSTR type,ENUMRESLANGPROC32W lpfun,
+	LONG lparam
+) {
+    PE_MODULE	*pe = HMODULE32toPE_MODULE(hmod);
+    int		i;
+    LPIMAGE_RESOURCE_DIRECTORY		resdir;
+    LPIMAGE_RESOURCE_DIRECTORY_ENTRY	et;
+    BOOL32	ret;
+
+    if (!pe || !pe->pe_resource)
+    	return FALSE;
+
+    resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
+    resdir = GetResDirEntryW(resdir,name,(DWORD)pe->pe_resource);
+    if (!resdir)
+    	return FALSE;
+    resdir = GetResDirEntryW(resdir,type,(DWORD)pe->pe_resource);
+    if (!resdir)
+    	return FALSE;
+    et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
+    ret = FALSE;
+    for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
+	ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
+	if (!ret)
+		break;
+    }
+    return ret;
 }
 #endif