Release 970101
Wed Jan 1 15:36:17 1997 Alexandre Julliard <julliard@lrc.epfl.ch>
* [controls/listbox.c]
Use FindFirstFile/FindNextFile in LISTBOX_Directory.
* [files/dos_fs.c]
Rewrote FindFirstFile/FindNextFile to use DOSFS_FindNext().
* [files/file.c] [files/directory.c]
Use Win32 kernel objects and handles for file handles.
Unified SearchPath() and OpenFile().
* [loader/builtin.c]
Moved to if1632/ directory.
* [tools/build.c] [debugger/*] [miscemu/*]
Win16 register functions now receive the same CONTEXT * structure
as Win32 functions.
* [include/sigcontext.h] [miscemu/instr.c]
Added new macros to get register values from the SIGCONTEXT
structure (only used for instruction emulation now).
* [scheduler/process.c] [scheduler/thread.c] (New files)
Allocate process and thread structures.
* [scheduler/process.c] [win32/k32obj.c]
Added Win32 kernel objects and handles management.
* [loader/task.c]
Create a Win32 process and thread for every Win16 task.
* [misc/commdlg.c] [misc/shell.c] [windows/msgbox.c]
Built-in resources are now in Win32 format. This also avoids
16-bit callbacks for built-in dialogs.
* [misc/lzexpand.c]
Differentiate between 16-bit and 32-bit file handles.
* [miscemu/int*.c]
Moved all int emulation to msdos/ directory.
* [msdos/*]
New directory msdos/ contains all MS-DOS emulation code that can
also be used for Winelib; this should enable Winelib apps to use
DOS3Call and related functions.
* [rc/winerc.c]
A few bug fixes for Win32 resource format.
* [windows/winpos.c]
Hack in WINPOS_ReorderOwnerPopups() to avoid X crashed (still not
right though).
Sun Dec 29 17:47:55 1996 O. Flebbe <flebbe@science-computing.uni-tuebingen.de>
* [loader/pe_image.c]
Make sure BSS of a PE_Image is zero.
Sat Dec 28 22:15:34 1996 Alex Korobka <alex@trantor.pharm.sunysb.edu>
* [windows/scroll.c]
ScrollWindowEx() rewrite, ScrollDC() fix.
* [windows/nonclient.c] [controls/menu.c]
Fixed Alt-Space crashes in dialogs.
* [windows/event.c] [windows/message.c]
Some changes in mouse message generation.
Thu Dec 26 09:25:24 1996 Philippe De Muyter <phdm@info.ucl.ac.be>
* [debugger/stabs.c]
Dummy DEBUG_ReadExecutableDbgInfo provided for !__ELF__ case.
Tue Dec 24 00:59:05 MET 1996 Martin Buck <martin-2.buck@student.uni-ulm.de>
* [windows/event.c]
Changed XK_Page_{Up,Down} to XK_{Prior,Next} for X11R5
compatibility.
diff --git a/scheduler/thread.c b/scheduler/thread.c
new file mode 100644
index 0000000..78b71f8
--- /dev/null
+++ b/scheduler/thread.c
@@ -0,0 +1,231 @@
+/*
+ * Win32 threads
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <assert.h>
+#include "thread.h"
+#include "winerror.h"
+#include "heap.h"
+#include "selectors.h"
+#include "winnt.h"
+
+THDB *pCurrentThread = NULL;
+
+
+/***********************************************************************
+ * THREAD_Create
+ */
+THDB *THREAD_Create( PDB32 *pdb, DWORD stack_size )
+{
+ THDB *thdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(THDB) );
+ if (!thdb) return NULL;
+ thdb->header.type = K32OBJ_THREAD;
+ thdb->header.refcount = 1;
+ thdb->process = pdb;
+ thdb->teb.except = (void *)-1;
+ thdb->teb.htask16 = 0; /* FIXME */
+ thdb->teb.stack_sel = 0; /* FIXME */
+ thdb->teb.self = &thdb->teb;
+ thdb->teb.tls_ptr = thdb->tls_array;
+ thdb->process2 = pdb;
+ thdb->exit_code = 0x103; /* STILL_ACTIVE */
+
+ /* Allocate the stack */
+
+ if (!stack_size) stack_size = 1024 * 1024; /* default size = 1Mb */
+ thdb->stack_base = VirtualAlloc( NULL, stack_size, MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE );
+ if (!thdb->stack_base) goto error;
+ /* Un-commit the first page (FIXME: should use PAGE_GUARD instead) */
+ VirtualFree( thdb->stack_base, 1, MEM_DECOMMIT );
+ thdb->teb.stack_top = (char *)thdb->stack_base + stack_size;
+ thdb->teb.stack_low = thdb->teb.stack_top;
+ thdb->exit_stack = thdb->teb.stack_top;
+
+ /* Allocate the TEB selector (%fs register) */
+
+ thdb->teb_sel = SELECTOR_AllocBlock( &thdb->teb, 0x1000, SEGMENT_DATA,
+ TRUE, FALSE );
+ if (!thdb->teb_sel) goto error;
+ return thdb;
+
+error:
+ if (thdb->teb_sel) SELECTOR_FreeBlock( thdb->teb_sel, 1 );
+ if (thdb->stack_base) VirtualFree( thdb->stack_base, 0, MEM_RELEASE );
+ HeapFree( SystemHeap, 0, thdb );
+ return NULL;
+}
+
+
+/***********************************************************************
+ * THREAD_Destroy
+ */
+void THREAD_Destroy( K32OBJ *ptr )
+{
+ THDB *thdb = (THDB *)ptr;
+ assert( ptr->type == K32OBJ_THREAD );
+ ptr->type = K32OBJ_UNKNOWN;
+ SELECTOR_FreeBlock( thdb->teb_sel, 1 );
+ HeapFree( SystemHeap, 0, thdb );
+}
+
+
+/***********************************************************************
+ * GetCurrentThread (KERNEL32.200)
+ */
+HANDLE32 GetCurrentThread(void)
+{
+ return 0xFFFFFFFE;
+}
+
+
+/***********************************************************************
+ * GetCurrentThreadId (KERNEL32.201)
+ */
+DWORD GetCurrentThreadId(void)
+{
+ /* FIXME: should probably use %fs register here */
+ assert( pCurrentThread );
+ return (DWORD)pCurrentThread;
+}
+
+
+/**********************************************************************
+ * GetLastError (KERNEL.148) (KERNEL32.227)
+ */
+DWORD GetLastError(void)
+{
+ THDB *thread = (THDB *)GetCurrentThreadId();
+ return thread->last_error;
+}
+
+
+/**********************************************************************
+ * SetLastError (KERNEL.147) (KERNEL32.497)
+ */
+void SetLastError( DWORD error )
+{
+ THDB *thread;
+ if (!pCurrentThread) return; /* FIXME */
+ thread = (THDB *)GetCurrentThreadId();
+ thread->last_error = error;
+}
+
+
+/**********************************************************************
+ * SetLastErrorEx (USER32.484)
+ */
+void SetLastErrorEx( DWORD error, DWORD type )
+{
+ /* FIXME: what about 'type'? */
+ SetLastError( error );
+}
+
+
+/**********************************************************************
+ * TlsAlloc (KERNEL32.530)
+ */
+DWORD TlsAlloc(void)
+{
+ DWORD i, mask, ret = 0;
+ THDB *thread = (THDB *)GetCurrentThreadId();
+ DWORD *bits = thread->process->tls_bits;
+ EnterCriticalSection( &thread->process->crit_section );
+ if (*bits == 0xffffffff)
+ {
+ bits++;
+ ret = 32;
+ if (*bits == 0xffffffff)
+ {
+ LeaveCriticalSection( &thread->process->crit_section );
+ SetLastError( ERROR_NO_MORE_ITEMS );
+ return 0xffffffff;
+ }
+ }
+ for (i = 0, mask = 1; i < 32; i++, mask <<= 1) if (!(*bits & mask)) break;
+ *bits |= mask;
+ LeaveCriticalSection( &thread->process->crit_section );
+ return ret + i;
+}
+
+
+/**********************************************************************
+ * TlsFree (KERNEL32.531)
+ */
+BOOL32 TlsFree( DWORD index )
+{
+ DWORD mask;
+ THDB *thread = (THDB *)GetCurrentThreadId();
+ DWORD *bits = thread->process->tls_bits;
+ if (index >= 64)
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ EnterCriticalSection( &thread->process->crit_section );
+ if (index >= 32) bits++;
+ mask = (1 << (index & 31));
+ if (!(*bits & mask)) /* already free? */
+ {
+ LeaveCriticalSection( &thread->process->crit_section );
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ *bits &= ~mask;
+ thread->tls_array[index] = 0;
+ /* FIXME: should zero all other thread values */
+ LeaveCriticalSection( &thread->process->crit_section );
+ return TRUE;
+}
+
+
+/**********************************************************************
+ * TlsGetValue (KERNEL32.532)
+ */
+LPVOID TlsGetValue( DWORD index )
+{
+ THDB *thread = (THDB *)GetCurrentThreadId();
+ if (index >= 64)
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return NULL;
+ }
+ SetLastError( ERROR_SUCCESS );
+ return thread->tls_array[index];
+}
+
+
+/**********************************************************************
+ * TlsSetValue (KERNEL32.533)
+ */
+BOOL32 TlsSetValue( DWORD index, LPVOID value )
+{
+ THDB *thread = (THDB *)GetCurrentThreadId();
+ if (index >= 64)
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ thread->tls_array[index] = value;
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * GetThreadContext (KERNEL32.294)
+ */
+BOOL32 GetThreadContext( HANDLE32 handle, CONTEXT *context )
+{
+ return FALSE;
+}
+
+
+/**********************************************************************
+ * NtCurrentTeb (NTDLL.89)
+ */
+void NtCurrentTeb( CONTEXT *context )
+{
+ EAX_reg(context) = GetSelectorBase( FS_reg(context) );
+}