Release 970329

Fri Mar 28 14:18:32 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [misc/main.c] [ANNOUNCE]
	Update the list of contributors. Please let me know if I forgot
	someone.

	* [controls/combo.c]
	Fixed bug in CB_DIR16 handling.
	Use correct text color in CBPaintText.

	* [controls/listbox.c]
	Fixed WM_CTLCOLOR handling.

	* [windows/winproc.c]
	Added translation for EM_*32 messages.

Mon Mar 24 01:31:52 1997  Steffen Moeller <moeller@mpimg-berlin-dahlem.mpg.de>

	* [files/drive.c]
	Added information on device and inode numbers to the DOSDRIVE
	struct, using it to find DOS drives in a path even if it contains
	symbolic links, eliminating annoying messages at startup.  
	Edited functions DRIVE_Init and rewrote DRIVE_FindDriveRoot.

Wed Mar 19 16:31:18 1997  John Harvey <john@division.co.uk>

	* [graphics/win16drv/font.c] [graphics/win16drv/init.c]
	  [graphics/x11drv/font.c] [objects/font.c] [include/gdi.h]
	  [include/win16drv.h] [include/x11drv.h]
	Implemented GetCharWidth via graphics drivers.

	* [graphics/win16drv/Makefile.in] [graphics/win16drv/prtdrv.c]
	Moved printer driver interfaces into a separate file.

	* [graphics/win16drv/text.c]
	Fixed bugs that seg-faulted write.

Wed Mar 19 13:52:41 1997  Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [BUGS]
	Update.

	* [controls/edit.c]
	Removed useless parameters from a lot of functions.

	* [controls/menu.c]
	Improved keyboard shortcuts. Added check for entries with popup 
	menu in EnableMenuItem().

	* [windows/winproc.c] [windows/win.c] [memory/selector.c]
	Do not allocate separate thunks for new windows.

	* [misc/clipboard.c] [windows/painting.c]
	Fixed problems with ClipBook.

        * [controls/combo.c] [controls/edit.c] [controls/listbox.c]
	  [controls/widgets.c] [windows/graphics.c] [windows/defdlg.c]
        Combo rewrite.

	* [objects/dib.c]
	Slight improvements.

Wed Mar 19 11:21:17 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [misc/crtdll.c]
	Added chdir/mkdir.

	* [misc/ntdll.c]
	Fixed some bugs, added RtlUnicodeStringToAnsiString.

	* [win32/process.c]
	Added initialisation of events/semaphores/mutices.

Wed Mar 19 01:55:40 1997  Ricardo R. Massaro <massaro@ime.usp.br>

	* [resources/sysres_Po.rc]
	Added support for Portuguese language.

Sat Mar 18 18:00:14 1997  Uwe Bonnes  <bon@elektron.ikp.physik.th-darmstadt.de>

	* [windows/winpos.c] [if1632/user.spec] [if1632/user32.spec]
	Implemented SwitchToThisWindow().
	
	* [misc/ver.c]
	Corrected a flaw in VerInstallFile32A.
	
	* [msdos/int21.c]
	Corrected wrong number in Int21 3305
	Corrected Int21 714e, implemented Int21 7160,CL=2, 7143 and 7147
	
Sun Mar 16 09:53:04 1997  Andreas Mohr <100.30936@germany.net>

	* [loader/ne_module.c]
	Fixed NE_LoadSegments() to set size to pSeg->minsize rather than
	setting it to 0x10000 if pSeg->size is 0.

Thu Mar 13 12:15:00 1997  Anand Kumria <akumria@ozemail.com.au>

	* [ANNOUNCE]
	Added ftp.progsoc.uts.edu.au as a mirror of Wine.

	* [memory/global.c]
	Removed MemManInfo sizeof check.

Mon Mar 10 10:35:44 MET 1997 Sven Verdoolaege <skimo@breughel.ufsia.ac.be>

	* [files/dos_fs.c]
	Pick up kernel dirent on glibc systems.

	* [loader/signal.c]
	Pick up kernel sigaction on glibc systems.

Sat Mar  8 21:05:37 1997  Jimen Ching  <jching@aloha.com>

	* [debugger/stabs.c] [debugger/msc.c]
	Check return value of mmap.

Fri Mar  7 05:42:03 1997  Lee Jaekil <juria@seodu.co.kr>

	* [win32/code_page.c]
	Added IsValidCodePage.
diff --git a/win32/process.c b/win32/process.c
index 58f8dc3..7178bf7 100644
--- a/win32/process.c
+++ b/win32/process.c
@@ -10,40 +10,298 @@
 #include "windows.h"
 #include "winerror.h"
 #include "heap.h"
+#include "thread.h"
 #include "handle32.h"
 #include "pe_image.h"
 #include "stddebug.h"
 #include "debug.h"
 
+typedef struct {
+	K32OBJ	header;
+	DWORD	maxcount;
+	DWORD	count;
+	DWORD	initial;
+} K32SEMAPHORE;
+
+typedef struct {
+	K32OBJ	header;
+	THDB	*owning_thread; /* we are locked by this thread */
+} K32MUTEX;
+
+typedef struct {
+	K32OBJ	header;
+} K32EVENT;
+
 /***********************************************************************
  *           CreateMutexA    (KERNEL32.52)
  */
-HANDLE32 CreateMutexA (SECURITY_ATTRIBUTES *sa, BOOL32 on, const char *a)
+HANDLE32 CreateMutex32A(SECURITY_ATTRIBUTES *sa,BOOL32 on,LPCSTR name)
 {
+	K32MUTEX	*mut;
+	HANDLE32	handle;
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_MUTEX) {
+			SetLastError( ERROR_ALREADY_EXISTS );
+			return PROCESS_AllocHandle( obj,0 );
+		}
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	mut = (K32MUTEX*)HeapAlloc(GetProcessHeap(),0,sizeof(K32MUTEX));
+	mut->header.type = K32OBJ_MUTEX;
+	mut->header.refcount  = 1;
+	mut->owning_thread = NULL;
+	if (name)
+		K32OBJ_AddName(&(mut->header),name);
+	handle = PROCESS_AllocHandle(&(mut->header),0);
+	if (handle != INVALID_HANDLE_VALUE32) {
+		if (on)
+			mut->owning_thread = (THDB *)GetCurrentThreadId();
+		return handle;
+	}
+	K32OBJ_DecCount(&(mut->header)); /* also frees name */
+	HeapFree(GetProcessHeap(),0,mut);
 	return 0;
 }
 
 /***********************************************************************
+ *           CreateMutexW    (KERNEL32.53)
+ */
+HANDLE32 CreateMutex32W(SECURITY_ATTRIBUTES *sa, BOOL32 on, LPCWSTR a)
+{
+	LPSTR		name = a?HEAP_strdupWtoA(GetProcessHeap(),0,a):NULL;
+	HANDLE32	ret;
+
+	ret = CreateMutex32A(sa,on,name);
+	if (name) HeapFree(GetProcessHeap(),0,name);
+	return ret;
+}
+
+/***********************************************************************
+ *           CreateSemaphoreA    (KERNEL32.60)
+ */
+HANDLE32 CreateSemaphore32A(
+	LPSECURITY_ATTRIBUTES sa,LONG initial,LONG max,LPCSTR name
+) {
+	K32SEMAPHORE	*sem;
+	HANDLE32	handle;
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_SEMAPHORE) {
+			SetLastError( ERROR_ALREADY_EXISTS );
+			return PROCESS_AllocHandle( obj,0 );
+		}
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	sem = (K32SEMAPHORE*)HeapAlloc(GetProcessHeap(),0,sizeof(K32SEMAPHORE));
+	sem->header.type = K32OBJ_SEMAPHORE;
+	sem->header.refcount  = 1;
+
+	sem->maxcount 	= max;
+	sem->count	= initial;
+	sem->initial	= initial;
+	if (name)
+		K32OBJ_AddName(&(sem->header),name);
+	handle = PROCESS_AllocHandle(&(sem->header),0);
+	if (handle != INVALID_HANDLE_VALUE32)
+		return handle;
+	K32OBJ_DecCount(&(sem->header)); /* also frees name */
+	HeapFree(GetProcessHeap(),0,sem);
+	return 0;
+}
+
+/***********************************************************************
+ *           CreateSemaphoreW    (KERNEL32.61)
+ */
+HANDLE32 CreateSemaphore32W(SECURITY_ATTRIBUTES *sa,LONG initial,LONG max,LPCWSTR a)
+{
+	LPSTR		name =a?HEAP_strdupWtoA(GetProcessHeap(),0,a):NULL;
+	HANDLE32	ret;
+
+	ret = CreateSemaphore32A(sa,initial,max,name);
+	if (a) HeapFree(GetProcessHeap(),0,name);
+	return ret;
+}
+
+
+/***********************************************************************
+ *           OpenSemaphoreA    (KERNEL32.403)
+ */
+HANDLE32 OpenSemaphore32A(DWORD desired,BOOL32 inherit,LPCSTR name)
+{
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_SEMAPHORE)
+			return PROCESS_AllocHandle( obj,0 );
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	return 0;
+}
+
+/***********************************************************************
+ *           OpenSemaphoreA    (KERNEL32.404)
+ */
+HANDLE32 OpenSemaphore32W(DWORD desired,BOOL32 inherit,LPCWSTR name)
+{
+	LPSTR	nameA = name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
+	HANDLE32	ret = OpenSemaphore32A(desired,inherit,nameA);
+
+	if (name) HeapFree(GetProcessHeap(),0,nameA);
+	return ret;
+}
+
+/***********************************************************************
+ *           ReleaseSemaphore    (KERNEL32.403)
+ */
+BOOL32 ReleaseSemaphore(HANDLE32 hSemaphore,LONG lReleaseCount,LPLONG lpPreviousCount) {
+	K32SEMAPHORE	*sem;
+
+	sem = (K32SEMAPHORE*)PROCESS_GetObjPtr(hSemaphore,K32OBJ_SEMAPHORE);
+	if (!sem)
+		return FALSE;
+	if (lpPreviousCount) *lpPreviousCount = sem->count;
+	sem->count += lReleaseCount;
+	if (sem->count>sem->maxcount) {
+		fprintf(stderr,"ReleaseSemaphore(%d,%ld,.), released more then possible??\n",hSemaphore,lReleaseCount);
+		sem->count = sem->maxcount;
+	}
+
+	/* FIXME: wake up all threads blocked on that semaphore */
+
+	K32OBJ_DecCount(&(sem->header));
+	return TRUE;
+}
+
+/***********************************************************************
+ *           OpenMutexA    (KERNEL32.399)
+ */
+HANDLE32 OpenMutex32A(DWORD desiredaccess, BOOL32 inherithandle, LPCSTR name)
+{
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_MUTEX)
+			return PROCESS_AllocHandle( obj,0 );
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	return 0;
+}
+
+/***********************************************************************
+ *           OpenMutexW    (KERNEL32.400)
+ */
+HANDLE32 OpenMutex32W(DWORD desiredaccess, BOOL32 inherithandle, LPCWSTR name)
+{
+	LPSTR		nameA=name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
+	HANDLE32	ret = OpenMutex32A(desiredaccess,inherithandle,nameA);
+
+	if (name) HeapFree(GetProcessHeap(),0,nameA);
+	return ret;
+}
+
+/***********************************************************************
  *           ReleaseMutex    (KERNEL32.435)
  */
 BOOL32 ReleaseMutex (HANDLE32 h)
 {
-	return 0;
+	K32MUTEX	*mut = (K32MUTEX*)PROCESS_GetObjPtr(h,K32OBJ_MUTEX);
+
+	if (!mut)
+		return 0;
+	if (mut->owning_thread != (THDB *)GetCurrentThreadId()) {
+		/* set error ... */
+		K32OBJ_DecCount(&(mut->header));
+		return 0;
+	}
+	mut->owning_thread = NULL;
+
+	/* FIXME: wake up all threads blocked on this mutex */
+
+	K32OBJ_DecCount(&(mut->header));
+	return TRUE;
 }
 
 /***********************************************************************
  *           CreateEventA    (KERNEL32.43)
  */
-HANDLE32 CreateEventA (SECURITY_ATTRIBUTES *sa, BOOL32 au, BOOL32 on, const char
-*name)
+HANDLE32 CreateEvent32A(SECURITY_ATTRIBUTES *sa,BOOL32 au,BOOL32 on,LPCSTR name)
 {
+	K32EVENT	*evt;
+	HANDLE32	handle;
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_EVENT) {
+			SetLastError( ERROR_ALREADY_EXISTS );
+			return PROCESS_AllocHandle( obj,0 );
+		}
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	evt = (K32EVENT*)HeapAlloc(GetProcessHeap(),0,sizeof(K32EVENT));
+	evt->header.type = K32OBJ_EVENT;
+	evt->header.refcount  = 1;
+	if (name)
+		K32OBJ_AddName(&(evt->header),name);
+	handle = PROCESS_AllocHandle(&(evt->header),0);
+	if (handle != INVALID_HANDLE_VALUE32)
+		return handle;
+	K32OBJ_DecCount(&(evt->header)); /* also frees name */
+	HeapFree(GetProcessHeap(),0,evt);
 	return 0;
 }
+
+/***********************************************************************
+ *           CreateEventW    (KERNEL32.43)
+ */
+HANDLE32 CreateEvent32W(SECURITY_ATTRIBUTES *sa, BOOL32 au, BOOL32 on,LPCWSTR name)
+{
+	LPSTR nameA=name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
+	HANDLE32 ret = CreateEvent32A(sa,au,on,nameA);
+
+	if (name) HeapFree(GetProcessHeap(),0,nameA);
+	return ret;
+}
+
+/***********************************************************************
+ *           OpenEventA    (KERNEL32.394)
+ */
+HANDLE32 OpenEvent32A(DWORD desiredaccess,BOOL32 inherithandle,LPCSTR name) {
+	K32OBJ 		*obj = K32OBJ_FindName( name );
+
+	if (obj) {
+		if (obj->type == K32OBJ_EVENT)
+			return PROCESS_AllocHandle( obj,0 );
+		SetLastError( ERROR_DUP_NAME );
+		return 0;
+	}
+	return 0;
+}
+
+/***********************************************************************
+ *           OpenEventW    (KERNEL32.395)
+ */
+HANDLE32 OpenEvent32W(DWORD desiredaccess,BOOL32 inherithandle,LPCWSTR name) {
+	LPSTR	nameA = name?HEAP_strdupWtoA(GetProcessHeap(),0,name):NULL;
+	HANDLE32	ret = OpenEvent32A(desiredaccess,inherithandle,nameA);
+
+	if (name) HeapFree(GetProcessHeap(),0,nameA);
+	return ret;
+}
+
 /***********************************************************************
  *           SetEvent    (KERNEL32.487)
  */
 BOOL32 SetEvent (HANDLE32 h)
 {
+	fprintf(stderr,"SetEvent(%d) stub\n",h);
 	return 0;
 }
 /***********************************************************************
@@ -51,13 +309,15 @@
  */
 BOOL32 ResetEvent (HANDLE32 h)
 {
+	fprintf(stderr,"ResetEvent(%d) stub\n",h);
 	return 0;
 }
 /***********************************************************************
  *           WaitForSingleObject    (KERNEL32.561)
  */
-DWORD WaitForSingleObject(HANDLE32 h, DWORD a)
+DWORD WaitForSingleObject(HANDLE32 h, DWORD timeout)
 {
+	fprintf(stderr,"WaitForSingleObject(%d,%ld) stub\n",h,timeout);
 	return 0;
 }
 /***********************************************************************
@@ -65,8 +325,9 @@
  */
 BOOL32 DuplicateHandle(HANDLE32 a, HANDLE32 b, HANDLE32 c, HANDLE32 * d, DWORD e, BOOL32 f, DWORD g)
 {
+	fprintf(stderr,"DuplicateHandle(%d,%d,%d,%p,%ld,%d,%ld) stub\n",a,b,c,d,e,f,g);
 	*d = b;
-	return 1;
+	return TRUE;
 }
 
 
@@ -89,7 +350,7 @@
 	}
 	/* Obtain module handle and call initialization function */
 #ifndef WINELIB
-	if (handle >= (HINSTANCE32)32) PE_InitializeDLLs( GetExePtr(handle));
+	if (handle >= (HINSTANCE32)32) PE_InitializeDLLs( GetExePtr(handle), DLL_PROCESS_ATTACH, NULL);
 #endif
 	return handle;
 }
@@ -134,11 +395,33 @@
 
 /**********************************************************************
  *           SetThreadAffinityMask
+ * Works now like the Windows95 (no MP support) version
  */
 BOOL32 SetThreadAffinityMask(HANDLE32 hThread, DWORD dwThreadAffinityMask)
 {
-	dprintf_task(stddeb,"SetThreadAffinityMask(%x,%lx)\n",hThread,
-		dwThreadAffinityMask);
-	/* FIXME: We let it fail */
-	return 1;
+	THDB	*thdb = (THDB*)PROCESS_GetObjPtr(hThread,K32OBJ_THREAD);
+
+	if (!thdb) 
+		return FALSE;
+	if (dwThreadAffinityMask!=1) {
+		fprintf(stderr,"SetThreadAffinityMask(%d,%ld), only 1 processor supported.\n",(int)hThread,dwThreadAffinityMask);
+		K32OBJ_DecCount((K32OBJ*)thdb);
+		return FALSE;
+	}
+	K32OBJ_DecCount((K32OBJ*)thdb);
+	return TRUE;
+}
+
+BOOL32
+CreateProcess32A(
+	LPCSTR appname,LPSTR cmdline,LPSECURITY_ATTRIBUTES processattributes,
+        LPSECURITY_ATTRIBUTES threadattributes,BOOL32 inherithandles,
+	DWORD creationflags,LPVOID env,LPCSTR curdir,
+	LPSTARTUPINFO32A startupinfo,LPPROCESS_INFORMATION processinfo
+) {
+	fprintf(stderr,"CreateProcess(%s,%s,%p,%p,%d,%08lx,%p,%s,%p,%p)\n",
+		appname,cmdline,processattributes,threadattributes,
+		inherithandles,creationflags,env,curdir,startupinfo,processinfo
+	);
+	return TRUE;
 }