Release 980927
Sun Sep 27 14:25:38 1998 Petter Reinholdtsen <pere@td.org.uit.no>
* [files/drive.c]
Make sure GetDriveType32A() handles param NULL. Added some
doc on function.
Sun Sep 27 14:07:26 1998 Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>
* [controls/edit.c] [windows/win.c]
Don't call SetWindowLong() in EDIT_WM_NCREATE.
Fix SetWindowLong(GWL_[EX]STYLE) to work for 16bit windows. Remove
UpdateWindow() call.
Sun Sep 27 13:41:22 1998 Alexandre Julliard <julliard@lrc.epfl.ch>
* [scheduler/*.c] [server/event.c] [server/mutex.c]
[server/semaphore.c]
Implemented server-side synchronisation objects.
Sun Sep 27 01:13:35 1998 Alex Priem <alexp@sci.kun.nl>
* [dlls/comctl32/treeview.c] [include/treeview.h] [include/comctl.h]
Treeview implementation.
* [dlls/comctl32/trackbar.c] [include/trackbar.h]
Trackbar implementation.
Sat Sep 26 20:49:13 1998 Ulrich Weigand <weigand@informatik.uni-erlangen.de>
* [if1632/thunk.c] [tools/build.c] [win32/kernel32.c]
Bugfix: several problems with flat thunks fixed.
* [memory/selector.c]
Bugfix: IsBad...Ptr16 didn't work for limit_in_pages segments.
* [scheduler/thread.c]
Bugfix: CreateThread: Allow id parameter == NULL.
* [objects/gdiobj.c]
Bugfix: IsGDIObject: Return correct object type for stock objects.
* [msdos/dpmi.c]
Bugfix: fixed typo in INT_DoRealModeInt.
* [msdos/int21.c]
Bugfix: int21 READ *must* use WIN16_hread, not _hread16.
* [if1632/kernel.spec] [if1632/dummy.c] [if1632/thunk.c]
[loader/ne/module.c] [scheduler/event.c] [scheduler/synchro.c]
[scheduler/thread.c] [win32/kernel32.c] [win32/ordinals.c]
Added names/stubs for all undocumented KERNEL routines (Win95).
Added the following undoc. 16-bit equivalents to Win32 routines:
KERNEL.441-443,449-453,456-462,471-476,479-486,488.
Added stubs for some other KERNEL routines.
* [memory/heap.c] [memory/global.c] [include/global.h]
Implemented Local32... 32-bit local heap routines (KERNEL.208-215, 229).
* [miscemu/instr.c] [loader/module.c] [include/module.h]
Implemented __GP fault handling and HasGPHandler (KERNEL.338).
* [misc/error.c]
Implemented LogParamErrorRegs (KERNEL.327).
* [loader/task.c] [include/windows.h]
Implemented GetCodeInfo (KERNEL.104).
* [loader/task.c] [scheduler/thread.c] [include/thread.h]
Implemented [GS]etThreadQueue and [GS]etFastQueue (KERNEL.463/4, 624/5).
* [if1632/gdi.spec] [objects/dc.c] [objects/dib.c]
[objects/bitmap.c] [include/windows.h]
Bugfix: fixed wrong parameter for CreateDIBSection16.
Added [GS]etDIBColorTable16, stub for GetBoundsRect16.
Partially implemented BITMAP_GetObject16 for DIBs.
* [if1632/gdi.spec] [relay32/gdi32.spec] [objects/palette.c]
Added some GDI stubs.
* [if1632/Makefile.in] [if1632/display.spec] [if1632/mouse.spec]
[if1632/keyboard.spec] [if1632/builtin.c] [windows/keyboard.c]
Added some stubs for Win16 drivers: KEYBOARD, MOUSE, DISPLAY.
* [if1632/wprocs.spec] [msdos/vxd.c]
Added some stubs for VxDs: VMM, ConfigMG, TimerAPI.
* [msdos/int2f.c]
Added some stubs for real-mode network drivers.
Sat Sep 26 18:18:18 1998 Marcus Meissner <marcus@jet.franken.de>
* [configure.in]
Merged in some more of the FreeBSD ports/emulators/wine patches.
(Maintainer(s) of this port: You can just submit these
patches to Alexandre directly.)
* [loader/pe_image.c]
Check filesize of image against size derived from header
to spot truncated executeables without crashing.
* [files/directory.c]
Set envvar "COMSPEC". One win32(!!) program crashes without it.
* [multimedia/mmio.c]
Added mmioSetInfo32.
* [include/file.h]
Return STD_ERROR_HANDLE for AUX and PRT dos handles.
* [loader/module.c]
Handle executeables with spaces in their names a bit better in
CreateProcess.
* [relay32/msvfw32.spec][if1632/msvideo.spec][multimedia/msvideo.c][include/vfw.h]
Started on MS Video support (can load Win32 ICMs).
* [tools/testrun]
A bit smarter use of ps.
* [memory/virtual.c]
Report PAGE_GUARDed pages as PAGE_PROTECTED (AutoCAD LT R17 fails
without that check (since Win95 doesn't know about PAGE_GUARD)).
Sat Sep 26 15:04:05 1998 Ove Kaaven <ovek@arcticnet.no>
* [include/miscemu.h] [if1632/builtin.c] [loader/task.c]
[miscemu/instr.c] [msdos/dpmi.c] [msdos/int21.c]
[msdos/interrupts.c] [windows/user.c]
INT_[S|G]etHandler was renamed to INT_[S|G]etPMHandler.
Added handlers to deal with real-mode interrupts; DOS
programs are now able to hook real-mode interrupts.
* [loader/dos/module.c] [msdos/dosmem.c] [msdos/int21.c]
Moved real-mode interrupt table initialization to
msdos/dosmem.c, and made new V86 tasks get a full copy
of the existing "system memory" instead of almost empty
space. Misc fixes.
* [include/dosexe.h] [loader/dos/module.c] [msdos/dpmi.c]
[msdos/int2f.c]
First shot at letting DOS programs start up DPMI (but DPMI
is still disabled for DOS programs, for pkunzip's sake).
* [include/debugger.h] [debugger/break.c] [debugger/dbg.y]
[debugger/registers.c] [debugger/memory.c] [debugger/info.c]
[loader/dos/dosvm.c]
First shot at making Wine's debugger work for DOS programs.
The -debug flag works, as do "nexti" and "stepi".
Sat Sep 26 13:13:13 1998 Juergen Schmied <juergen.schmied@metronet.de>
* [dlls/shell32/dataobject.c]
New classes IEnumFORMATETC implemented, IDataObject stubs.
* [dlls/shell32/*.*][relay32/shell32.spec]
Bugfixes.
New: ICM_InsertItem(), ILCreateFromPath().
Implemented: ILCloneFirst().
Stubs: ILIsEqual(), ILFindChild(), SHLogILFromFSIL(),
PathMatchSpec(), PathIsExe().
Changed: ILGetSize(), _ILIsDesktop(), PathCombine().
* [include/shlobj.h]
New SHLGUID's
New structures: DVTARGETDEVICE32, STGMEDIUM32, FORMATETC32,
CLIPFORMAT32.
New interfaces: IEnumFORMATETC, IDataObject, ICommDlgBrowser
IDockingWindowFrame, IServiceProvider.
* [dlls/shell32/folders.c]
Stubs for IShellLink.
* [loader/resource.c]
Small fixes.
* [misc/crtdll.c][relay32/crtdll.spec]
New __dllonexit().
* [windows/message.c]
SendNotifyMessageA, SendMessageCallBack32A half implemented.
* [controls/edit.c]
EDIT_WM_SetText set EF_UPDATE flag not for ES_MULTILINE.
* [files/file.c]
Handling of fileposition fixed.
Fri Sep 25 18:13:30 1998 Patrik Stridvall <ps@leissner.se>
* [include/windows.h] [include/wintypes.h]
[ole/ole2nls.h] [relay32/kernel32.spec]
Implemented EnumDateFormats and EnumTimeFormats.
Only adds US English support.
* [Makefile.in] [configure.in]
[dlls/Makefile.in] [dlls/psapi/Makefile.in]
[dlls/psapi/psapi_main.c]
New files to implement stubs for PSAPI.DLL (NT only).
* [relay32/Makefile.in] [relay32/builtin32.c]
[relay32/psapi.spec]
New spec file for PSAPI.DLL (NT only).
* [scheduler/handle.c]
HANDLE_GetObjPtr should only interpret the pseudo handles as the
current thread or the current process if a thread or a process is
requested.
* [include/winversion.h] [misc/version.c]
Adds the global function VERSION_GetVersion() so functions can
have different behavior depending on the -winver flag.
* [include/oledlg.h] [ole/oledlg.c]
Minor fixes.
* [windows/winproc.c]
Minor changes.
* [include/imm.h] [misc/imm.c]
Now returns correct values under both Windows 95 and NT 4.0.
Thu Sep 24 22:11:44 1998 Kristian Nielsen <kristian.nielsen@risoe.dk>
* [configure.in] [include/acconfig.h] [include/thread.h]
[scheduler/sysdeps.c]
Autoconfig test for non-reentrant libc.
Wed Sep 23 19:52:12 1998 Matthew Becker <mbecker@glasscity.net>
* [*/*.c]
Miscellaneous documentation updates and debugging output
standardizations.
* [objects/clipping.c]
Added ExtSelectClipRgn.
Wed Sep 23 00:03:28 EDT 1998 Pete Ratzlaff <pratzlaff@cfa.harvard.edu>
* [include/windows.h] [if1632/user.spec] [relay32/user32.spec]
[windows/keyboard.c]
Added, marginally implemented, GetKeyboardLayoutName().
Only returns US English keyboard name.
Tue Sep 22 16:32:41 1998 Marcel Baur <mbaur@iiic.ethz.ch>
* [programs/control/*]
New Winelib application.
Mon Sep 21 00:29:18 1998 Peter Hunnisett <hunnise@nortel.ca>
* [include/dplay.h][multimedia/dplay.c][ole/compobj.c]
Added all DirectPlayLobby interfaces and enhanced DirectPlay
and DirectPlayLobby support. Still not all that much. Useful
enough if you just need to start a program, don't try any
real dplay/lobby stuff.
* [documentation/status/directplay]
Added a very little bit.
* [graphics/ddraw.c]
- Call to SetWindowLong32A wasn't working because there was no
memory set aside when the window class was registered.
- Fixed some xlib reference counting and change the behaviour
of DirectDrawSurface3_SetPalette to mimic observed behaviour
(palette is associated will all backbuffers)
- Also stored all palette colour fields and spit back our saved
colour fields rather than query X for them.
- Added plenty of AddRef and Release traces.
- Added Xlib support for using -desktop option.
- Fixed Xlib message handling. Messages weren't being passed to
the application. Fixes mouse movements in some xlib DDraw games.
- Added a few stubs.
* [windows/win.c][include/winerror.h]
Fixed up some error handling in WIN_SetWindowLong. SetLastError
wasn't being used. Could cause problems with 0 return codes.
Added new error in winerror (1400).
* [AUTHORS] [include/authors.h]
Added myself as a Wine author.
Sun Sep 20 21:22:44 1998 Alexander Larsson <alla@lysator.liu.se>
* [loader/module.c]
Changed GetModuleFileName32A so that is returns the
long version of the filename. Note that just the name
is long, not the directories.
Sat Sep 19 20:05:30 1998 Per Ångström <pang@mind.nu>
* [controls/menu.c]
Made a couple of fixes to make life easier for applications that alter
their menus at runtime.
* [windows/defdlg.c]
Removed the cast of the return value from dialog procedures to a 16-bit
bool. The return value needs to retain all its 32 bits, since it is not
always a bool, such as when responding to the WM_NCHITTEST message.
Fri Sep 18 11:30:38 1998 Sergey Turchanov <turchanov@usa.net>
* [loader/resource.c]
Fixed very funny bug (though gravely affecting further excecution)
with FindResource[Ex]32 functions.
* [include/multimon.h] [windows/multimon.c] [relay32/user32.spec]
[include/windows.h] [windows/sysmetrics.c]
Default implementation for Multimonitor API.
* [include/windows.h] [windows/winpos.c]
Fixed incorrect declaration (and behaviour) of GetWindowRect32.
Wed Sep 16 10:21:15 1998 Gerard Patel <G.Patel@Wanadoo.fr>
* [controls/edit.c]
Fixed EDIT_EM_GetLine to use correctly length of lines.
Tue Sep 15 20:40:16 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
* [misc/tweak.c][include/tweak.h][controls/menu.c]
Replaced the tweak graphic routines by calls to DrawEdge32().
* [misc/tweak.c][include/tweak.h][documentation/win95look]
[wine.ini][*/*]
Changed "look and feel" selection. Allows Win3.1, Win95 and
Win98 (no GUI code implemented) look and feel.
* [dlls/comctl32/header.c][include/header.h][include/commctrl.h]
Started callback item support and did some minor improvements.
* [dlls/comctl32/imagelist.c]
Fixed bug in transparent image display.
ImageList_GetIcon is still buggy :-(
* [dlls/comctl32/toolbar.c]
Fixed button drawing (partial hack).
* [dlls/comctl32/commctrl.c]
Fixed MenuHelp().
* [controls/button.c]
Added 3d effect for groupbox.
* [windows/msgbox.c]
Added font support for message boxes.
* [windows/nonclient.c]
Fixed window moving bug.
* [dlls/comctl32/*.c]
Various improvements.
* [dlls/comctl32/listview.c][dlls/comctl32/rebar.c]
[include/commctrl.h]
More messages.
* [windows/syscolor.c][include/windows.h]
Introduced new Win98 system colors.
Tue Sep 15 18:29:45 1998 Wesley Filardo <eightknots@aol.com>
* [files/profile.c]
Added support in PROFILE_LoadWineIni for -config option
* [misc/main.c] [include/options.h]
Added -config option.
Tue Sep 15 18:22:26 1998 Petter Reinholdtsen <pere@td.org.uit.no>
* [documentation/Makefile.in]
Make sure directory exists before installing into it.
Tue Sep 15 01:47:33 1998 Pablo Saratxaga <pablo.sarachaga@ping.be>
* [ole/nls/*] [ole/ole2nls.c] [include/winnls.h]
Fixed a few errors and completed some NLS files.
Mon Sep 14 01:23:45 1998 Joseph Pranevich <knight@baltimore.wwaves.com>
* [include/miscemu.h] [msdos/interrupts.c]
Removed a compilation warning, added INT 25 to the list of interrupts
callable from DOS applications, added a debug message when unsupported
interrupts are used.
Sun Sep 13 19:55:22 1998 Lawson Whitney <lawson_whitney@juno.com>
* [if1632/relay.c]
CallProcEx32W should not reverse arguments.
Sun Aug 17 21:18:12 1998 Eric Pouech <eric.pouech@lemel.fr>
* [multimedia/midi.c] [multimedia/init.c] [multimedia/mmsys.c]
[include/multimedia.h] [include/mmsystem.h]
[multimedia/Makefile.in] [multimedia/midipatch.c]
[if1632/multimedia.spec]
Made MIDI input and output functional on OSS capable systems.
* [multimedia/timer.c]
Changes to trigger callbacks at the accurate pace even when
fake timers are used.
diff --git a/memory/global.c b/memory/global.c
index fd8bb5b..799eb9f 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -3,6 +3,7 @@
*
* Copyright 1995 Alexandre Julliard
*/
+/* 0xffff sometimes seems to mean: CURRENT_DS */
#include <sys/types.h>
#include <stdlib.h>
@@ -173,6 +174,30 @@
return TRUE;
}
+/***********************************************************************
+ * GLOBAL_MoveBlock
+ */
+BOOL16 GLOBAL_MoveBlock( HGLOBAL16 handle, const void *ptr, DWORD size )
+{
+ WORD sel;
+ GLOBALARENA *pArena;
+
+ if (!handle) return TRUE;
+ sel = GlobalHandleToSel( handle );
+ if (!VALID_HANDLE(sel))
+ return FALSE;
+ pArena = GET_ARENA_PTR(sel);
+ if (pArena->selCount != 1)
+ return FALSE;
+
+ pArena->base = (DWORD)ptr;
+ pArena->size = size;
+
+ SELECTOR_MoveBlock( sel, ptr );
+ SetSelectorLimit( sel, size-1 );
+
+ return TRUE;
+}
/***********************************************************************
* GLOBAL_Alloc
diff --git a/memory/heap.c b/memory/heap.c
index 3bcc396..05dc8fa 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -2,6 +2,7 @@
* Win32 heap functions
*
* Copyright 1996 Alexandre Julliard
+ * Copyright 1998 Ulrich Weigand
*/
#include <assert.h>
@@ -9,6 +10,7 @@
#include <string.h>
#include "windows.h"
#include "selectors.h"
+#include "global.h"
#include "winbase.h"
#include "winerror.h"
#include "winnt.h"
@@ -426,17 +428,104 @@
}
}
+/***********************************************************************
+ * HEAP_InitSubHeap
+ */
+static BOOL32 HEAP_InitSubHeap( HEAP *heap, LPVOID address, DWORD flags,
+ DWORD commitSize, DWORD totalSize )
+{
+ SUBHEAP *subheap = (SUBHEAP *)address;
+ WORD selector = 0;
+ FREE_LIST_ENTRY *pEntry;
+ int i;
+
+ /* Commit memory */
+
+ if (!VirtualAlloc(address, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
+ {
+ WARN(heap, "Could not commit %08lx bytes for sub-heap %08lx\n",
+ commitSize, (DWORD)address );
+ return FALSE;
+ }
+
+ /* Allocate a selector if needed */
+
+ if (flags & HEAP_WINE_SEGPTR)
+ {
+ selector = SELECTOR_AllocBlock( address, totalSize,
+ (flags & HEAP_WINE_CODESEG) ? SEGMENT_CODE : SEGMENT_DATA,
+ (flags & HEAP_WINE_CODESEG) != 0, FALSE );
+ if (!selector)
+ {
+ WARN(heap, "Could not allocate selector\n" );
+ return FALSE;
+ }
+ }
+
+ /* Fill the sub-heap structure */
+
+ subheap->heap = heap;
+ subheap->selector = selector;
+ subheap->size = totalSize;
+ subheap->commitSize = commitSize;
+ subheap->magic = SUBHEAP_MAGIC;
+
+ if ( subheap != (SUBHEAP *)heap )
+ {
+ /* If this is a secondary subheap, insert it into list */
+
+ subheap->headerSize = sizeof(SUBHEAP);
+ subheap->next = heap->subheap.next;
+ heap->subheap.next = subheap;
+ }
+ else
+ {
+ /* If this is a primary subheap, initialize main heap */
+
+ subheap->headerSize = sizeof(HEAP);
+ subheap->next = NULL;
+ heap->next = NULL;
+ heap->flags = flags;
+ heap->magic = HEAP_MAGIC;
+
+ /* Build the free lists */
+
+ for (i = 0, pEntry = heap->freeList; i < HEAP_NB_FREE_LISTS; i++, pEntry++)
+ {
+ pEntry->size = HEAP_freeListSizes[i];
+ pEntry->arena.size = 0 | ARENA_FLAG_FREE;
+ pEntry->arena.next = i < HEAP_NB_FREE_LISTS-1 ?
+ &heap->freeList[i+1].arena : &heap->freeList[0].arena;
+ pEntry->arena.prev = i ? &heap->freeList[i-1].arena :
+ &heap->freeList[HEAP_NB_FREE_LISTS-1].arena;
+ pEntry->arena.threadId = 0;
+ pEntry->arena.magic = ARENA_FREE_MAGIC;
+ }
+
+ /* Initialize critical section */
+
+ InitializeCriticalSection( &heap->critSection );
+ if (!SystemHeap) HEAP_SystemLock = &heap->critSection;
+ }
+
+ /* Create the first free block */
+
+ HEAP_CreateFreeBlock( subheap, (LPBYTE)subheap + subheap->headerSize,
+ subheap->size - subheap->headerSize );
+
+ return TRUE;
+}
/***********************************************************************
* HEAP_CreateSubHeap
*
* Create a sub-heap of the given size.
+ * If heap == NULL, creates a main heap.
*/
-static SUBHEAP *HEAP_CreateSubHeap( DWORD flags, DWORD commitSize,
- DWORD totalSize )
+static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, DWORD flags,
+ DWORD commitSize, DWORD totalSize )
{
- SUBHEAP *subheap;
- WORD selector = 0;
+ LPVOID address;
/* Round-up sizes on a 64K boundary */
@@ -454,46 +543,24 @@
/* Allocate the memory block */
- if (!(subheap = VirtualAlloc( NULL, totalSize,
+ if (!(address = VirtualAlloc( NULL, totalSize,
MEM_RESERVE, PAGE_EXECUTE_READWRITE )))
{
WARN(heap, "Could not VirtualAlloc %08lx bytes\n",
totalSize );
return NULL;
}
- if (!VirtualAlloc(subheap, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
+
+ /* Initialize subheap */
+
+ if (!HEAP_InitSubHeap( heap? heap : (HEAP *)address,
+ address, flags, commitSize, totalSize ))
{
- WARN(heap, "Could not commit %08lx bytes for sub-heap %08lx\n",
- commitSize, (DWORD)subheap );
- VirtualFree( subheap, 0, MEM_RELEASE );
+ VirtualFree( address, 0, MEM_RELEASE );
return NULL;
}
- /* Allocate a selector if needed */
-
- if (flags & HEAP_WINE_SEGPTR)
- {
- selector = SELECTOR_AllocBlock( subheap, totalSize,
- (flags & HEAP_WINE_CODESEG) ? SEGMENT_CODE : SEGMENT_DATA,
- (flags & HEAP_WINE_CODESEG) != 0, FALSE );
- if (!selector)
- {
- WARN(heap, "Could not allocate selector\n" );
- VirtualFree( subheap, 0, MEM_RELEASE );
- return NULL;
- }
- }
-
- /* Fill the sub-heap structure */
-
- subheap->size = totalSize;
- subheap->commitSize = commitSize;
- subheap->headerSize = sizeof(*subheap);
- subheap->next = NULL;
- subheap->heap = NULL;
- subheap->magic = SUBHEAP_MAGIC;
- subheap->selector = selector;
- return subheap;
+ return (SUBHEAP *)address;
}
@@ -538,20 +605,13 @@
return NULL;
}
size += sizeof(SUBHEAP) + sizeof(ARENA_FREE);
- if (!(subheap = HEAP_CreateSubHeap( heap->flags, size,
+ if (!(subheap = HEAP_CreateSubHeap( heap, heap->flags, size,
MAX( HEAP_DEF_SIZE, size ) )))
return NULL;
- /* Insert the new sub-heap in the list */
-
- subheap->heap = heap;
- subheap->next = heap->subheap.next;
- heap->subheap.next = subheap;
- size = subheap->size;
TRACE(heap, "created new sub-heap %08lx of %08lx bytes for heap %08lx\n",
- (DWORD)subheap, size, (DWORD)heap );
+ (DWORD)subheap, size, (DWORD)heap );
- HEAP_CreateFreeBlock( subheap, subheap + 1, size - sizeof(*subheap) );
*ppSubHeap = subheap;
return (ARENA_FREE *)(subheap + 1);
}
@@ -809,10 +869,7 @@
DWORD initialSize, /* [in] Initial heap size */
DWORD maxSize /* [in] Maximum heap size */
) {
- int i;
- HEAP *heap;
SUBHEAP *subheap;
- FREE_LIST_ENTRY *pEntry;
/* Allocate the heap block */
@@ -821,50 +878,15 @@
maxSize = HEAP_DEF_SIZE;
flags |= HEAP_GROWABLE;
}
- if (!(subheap = HEAP_CreateSubHeap( flags, initialSize, maxSize )))
+ if (!(subheap = HEAP_CreateSubHeap( NULL, flags, initialSize, maxSize )))
{
SetLastError( ERROR_OUTOFMEMORY );
return 0;
}
- /* Fill the heap structure */
-
- heap = (HEAP *)subheap;
- subheap->heap = heap;
- subheap->headerSize = sizeof(HEAP);
- heap->next = NULL;
- heap->flags = flags;
- heap->magic = HEAP_MAGIC;
-
- /* Build the free lists */
-
- for (i = 0, pEntry = heap->freeList; i < HEAP_NB_FREE_LISTS; i++, pEntry++)
- {
- pEntry->size = HEAP_freeListSizes[i];
- pEntry->arena.size = 0 | ARENA_FLAG_FREE;
- pEntry->arena.next = i < HEAP_NB_FREE_LISTS-1 ?
- &heap->freeList[i+1].arena : &heap->freeList[0].arena;
- pEntry->arena.prev = i ? &heap->freeList[i-1].arena :
- &heap->freeList[HEAP_NB_FREE_LISTS-1].arena;
- pEntry->arena.threadId = 0;
- pEntry->arena.magic = ARENA_FREE_MAGIC;
- }
-
- /* Create the first free block */
-
- HEAP_CreateFreeBlock( subheap, heap + 1, subheap->size - sizeof(*heap) );
-
- /* Initialize critical section */
-
- InitializeCriticalSection( &heap->critSection );
- if (!SystemHeap) HEAP_SystemLock = &heap->critSection;
-
- /* We are done */
-
- return (HANDLE32)heap;
+ return (HANDLE32)subheap;
}
-
/***********************************************************************
* HeapDestroy (KERNEL32.337)
* RETURNS
@@ -1354,3 +1376,453 @@
lstrcpyWtoA( ret, str );
return ret;
}
+
+
+
+/***********************************************************************
+ * 32-bit local heap functions (Win95; undocumented)
+ */
+
+#define HTABLE_SIZE 0x10000
+#define HTABLE_PAGESIZE 0x1000
+#define HTABLE_NPAGES (HTABLE_SIZE / HTABLE_PAGESIZE)
+
+#pragma pack(1)
+typedef struct _LOCAL32HEADER
+{
+ WORD freeListFirst[HTABLE_NPAGES];
+ WORD freeListSize[HTABLE_NPAGES];
+ WORD freeListLast[HTABLE_NPAGES];
+
+ DWORD selectorTableOffset;
+ WORD selectorTableSize;
+ WORD selectorDelta;
+
+ DWORD segment;
+ LPBYTE base;
+
+ DWORD limit;
+ DWORD flags;
+
+ DWORD magic;
+ HANDLE32 heap;
+
+} LOCAL32HEADER;
+#pragma pack(4)
+
+#define LOCAL32_MAGIC ((DWORD)('L' | ('H'<<8) | ('3'<<16) | ('2'<<24)))
+
+/***********************************************************************
+ * Local32Init (KERNEL.208)
+ */
+HANDLE32 WINAPI Local32Init( WORD segment, DWORD tableSize,
+ DWORD heapSize, DWORD flags )
+{
+ DWORD totSize, segSize = 0;
+ LPBYTE base;
+ LOCAL32HEADER *header;
+ HEAP *heap;
+ WORD *selectorTable;
+ WORD selectorEven, selectorOdd;
+ int i, nrBlocks;
+
+ /* Determine new heap size */
+
+ if ( segment )
+ if ( (segSize = GetSelectorLimit( segment )) == 0 )
+ return 0;
+ else
+ segSize++;
+
+ if ( heapSize == -1L )
+ heapSize = 1024L*1024L; /* FIXME */
+
+ heapSize = (heapSize + 0xffff) & 0xffff0000;
+ segSize = (segSize + 0x0fff) & 0xfffff000;
+ totSize = segSize + HTABLE_SIZE + heapSize;
+
+
+ /* Allocate memory and initialize heap */
+
+ if ( !(base = VirtualAlloc( NULL, totSize, MEM_RESERVE, PAGE_READWRITE )) )
+ return 0;
+
+ if ( !VirtualAlloc( base, segSize + HTABLE_PAGESIZE,
+ MEM_COMMIT, PAGE_READWRITE ) )
+ {
+ VirtualFree( base, 0, MEM_RELEASE );
+ return 0;
+ }
+
+ heap = (HEAP *)(base + segSize + HTABLE_SIZE);
+ if ( !HEAP_InitSubHeap( heap, (LPVOID)heap, 0, 0x10000, heapSize ) )
+ {
+ VirtualFree( base, 0, MEM_RELEASE );
+ return 0;
+ }
+
+
+ /* Set up header and handle table */
+
+ header = (LOCAL32HEADER *)(base + segSize);
+ header->base = base;
+ header->limit = HTABLE_PAGESIZE-1;
+ header->flags = 0;
+ header->magic = LOCAL32_MAGIC;
+ header->heap = (HANDLE32)heap;
+
+ header->freeListFirst[0] = sizeof(LOCAL32HEADER);
+ header->freeListLast[0] = HTABLE_PAGESIZE - 4;
+ header->freeListSize[0] = (HTABLE_PAGESIZE - sizeof(LOCAL32HEADER)) / 4;
+
+ for (i = header->freeListFirst[0]; i < header->freeListLast[0]; i += 4)
+ *(DWORD *)((LPBYTE)header + i) = i+4;
+
+ header->freeListFirst[1] = 0xffff;
+
+
+ /* Set up selector table */
+
+ nrBlocks = (totSize + 0x7fff) >> 15;
+ selectorTable = (LPWORD) HeapAlloc( header->heap, 0, nrBlocks * 2 );
+ selectorEven = SELECTOR_AllocBlock( base, totSize,
+ SEGMENT_DATA, FALSE, FALSE );
+ selectorOdd = SELECTOR_AllocBlock( base + 0x8000, totSize - 0x8000,
+ SEGMENT_DATA, FALSE, FALSE );
+
+ if ( !selectorTable || !selectorEven || !selectorOdd )
+ {
+ if ( selectorTable ) HeapFree( header->heap, 0, selectorTable );
+ if ( selectorEven ) SELECTOR_FreeBlock( selectorEven, totSize >> 16 );
+ if ( selectorOdd ) SELECTOR_FreeBlock( selectorOdd, (totSize-0x8000) >> 16 );
+ HeapDestroy( header->heap );
+ VirtualFree( base, 0, MEM_RELEASE );
+ return 0;
+ }
+
+ header->selectorTableOffset = (LPBYTE)selectorTable - header->base;
+ header->selectorTableSize = nrBlocks * 4; /* ??? Win95 does it this way! */
+ header->selectorDelta = selectorEven - selectorOdd;
+ header->segment = segment? segment : selectorEven;
+
+ for (i = 0; i < nrBlocks; i++)
+ selectorTable[i] = (i & 1)? selectorOdd + ((i >> 1) << __AHSHIFT)
+ : selectorEven + ((i >> 1) << __AHSHIFT);
+
+ /* Move old segment */
+
+ if ( segment )
+ {
+ /* FIXME: This is somewhat ugly and relies on implementation
+ details about 16-bit global memory handles ... */
+
+ LPBYTE oldBase = (LPBYTE)GetSelectorBase( segment );
+ memcpy( base, oldBase, segSize );
+ GLOBAL_MoveBlock( segment, base, totSize );
+ HeapFree( SystemHeap, 0, oldBase );
+ }
+
+ return (HANDLE32)header;
+}
+
+/***********************************************************************
+ * Local32_SearchHandle
+ */
+static LPDWORD Local32_SearchHandle( LOCAL32HEADER *header, DWORD addr )
+{
+ LPDWORD handle;
+
+ for ( handle = (LPDWORD)((LPBYTE)header + sizeof(LOCAL32HEADER));
+ handle < (LPDWORD)((LPBYTE)header + header->limit);
+ handle++)
+ {
+ if (*handle == addr)
+ return handle;
+ }
+
+ return NULL;
+}
+
+/***********************************************************************
+ * Local32_ToHandle
+ */
+static VOID Local32_ToHandle( LOCAL32HEADER *header, INT16 type,
+ DWORD addr, LPDWORD *handle, LPBYTE *ptr )
+{
+ *handle = NULL;
+ *ptr = NULL;
+
+ switch (type)
+ {
+ case -2: /* 16:16 pointer, no handles */
+ *ptr = PTR_SEG_TO_LIN( addr );
+ *handle = (LPDWORD)*ptr;
+ break;
+
+ case -1: /* 32-bit offset, no handles */
+ *ptr = header->base + addr;
+ *handle = (LPDWORD)*ptr;
+ break;
+
+ case 0: /* handle */
+ if ( addr >= sizeof(LOCAL32HEADER)
+ && addr < header->limit && !(addr & 3)
+ && *(LPDWORD)((LPBYTE)header + addr) >= HTABLE_SIZE )
+ {
+ *handle = (LPDWORD)((LPBYTE)header + addr);
+ *ptr = header->base + **handle;
+ }
+ break;
+
+ case 1: /* 16:16 pointer */
+ *ptr = PTR_SEG_TO_LIN( addr );
+ *handle = Local32_SearchHandle( header, *ptr - header->base );
+ break;
+
+ case 2: /* 32-bit offset */
+ *ptr = header->base + addr;
+ *handle = Local32_SearchHandle( header, *ptr - header->base );
+ break;
+ }
+}
+
+/***********************************************************************
+ * Local32_FromHandle
+ */
+static VOID Local32_FromHandle( LOCAL32HEADER *header, INT16 type,
+ DWORD *addr, LPDWORD handle, LPBYTE ptr )
+{
+ switch (type)
+ {
+ case -2: /* 16:16 pointer */
+ case 1:
+ {
+ WORD *selTable = (LPWORD)(header->base + header->selectorTableOffset);
+ DWORD offset = (LPBYTE)ptr - header->base;
+ *addr = MAKELONG( offset & 0x7fff, selTable[offset >> 15] );
+ }
+ break;
+
+ case -1: /* 32-bit offset */
+ case 2:
+ *addr = ptr - header->base;
+ break;
+
+ case 0: /* handle */
+ *addr = (LPBYTE)handle - (LPBYTE)header;
+ break;
+ }
+}
+
+/***********************************************************************
+ * Local32Alloc (KERNEL.209)
+ */
+DWORD WINAPI Local32Alloc( HANDLE32 heap, DWORD size, INT16 type, DWORD flags )
+{
+ LOCAL32HEADER *header = (LOCAL32HEADER *)heap;
+ LPDWORD handle;
+ LPBYTE ptr;
+ DWORD addr;
+
+ /* Allocate memory */
+ ptr = HeapAlloc( header->heap,
+ (flags & LMEM_MOVEABLE)? HEAP_ZERO_MEMORY : 0, size );
+ if (!ptr) return 0;
+
+
+ /* Allocate handle if requested */
+ if (type >= 0)
+ {
+ int page, i;
+
+ /* Find first page of handle table with free slots */
+ for (page = 0; page < HTABLE_NPAGES; page++)
+ if (header->freeListFirst[page] != 0)
+ break;
+ if (page == HTABLE_NPAGES)
+ {
+ WARN( heap, "Out of handles!\n" );
+ HeapFree( header->heap, 0, ptr );
+ return 0;
+ }
+
+ /* If virgin page, initialize it */
+ if (header->freeListFirst[page] == 0xffff)
+ {
+ if ( !VirtualAlloc( (LPBYTE)header + (page << 12),
+ 0x1000, MEM_COMMIT, PAGE_READWRITE ) )
+ {
+ WARN( heap, "Cannot grow handle table!\n" );
+ HeapFree( header->heap, 0, ptr );
+ return 0;
+ }
+
+ header->limit += HTABLE_PAGESIZE;
+
+ header->freeListFirst[page] = 0;
+ header->freeListLast[page] = HTABLE_PAGESIZE - 4;
+ header->freeListSize[page] = HTABLE_PAGESIZE / 4;
+
+ for (i = 0; i < HTABLE_PAGESIZE; i += 4)
+ *(DWORD *)((LPBYTE)header + i) = i+4;
+
+ if (page < 31)
+ header->freeListFirst[page+1] = 0xffff;
+ }
+
+ /* Allocate handle slot from page */
+ handle = (LPDWORD)((LPBYTE)header + header->freeListFirst[page]);
+ if (--header->freeListSize[page] == 0)
+ header->freeListFirst[page] = header->freeListLast[page] = 0;
+ else
+ header->freeListFirst[page] = *handle;
+
+ /* Store 32-bit offset in handle slot */
+ *handle = ptr - header->base;
+ }
+ else
+ {
+ handle = (LPDWORD)ptr;
+ header->flags |= 1;
+ }
+
+
+ /* Convert handle to requested output type */
+ Local32_FromHandle( header, type, &addr, handle, ptr );
+ return addr;
+}
+
+/***********************************************************************
+ * Local32ReAlloc (KERNEL.210)
+ */
+DWORD WINAPI Local32ReAlloc( HANDLE32 heap, DWORD addr, INT16 type,
+ DWORD size, DWORD flags )
+{
+ LOCAL32HEADER *header = (LOCAL32HEADER *)heap;
+ LPDWORD handle;
+ LPBYTE ptr;
+
+ if (!addr)
+ return Local32Alloc( heap, size, type, flags );
+
+ /* Retrieve handle and pointer */
+ Local32_ToHandle( header, type, addr, &handle, &ptr );
+ if (!handle) return FALSE;
+
+ /* Reallocate memory block */
+ ptr = HeapReAlloc( header->heap,
+ (flags & LMEM_MOVEABLE)? HEAP_ZERO_MEMORY : 0,
+ ptr, size );
+ if (!ptr) return 0;
+
+ /* Modify handle */
+ if (type >= 0)
+ *handle = ptr - header->base;
+ else
+ handle = (LPDWORD)ptr;
+
+ /* Convert handle to requested output type */
+ Local32_FromHandle( header, type, &addr, handle, ptr );
+ return addr;
+}
+
+/***********************************************************************
+ * Local32Free (KERNEL.211)
+ */
+BOOL32 WINAPI Local32Free( HANDLE32 heap, DWORD addr, INT16 type )
+{
+ LOCAL32HEADER *header = (LOCAL32HEADER *)heap;
+ LPDWORD handle;
+ LPBYTE ptr;
+
+ /* Retrieve handle and pointer */
+ Local32_ToHandle( header, type, addr, &handle, &ptr );
+ if (!handle) return FALSE;
+
+ /* Free handle if necessary */
+ if (type >= 0)
+ {
+ int offset = (LPBYTE)handle - (LPBYTE)header;
+ int page = offset >> 12;
+
+ /* Return handle slot to page free list */
+ if (header->freeListSize[page]++ == 0)
+ header->freeListFirst[page] = header->freeListLast[page] = offset;
+ else
+ *(LPDWORD)((LPBYTE)header + header->freeListLast[page]) = offset,
+ header->freeListLast[page] = *handle;
+
+ *handle = 0;
+
+ /* Shrink handle table when possible */
+ while (page > 0 && header->freeListSize[page] == HTABLE_PAGESIZE / 4)
+ {
+ if ( VirtualFree( (LPBYTE)header +
+ (header->limit & ~(HTABLE_PAGESIZE-1)),
+ HTABLE_PAGESIZE, MEM_DECOMMIT ) )
+ break;
+
+ header->limit -= HTABLE_PAGESIZE;
+ header->freeListFirst[page] = -1;
+ page--;
+ }
+ }
+
+ /* Free memory */
+ return HeapFree( header->heap, 0, ptr );
+}
+
+/***********************************************************************
+ * Local32Translate (KERNEL.213)
+ */
+DWORD WINAPI Local32Translate( HANDLE32 heap, DWORD addr, INT16 type1, INT16 type2 )
+{
+ LOCAL32HEADER *header = (LOCAL32HEADER *)heap;
+ LPDWORD handle;
+ LPBYTE ptr;
+
+ Local32_ToHandle( header, type1, addr, &handle, &ptr );
+ if (!handle) return 0;
+
+ Local32_FromHandle( header, type2, &addr, handle, ptr );
+ return addr;
+}
+
+/***********************************************************************
+ * Local32Size (KERNEL.214)
+ */
+DWORD WINAPI Local32Size( HANDLE32 heap, DWORD addr, INT16 type )
+{
+ LOCAL32HEADER *header = (LOCAL32HEADER *)heap;
+ LPDWORD handle;
+ LPBYTE ptr;
+
+ Local32_ToHandle( header, type, addr, &handle, &ptr );
+ if (!handle) return 0;
+
+ return HeapSize( header->heap, 0, ptr );
+}
+
+/***********************************************************************
+ * Local32ValidHandle (KERNEL.215)
+ */
+BOOL32 WINAPI Local32ValidHandle( HANDLE32 heap, WORD addr )
+{
+ LOCAL32HEADER *header = (LOCAL32HEADER *)heap;
+ LPDWORD handle;
+ LPBYTE ptr;
+
+ Local32_ToHandle( header, 0, addr, &handle, &ptr );
+ return handle != NULL;
+}
+
+/***********************************************************************
+ * Local32GetSegment (KERNEL.229)
+ */
+WORD WINAPI Local32GetSegment( HANDLE32 heap )
+{
+ LOCAL32HEADER *header = (LOCAL32HEADER *)heap;
+ return header->segment;
+}
+
+
diff --git a/memory/local.c b/memory/local.c
index 5e4192c..9d8fe87 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -345,7 +345,8 @@
if ((pModule = NE_GetPtr( selector )))
{
SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
- if (pModule->dgroup && (pSeg->selector == selector)) {
+ if (pModule->dgroup && (GlobalHandleToSel(pSeg->hSeg) == selector))
+ {
/* We can't just use the simple method of using the value
* of minsize + stacksize, since there are programs that
* resize the data segment before calling InitTask(). So,
@@ -1602,7 +1603,8 @@
WORD ds;
if (!(pModule = NE_GetPtr( module ))) return 0;
- ds = (NE_SEG_TABLE( pModule ) + pModule->dgroup - 1)->selector;
+ ds =
+ GlobalHandleToSel((NE_SEG_TABLE( pModule ) + pModule->dgroup - 1)->hSeg);
return MAKELONG( LOCAL_CountFree( ds ), LOCAL_HeapSize( ds ) );
}
diff --git a/memory/selector.c b/memory/selector.c
index 859cc6a..16bddc6 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -406,7 +406,7 @@
if (IS_SELECTOR_FREE(sel)) return TRUE;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
if (entry.type != SEGMENT_CODE) return TRUE;
- if (OFFSETOF(lpfn) > entry.limit) return TRUE;
+ if (OFFSETOF(lpfn) > GET_SEL_LIMIT(sel)) return TRUE;
return FALSE;
}
@@ -425,7 +425,7 @@
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
if (strlen(PTR_SEG_TO_LIN(ptr)) < size) size = strlen(PTR_SEG_TO_LIN(ptr));
- if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
+ if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
return FALSE;
}
@@ -443,7 +443,7 @@
if (IS_SELECTOR_FREE(sel)) return TRUE;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
if ((entry.type == SEGMENT_CODE) && entry.read_only) return TRUE;
- if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
+ if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
return FALSE;
}
@@ -461,7 +461,7 @@
if (IS_SELECTOR_FREE(sel)) return TRUE;
LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
if ((entry.type == SEGMENT_CODE) || entry.read_only) return TRUE;
- if (OFFSETOF(ptr) + size - 1 > entry.limit) return TRUE;
+ if (OFFSETOF(ptr) + size - 1 > GET_SEL_LIMIT(sel)) return TRUE;
return FALSE;
}
diff --git a/memory/virtual.c b/memory/virtual.c
index 3b4e94f..58aa32a 100644
--- a/memory/virtual.c
+++ b/memory/virtual.c
@@ -6,6 +6,7 @@
#include <assert.h>
#include <errno.h>
+#include <sys/errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
@@ -310,8 +311,10 @@
) {
if (protect) {
*protect = VIRTUAL_Win32Flags[vprot & 0x0f];
- if (vprot & VPROT_GUARD) *protect |= PAGE_GUARD;
+/* if (vprot & VPROT_GUARD) *protect |= PAGE_GUARD;*/
if (vprot & VPROT_NOCACHE) *protect |= PAGE_NOCACHE;
+
+ if (vprot & VPROT_GUARD) *protect = PAGE_NOACCESS;
}
if (state) *state = (vprot & VPROT_COMMITTED) ? MEM_COMMIT : MEM_RESERVE;