Release 940420

Wed Apr 20 14:53:35 1994  Bob Amstadt  (bob@pooh)

	* [tools/build.c] [if1632/call.S] [if1632/Imakefile]
	Fixed bug for non-Linux systems.

Apr 18, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [windows/win.c]
	Bug fixed in CreateWindowEx() : Now use SetMenu() for menubar setup.
	New empty stub for function SetSysModalWindow().

	* [misc/exec.c]
	New empty stub for function ExitWindows().

	* [objects/font.c]
	New empty stub for function EnumFonts().

	* New file [misc/property.c]
	New functions RemoveProp(), GetProp(), SetProp() & EnumProps().

	* New file [misc/shell.c]
	New empty stubs for function RegisterShellProc(), 
			ShellExecute() & ShellProc().

	* New files [loader/task.c] & [include/task.h]
	Move functions GetWindowTask(), GetNumTask(), EnumTaskWindows()
		from 'loader/library.c'.

	* [if1632/user.c] [if1632/kernel.c]
	Put Atoms functions entries.

	* [controls/combo.c]
	New functions DirDlgSelectComboBox() & DirDlgListComboBox().

	* [controls/listbox.c]
	New functions DirDlgSelect() & DirDlgList().

Sun Apr 17 20:57:59 1994  Erik Bos (erik@trashcan.hacktic.nl)

	* [objects/test.c]
	GrayString() added.

	* [if1632/callback.c]
	CallGrayStringProc() added.

	* [if1632/relay.c] [if1632/mmsystem.spec]
	Added.

	* [if1632/kernel.spec] [if1632/user.spec]
	Added forgotten specs for atom functions.

Tue Apr 12 00:05:31 1994  Bob Amstadt  (bob@pooh)

	* misc/spy.c (SpyInit): Added more message types

	* [windows/mdi.c] [include/mdi.h]
	Maximizing and restoring child windows.
	Tiling of child windows.

Mon Apr 11 20:48:28 1994  Alexandre Julliard  (julliard@lamisun.epfl.ch)

	* [windows/winpos.c]
	Revert focus and activation to previous window when hiding a window.

	* [windows/syscolor.c]
	Implemented system color objects (brushes and pens created at
	SetSysColor() time for better performance).

	* [windows/graphics.c] [windows/nonclient.c] [controls/button.c]
	Changed painting code to use system color objects.

	* [windows/message.c]
	New function MSG_InternalGetMessage() for internal messages
	loops (e.g. for dialogs or menus).

	* [windows/hook.c] [include/hook.h]  (New files)
	Beginning of the window hooks implementation.

	* [windows/dialog.c]
	Use new function MSG_InternalGetMessage() in DialogBox().

	* [if1632/callback.c]
	Added function CallHookProc().

Apr 11, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [windows/event.c]
	Bug fix : WM_CHARs are sent to focused window like WM_KEY???.

	* [misc/exec.c]
	Nothing much more than a stub for LoadModule(), I saw there a lot
		to be done in that corner, I will come back later ...

	* [loader/library.c]
	New functions GetWindowTask(), GetNumTask(), EnumTaskWindows() 
			and associated modules & tasks linked-lists.
	(it's only an 'emerging bud', more to come next weeks).

	* [loader/wine.c]
	Use LoadLibrary() instead of LoadImage() for 'sysres.dll'.

	* [control/menu.c]
	You can now click outside menu region without problem.
	Keyboard navig more smootly, even if a child has the focus.
	Bug fix in InsertItem(), (bad linklist when insert point not found).
	change Realloc for Free & Alloc in ModifyItem().
	MF_STRING now set BLACK_PEN to fix bug of bad color of the underscores 
		done by DrawText(), (maybe it should done in DrawText() itself ?).

Sun Apr 10 14:06:08 1994  Erik Bos (erik@trashcan.hacktic.nl)

	* [misc/profile.c]
	.INI files will now be stored in / loaded from the windows dir
	if no path is supplied.

	* [if1632/kernel.spec]
	Fixed GetDriveType's prototype.

	* [if1632/winsock.spec] [include/winsock.h] [misc/winsocket.c]
	Fixed prototypes: winsock uses a word as socket handle not an int.

	* [misc/winsocket.c]
	Added heap allocation for returned structures.
	Added non-blocking WSAAsyncGetXbyY() functions as blocking ones.

	* [loader/wine.c]
	Added IsDLLLoaded(), used in LoadImage() to prevent loading
	a dll multiple times.
	Directory is added to wine's path when a fullpath is supplied when
	starting wine.
	LoadImage(): DLL filename used instead DLL's own internal name,
	fixes 'Bad DLL name' errors.

Sat Apr  9 08:26:03 1994  David Metcalfe <david@prism.demon.co.uk>

	* [controls/edit.c] [controls/widgets.c]
	First release of edit control.
diff --git a/loader/Imakefile b/loader/Imakefile
index df53854..68297d2 100644
--- a/loader/Imakefile
+++ b/loader/Imakefile
@@ -10,6 +10,7 @@
 	signal.c \
 	library.c \
 	resource.c \
+	task.c \
 	wine.c
 
 OBJS = $(SRCS:.c=.o)
diff --git a/loader/library.c b/loader/library.c
index 39ea0bb..4e60f1d 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -1,3 +1,8 @@
+/*
+ *        Modules & Libraries functions
+ */
+static char Copyright[] = "Copyright  Martin Ayotte, 1994";
+
 #ifndef WINELIB
 #include <stdio.h>
 #include <stdlib.h>
@@ -10,30 +15,25 @@
 #include "windows.h"
 #include "wine.h"
 #include "dlls.h"
+#include "task.h"
 
-typedef struct module_table_entry
-{
+typedef struct {
+	LPSTR		ModuleName;
+	LPSTR		FileName;
+	WORD		Count;
+	HANDLE		hModule;
 	HINSTANCE	hInst;
-	LPSTR		name;
-	WORD		count;
+	void		*lpPrevModule;
+	void		*lpNextModule;
 } MODULEENTRY;
+typedef MODULEENTRY *LPMODULEENTRY;
+
+static LPMODULEENTRY lpModList = NULL;
 
 extern struct  w_files * wine_files;
-
 #define N_BUILTINS	10
-
 extern struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS];
 
-/**********************************************************************
- *				GetCurrentTask	[KERNEL.36]
- */
-HTASK GetCurrentTask()
-{
-    int pid = getpid();
-    printf("GetCurrentTask() returned %d !\n", pid);
-    return pid;
-}
-
 
 /**********************************************************************
  *				GetModuleHandle	[KERNEL.47]
@@ -69,11 +69,11 @@
  */
 int GetModuleUsage(HANDLE hModule)
 {
-    struct w_files *w;
-    printf("GetModuleUsage(%04X);\n", hModule);
-    w = GetFileInfo(hModule);
-/*    return w->Usage; */
-    return 1;
+	struct w_files *w;
+	printf("GetModuleUsage(%04X);\n", hModule);
+	w = GetFileInfo(hModule);
+/*	return w->Usage; */
+	return 1;
 }
 
 
@@ -100,10 +100,44 @@
 HANDLE LoadLibrary(LPSTR libname)
 {
     HANDLE hModule;
+	LPMODULEENTRY lpMod = lpModList;
+	LPMODULEENTRY lpNewMod;
     printf("LoadLibrary '%s'\n", libname);
-    hModule = LoadImage(libname, DLL);
-    printf("LoadLibrary returned hModule=%04X\n", hModule);
-    return hModule;
+	if (lpMod != NULL) {
+		while (TRUE) {
+			if (strcmp(libname, lpMod->FileName) == 0) {
+				lpMod->Count++;
+			    printf("LoadLibrary // already loaded hInst=%04X\n", lpMod->hInst);
+				return lpMod->hInst;
+				}
+			if (lpMod->lpNextModule == NULL) break;
+			lpMod = lpMod->lpNextModule;
+			}
+		}
+	hModule = GlobalAlloc(GMEM_MOVEABLE, sizeof(MODULEENTRY));
+	lpNewMod = (LPMODULEENTRY) GlobalLock(hModule);	
+#ifdef DEBUG_LIBRARY
+    printf("LoadLibrary // creating new module entry %08X\n", lpNewMod);
+#endif
+	if (lpNewMod == NULL) return 0;
+	if (lpModList == NULL) {
+		lpModList = lpNewMod;
+		lpNewMod->lpPrevModule = NULL;
+		}
+	else {
+		lpMod->lpNextModule = lpNewMod;
+		lpNewMod->lpPrevModule = lpMod;
+		}
+	lpNewMod->lpNextModule = NULL;
+	lpNewMod->hModule = hModule;
+	lpNewMod->ModuleName = NULL;
+	lpNewMod->FileName = (LPSTR) malloc(strlen(libname));
+	if (lpNewMod->FileName != NULL)	strcpy(lpNewMod->FileName, libname);
+	lpNewMod->hInst = LoadImage(libname, DLL);
+	lpNewMod->Count = 1;
+    printf("LoadLibrary returned Library hInst=%04X\n", lpNewMod->hInst);
+	GlobalUnlock(hModule);	
+    return lpNewMod->hInst;
 }
 
 
@@ -112,8 +146,24 @@
  */
 void FreeLibrary(HANDLE hLib)
 {
+	LPMODULEENTRY lpMod = lpModList;
     printf("FreeLibrary(%04X);\n", hLib);
-    if (hLib != (HANDLE)NULL) GlobalFree(hLib);
+	while (lpMod != NULL) {
+		if (lpMod->hInst == hLib) {
+			if (lpMod->Count == 1) {
+				if (hLib != (HANDLE)NULL) GlobalFree(hLib);
+				if (lpMod->ModuleName != NULL) free(lpMod->ModuleName);
+				if (lpMod->FileName != NULL) free(lpMod->FileName);
+				GlobalFree(lpMod->hModule);
+				printf("FreeLibrary // freed !\n");
+				return;
+				}
+			lpMod->Count--;
+			printf("FreeLibrary // Count decremented !\n");
+			return;
+			}
+		lpMod = lpMod->lpNextModule;
+		}
 }
 
 
@@ -128,26 +178,39 @@
 	int 	ordinal, len;
 	char 	* cpnt;
 	char	C[128];
-	if (hModule == 0) {
-		printf("GetProcAddress: Bad Module handle=%#04X\n", hModule);
-		return NULL;
-		}
+	HTASK	hTask;
+	LPTASKENTRY lpTask;
 	if (hModule >= 0xF000) {
 		if ((int) proc_name & 0xffff0000) {
-			printf("GetProcAddress: builtin %#04x, '%s'\n", hModule, proc_name);
+			printf("GetProcAddress: builtin %#04X, '%s'\n", 
+										hModule, proc_name);
 /*			wOrdin = FindOrdinalFromName(struct dll_table_entry_s *dll_table, proc_name); */
 			}
 		else {
-			printf("GetProcAddress: builtin %#04x, %d\n", hModule, (int) proc_name);
+			printf("GetProcAddress: builtin %#04X, %d\n", 
+								hModule, (int)proc_name);
 			}
 		return NULL;
 		}
+	if (hModule == 0) {
+		hTask = GetCurrentTask();
+		printf("GetProcAddress // GetCurrentTask()=%04X\n", hTask);
+		lpTask = (LPTASKENTRY) GlobalLock(hTask);
+		if (lpTask == NULL) {
+			printf("GetProcAddress: can't find current module handle !\n");
+			return NULL;
+			}
+		hModule = lpTask->hInst;
+		printf("GetProcAddress: current module=%04X instance=%04X!\n", 
+			lpTask->hModule, lpTask->hInst);
+		GlobalUnlock(hTask);
+		}
 	while (w && w->hinstance != hModule) w = w->next;
-	printf("GetProcAddress // Module Found ! w->filename='%s'\n", w->filename);
 	if (w == NULL) return NULL;
-	if ((int) proc_name & 0xffff0000) {
+	printf("GetProcAddress // Module Found ! w->filename='%s'\n", w->filename);
+	if ((int)proc_name & 0xFFFF0000) {
 		AnsiUpper(proc_name);
-		printf("GetProcAddress: %#04x, '%s'\n", hModule, proc_name);
+		printf("GetProcAddress: %04X, '%s'\n", hModule, proc_name);
 		cpnt = w->nrname_table;
 		while(TRUE) {
 			if (((int) cpnt)  - ((int)w->nrname_table) >  
@@ -155,11 +218,19 @@
 			len = *cpnt++;
 			strncpy(C, cpnt, len);
 			C[len] = '\0';
+#ifdef DEBUG_MODULE
 			printf("pointing Function '%s' !\n", C);
-			if (strncmp(cpnt, proc_name, len) ==  0) break;
+#endif
+			if (strncmp(cpnt, proc_name, len) ==  0) {
+				ordinal =  *((unsigned short *)  (cpnt +  len));
+				break;
+				}
 			cpnt += len + 2;
 			};
-		ordinal =  *((unsigned short *)  (cpnt +  len));
+		if (ordinal == 0) {
+			printf("GetProcAddress // function '%s' not found !\n", proc_name);
+			return NULL;
+			}
 		}
 	else {
 		printf("GetProcAddress: %#04x, %d\n", hModule, (int) proc_name);
@@ -167,13 +238,13 @@
 		}
 	ret = GetEntryPointFromOrdinal(w, ordinal);
 	if (ret == -1) {
-		printf("GetProcAddress // Function not found !\n");
+		printf("GetProcAddress // Function #%d not found !\n", ordinal);
 		return NULL;
 		}
 	addr  = ret & 0xffff;
 	sel = (ret >> 16);
 	printf("GetProcAddress // ret=%08X sel=%04X addr=%04X\n", ret, sel, addr);
-	return ret;
+	return (FARPROC) ret;
 }
 
 #endif /* ifndef WINELIB */
diff --git a/loader/task.c b/loader/task.c
new file mode 100644
index 0000000..46bb89b
--- /dev/null
+++ b/loader/task.c
@@ -0,0 +1,159 @@
+/*
+ *        Tasks functions
+ */
+static char Copyright[] = "Copyright  Martin Ayotte, 1994";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "windows.h"
+#include "wine.h"
+#include "task.h"
+
+static LPTASKENTRY lpTaskList = NULL;
+static int nTaskCount = 0;
+
+
+
+/**********************************************************************
+ *				GetCurrentTask	[KERNEL.36]
+ */
+HTASK GetCurrentTask()
+{
+	LPTASKENTRY lpTask = lpTaskList;
+	int pid = getpid();
+	printf("GetCurrentTask() // unix_pid=%08X !\n", pid);
+	if (lpTask == NULL) return 0;
+	while (TRUE) {
+		printf("GetCurrentTask() // searching lpTask->unix_pid=%08 !\n", lpTask->unix_pid);
+		if (lpTask->unix_pid == pid) break;
+		if (lpTask->lpNextTask == NULL) return 0;
+		lpTask = lpTask->lpNextTask;
+		}
+	printf("GetCurrentTask() returned hTask=%04X !\n", lpTask->hTask);
+	return lpTask->hTask;
+}
+
+
+/**********************************************************************
+ *				GetNumTasks	[KERNEL.152]
+ */
+WORD GetNumTasks()
+{
+	printf("GetNumTasks() returned %d !\n", nTaskCount);
+	return nTaskCount;
+}
+
+
+/**********************************************************************
+ *				GetWindowTask	[USER.224]
+ */
+HTASK GetWindowTask(HWND hWnd)
+{
+	printf("GetWindowTask(%04X) !\n", hWnd);
+	return 0;
+}
+
+
+/**********************************************************************
+ *				EnumTaskWindows	[USER.225]
+ */
+BOOL EnumTaskWindows(HANDLE hTask, FARPROC lpEnumFunc, LONG lParam)
+{
+	printf("EnumTaskWindows(%04X, %08X, %08X) !\n", hTask, lpEnumFunc, lParam);
+	return FALSE;
+}
+
+
+/**********************************************************************
+ *				CreateNewTask		[internal]
+ */
+HANDLE CreateNewTask(HINSTANCE hInst)
+{
+    HANDLE hTask;
+	LPTASKENTRY lpTask = lpTaskList;
+	LPTASKENTRY lpNewTask;
+	if (lpTask != NULL) {
+		while (TRUE) {
+			if (lpTask->lpNextTask == NULL) break;
+			lpTask = lpTask->lpNextTask;
+			}
+		}
+	hTask = GlobalAlloc(GMEM_MOVEABLE, sizeof(TASKENTRY));
+	lpNewTask = (LPTASKENTRY) GlobalLock(hTask);
+#ifdef DEBUG_TASK
+    printf("CreateNewTask entry allocated %08X\n", lpNewTask);
+#endif
+	if (lpNewTask == NULL) return 0;
+	if (lpTaskList == NULL) {
+		lpTaskList = lpNewTask;
+		lpNewTask->lpPrevTask = NULL;
+		}
+	else {
+		lpTask->lpNextTask = lpNewTask;
+		lpNewTask->lpPrevTask = lpTask;
+		}
+	lpNewTask->lpNextTask = NULL;
+	lpNewTask->hIcon = 0;
+	lpNewTask->hModule = 0;
+	lpNewTask->hTask = hTask;
+	lpNewTask->lpWndList = (HWND *) malloc(MAXWIN_PER_TASK * sizeof(HWND));
+	if (lpNewTask->lpWndList != NULL) 
+		memset((LPSTR)lpNewTask->lpWndList, 0, MAXWIN_PER_TASK * sizeof(HWND));
+	lpNewTask->hInst = hInst;
+	lpNewTask->unix_pid = getpid();
+    printf("CreateNewTask // unix_pid=%08X return hTask=%04X\n", 
+									lpNewTask->unix_pid, hTask);
+	GlobalUnlock(hTask);	
+    return hTask;
+}
+
+
+/**********************************************************************
+ *				AddWindowToTask		[internal]
+ */
+BOOL AddWindowToTask(HTASK hTask, HWND hWnd)
+{
+	HWND 	*wptr;
+	int		count = 0;
+	LPTASKENTRY lpTask = lpTaskList;
+	printf("AddWindowToTask(%04X, %04X); !\n", hTask, hWnd);
+	while (TRUE) {
+		if (lpTask->hTask == hTask) break;
+		if (lpTask == NULL) return FALSE;
+		lpTask = lpTask->lpNextTask;
+		}
+	wptr = lpTask->lpWndList;
+	if (wptr == NULL) return FALSE;
+	while (*(wptr++) != 0) {
+		if (++count >= MAXWIN_PER_TASK) return FALSE;
+		}
+	*wptr = hWnd;
+	return TRUE;
+}
+
+
+/**********************************************************************
+ *				RemoveWindowFromTask		[internal]
+ */
+BOOL RemoveWindowFromTask(HTASK hTask, HWND hWnd)
+{
+	HWND 	*wptr;
+	int		count = 0;
+	LPTASKENTRY lpTask = lpTaskList;
+	printf("AddWindowToTask(%04X, %04X); !\n", hTask, hWnd);
+	while (TRUE) {
+		if (lpTask->hTask == hTask) break;
+		if (lpTask == NULL) return FALSE;
+		lpTask = lpTask->lpNextTask;
+		}
+	wptr = lpTask->lpWndList;
+	if (wptr == NULL) return FALSE;
+	while (*(wptr++) != hWnd) {
+		if (++count >= MAXWIN_PER_TASK) return FALSE;
+		}
+	*wptr = 0;
+	return TRUE;
+}
+
+
diff --git a/loader/wine.c b/loader/wine.c
index 4edecaa..8236853 100644
--- a/loader/wine.c
+++ b/loader/wine.c
@@ -49,6 +49,7 @@
 
 static char *DLL_Extensions[] = { "dll", "exe", NULL };
 static char *EXE_Extensions[] = { "exe", NULL };
+static char *WinePath = NULL;
 
 FILE *SpyFp = NULL;
 
@@ -154,7 +155,6 @@
       wpnt1->next  = wpnt;
     };
     wpnt->next = NULL;
-    wpnt->resnamtab = (RESNAMTAB *) -1;
 
     /*
      * Open file for reading.
@@ -248,6 +248,8 @@
      */
     for(i=0; i<wpnt->ne_header->n_mod_ref_tab; i++){
       char buff[14];
+      char buff2[256];
+      int  fd, j;
       GetModuleName(wpnt, i + 1, buff);
       
 #ifndef WINELIB
@@ -263,27 +265,38 @@
 }
 
 
-#ifndef WINELIB
 /**********************************************************************
  *					main
  */
-int _WinMain(int argc, char **argv)
+_WinMain(int argc, char **argv)
 {
 	int segment;
 	char *p;
 	char *sysresname;
 	char filename[100];
+	char syspath[256];
+	char exe_path[256];
 #ifdef WINESTAT
 	char * cp;
 #endif
 	struct w_files * wpnt;
 	int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
+	int i;
 	int rv;
 
 	Argc = argc - 1;
 	Argv = argv + 1;
 	
-	if (LoadImage(Argv[0], EXE) == (HINSTANCE) NULL ) {
+	WinePath = malloc(1024);
+	
+	getcwd(WinePath, 512);
+	
+	if ((p = getenv("WINEPATH")) != NULL) { 
+		strcat(WinePath, ";");
+		strcat(WinePath, p);
+	}
+	
+	if ((hInstMain = LoadImage(Argv[0], EXE)) == (HINSTANCE) NULL ) {
 		fprintf(stderr, "wine: can't find %s!.\n", Argv[0]);
 		exit(1);
 	}
@@ -380,7 +393,6 @@
 	}
     }
 }
-#endif
 
 
 /**********************************************************************
@@ -390,8 +402,10 @@
 GetImportedName(int fd, struct mz_header_s *mz_header, 
 		struct ne_header_s *ne_header, int name_offset, char *buffer)
 {
+    char *p;
     int length;
     int status;
+    int i;
     
     status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
 		   name_offset, SEEK_SET);
@@ -412,6 +426,7 @@
     int fd = wpnt->fd;
     struct mz_header_s *mz_header = wpnt->mz_header; 
     struct ne_header_s *ne_header = wpnt->ne_header;
+    char *p;
     int length;
     WORD name_offset, status;
     int i;
@@ -699,4 +714,16 @@
     return 0;
 }
 
+/**********************************************************************
+ *					GetProcAddress
+ */
+FARPROC GetProcAddress(HINSTANCE hinstance, char *proc_name)
+{
+    if ((int) proc_name & 0xffff0000)
+	printf("GetProcAddress: %#04x, '%s'\n", hinstance, proc_name);
+    else
+	printf("GetProcAddress: %#04x, %d\n", hinstance, (int) proc_name);
+
+    return NULL;
+}
 #endif