Release 951124
Tue Nov 21 18:49:10 1995 Alexandre Julliard <julliard@sunsite.unc.edu>
* [configure.in] [Makefile] [misc/dos_fs.c]
Got rid of autoconf.h file.
* [debugger/dbg.y]
More logical behavior upon syntax errors.
* [include/hook.h] [windows/hook.c]
Changed hook structure and rewrote most of the hook functions for
better compatibility, based on investigations by Alex Korobka.
* [include/message.h] [windows/message.c]
Added hooks to message queue structure and made the structure
layout Windows-compatible.
Added support for WH_MOUSE, WH_KEYBOARD, WH_HARDWARE and
WH_JOURNALRECORD hooks.
* [misc/main.c]
Added command-line option for changing the language at run-time
(not implemented yet), based on a suggestion from Michael Patra.
* [objects/cursoricon.c]
Fixed silly SEGPTR bug in DumpIcon().
Mon Nov 20 22:22:22 1995 Alex Korobka <alex@phm30.pharm.sunysb.edu>
* [controls/listbox.c] [controls/combo.c] [include/listbox.h]
Partial implementaion of LBS_EXTENDEDSEL style,
yet more updates for drag & drop support. Now works.
* [windows/defwnd.c]
More message handlers.
* [windows/win.c]
DragObject, DragDetect, AnyPopup functions.
* [controls/listbox.c]
More kludgy fixes (WM_...TOITEM, etc.).
* [objects/cursoricon.c] [objects/oembitmap.c]
IconToCursor skeleton, patch for OBM_LoadCursorIcon to handle new
cursor.
* [include/bitmaps/ocr*]
New OEM cursors.
Mon Nov 20 11:05:20 EST 1995 Jim Peterson <jspeter@birch.ee.vt.edu>
* [toolkit/heap.c]
Swapped flags and size arguments to LocalRealloc as per changes in
memory/local.c by William Magro in previous release.
* [include/wintypes.h]
Reinstated the #define's for 'min' and 'max', since they're part of
the Windows API. I really don't think it's a wise idea, so I put
a '#ifndef DONT_DEFINE_min_AND_max' around them. I think the actual
WINE code should never use these (it should use 'MIN' and 'MAX'
instead).
* [loader/*]
Put '#ifndef WINELIB' around many things that WINElib should not need.
* [controls/edit.c]
Took out many '#if defined(WINELIB)' sections with the associated
comment 'temporary fix, until Local memory is correctly implemented in
WINELIB', since the effective translations are now in
toolkit/miscstubs.c.
Took out the #ifndef's I put in EDIT_ClearText. Whoever modified this
file fixed (or at least postponed) the bug I had encountered.
* [loader/task.c]
Put an #ifdef in TASK_CreateTask() that hardwires the current drive to
C: This will probably cause a lot of trouble if this change is
forgotten in the future, but it will let things like the OpenFileName
dialog work for now.
* [toolkit/libres.c] [toolkit/Makefile.in] [toolkit/Makefile]
[include/libres.h]
Made new libres.c file, which will contain functions for supporting
accessing resources by name in WINElib. 'winerc' will need to be
changed.
* [toolkit/heap.c]
Refined memory routines to allow for differences between LocalAlloc
and GlobalAlloc and between LocalSize and GlobalSize.
* [windows/message.c] [include/windows.h]
Defined the GetCurrentTime routine in windows/message.c, and removed
the #define in windows.h.
Mon Nov 20 00:36:42 MET 1995 Sven Verdoolaege <skimo@dns.ufsia.ac.be>
* [*/*]
Added new debugging type DEBUG_WIN32 and DEBUG_ENV.
* [loader/module.c]
Added undocumented GetExpWinVer.
* [tools/build.c]
Previous code didn't pop possibly changed %esi, %edi and %edx
from the stack.
* [win32/advapi.c]
Added GetUserNameA.
* [win32/code_page.c]
Added stub for MultiByteToWideChar.
* [win32/console.c]
Added SetConsoleCtrlHandler stub.
* [win32/file.c]
Added ReadFile CreateFileA GetFileInformationByHandle stubs.
Added CloseHandle.
* [win32/memory.c]
Changed VirtualAlloc and VirtualFree.
* [win32/process.c]
Added ExitProcess.
Sun Nov 19 17:54:42 1995 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* [include/windows.h]
Fixed a few broken structure definitions.
* [loader/resource.c]
FindResource(): Need to check for '#xxx' strings here.
* [miscemu/int21.c]
FindNext(): Return MS-DOS filenames uppercase.
* [objects/cursoricon.c]
CreateIcon(), CreateCursor(): Added missing element to CURSORICONINFO
initializers.
* [misc/file.c]
_lopen(): Files opened in OF_WRITE mode are truncated.
OpenFile(): Ignore OF_READ/OF_WRITE/OF_READWRITE when files are
created; use read/write mode.
* [misc/profile.c]
load(): Rewritten.
* [misc/commdlg.c]
Fixed bad call to strncpy() that smashed the stack.
* [controls/combo.c] [windows/winpos.c] [memory/selector.c]
Operator precedence fixes. People who use gcc 2.7.1 don't need a
debugger :-)
* [if1632/gdi.spec] [objects/palette.c]
Add ResizePalette() and AnimatePalette() stubs. They don't do anything,
but sometimes that's good enough.
Fri Nov 17 09:10:35 GMT 1995 John Harvey <john@division.co.uk>
* [include/wine.h] [include/registers.h] [include/winsock.h]
Added definitions for Unixware.
* [loader/signal.c] [misc/comm.c] [misc/winsocket.c]
Misc. fixes for Unixware.
* [loader/task.c]
Made assignemts to context in InitTask for registers use the macros
from registers.h to make them more portable. (Needed for Unixware)
* [tools/build.c]
Fixed register acces routines to work on Unixware. Bit grubby but
it seems to work.
* [controls/edit.c]
EDIT_WM_NCCreate allocates local heap if hasn't been previously
allocated.
* [miscemu/int21.c]
mkdir now creates directory with permission to access it.
* [misc/dos_fs.c]
mkdir now creates directory with permission to access it.
DOS_opendir now uses linked list of dirents to avoid problems with
realloc changing address of malloced memory.
Thu Nov 16 12:47:13 1995 Michael Patra <patra@itp1.Physik.TU-Berlin.DE>
* [controls/menu.c]
MENU_CalcItemSize(): Fixed handling of empty menu items.
Sat Nov 11 21:46:54 1995 Hans de Graaff <graaff@twi72.twi.tudelft.nl>
* [misc/file.c]
In OpenFile, unlink should be done on the unix filename.
Sat Nov 11 16:43:29 1995 Cameron Heide (heide@ee.ualberta.ca)
* [include/handle32.h]
New header file containing internal Win32 kernel handle
information.
* [win32/file.c]
Added ReadFile, CreateFile, and CloseFileHandle, and did
some reorganizing to match the new handle allocation scheme.
* [win32/init.c]
Added CloseHandle and the creation of standard I/O handles.
* [win32/object_mgt.c]
New module for allocating and freeing Win32 kernel handles.
diff --git a/windows/defwnd.c b/windows/defwnd.c
index eda4fe2..786c0a7 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -2,6 +2,7 @@
* Default window procedure
*
* Copyright 1993 Alexandre Julliard
+ * 1995 Alex Korobka
*/
#include <stdlib.h>
@@ -20,6 +21,8 @@
/* Last COLOR id */
#define COLOR_MAX COLOR_BTNHIGHLIGHT
+static short iMenuKey = 0;
+static short iMenuSysKey = 0;
/***********************************************************************
* DEFWND_SetText
@@ -244,16 +247,95 @@
return NC_HandleSysCommand( hwnd, wParam, pt );
}
+ case WM_KEYDOWN:
+
+ if(wParam == VK_F10) iMenuKey = VK_F10;
+ break;
+
case WM_SYSKEYDOWN:
+ /* this breaks current pseudo accelerators but
+ creates a basis for implementing real ones */
+
+ if(wParam == VK_F10)
+ {
+ iMenuKey = VK_F10;
+ break;
+ }
+
if (wParam == VK_MENU)
- { /* Send to WS_OVERLAPPED parent. TODO: Handle MDI */
- SendMessage( WIN_GetTopParent(hwnd), WM_SYSCOMMAND,
- SC_KEYMENU, 0L );
+ {
+ iMenuSysKey = (iMenuSysKey)? 0: 1;
+ iMenuKey = 0;
}
break;
+ case WM_KEYUP:
case WM_SYSKEYUP:
+
+ if( (wParam == VK_MENU && iMenuSysKey) ||
+ (wParam == VK_F10 && iMenuKey) )
+
+ /* Send to WS_OVERLAPPED parent. TODO: Handle MDI */
+ SendMessage( WIN_GetTopParent(hwnd), WM_SYSCOMMAND,
+ SC_KEYMENU, 0L );
+
+ iMenuSysKey = 0;
+ iMenuKey = 0;
break;
+
+ case WM_SHOWWINDOW:
+ if( !lParam ) return 0; /* sent from ShowWindow */
+
+ if( !(wndPtr->dwStyle & WS_POPUP) || !wndPtr->hwndOwner )
+ return 0;
+
+ if( wndPtr->dwStyle & WS_VISIBLE )
+ { if( wParam ) return 0; }
+ else
+ if(!wParam ) return 0;
+
+ ShowWindow(hwnd,(wParam)? SW_SHOWNOACTIVATE: SW_HIDE);
+ break;
+
+ case WM_CANCELMODE:
+
+ /* EndMenu() should be called if in menu state but currently it's
+ impossible to detect - menu code should be updated*/
+
+ if( GetCapture() == hwnd )
+ ReleaseCapture();
+
+ break;
+
+ case WM_VKEYTOITEM:
+ case WM_CHARTOITEM:
+ return -1;
+
+ case WM_DROPOBJECT:
+ return DRAG_FILE;
+
+ case WM_QUERYDROPOBJECT:
+ if(wndPtr->dwExStyle & WS_EX_ACCEPTFILES)
+ return 1;
+ break;
+
+ case WM_QUERYDRAGICON:
+ {
+ HICON hI = 0;
+
+ len = 1;
+ while(len < 64)
+ if( (hI = LoadIcon(wndPtr->hInstance,MAKEINTRESOURCE(len))) )
+ return hI;
+ }
+ break;
+
+ case WM_QUERYOPEN:
+ case WM_QUERYENDSESSION:
+ return 1;
+
}
return 0;
}
+
+
diff --git a/windows/dialog.c b/windows/dialog.c
index 6a16805..8f7cdb0 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -411,7 +411,7 @@
header->y * yUnit / 8,
header->cx * xUnit / 4,
header->cy * yUnit / 8,
- hwnd, (HMENU)header->id,
+ hwnd, (HMENU)((DWORD)header->id),
dlgInfo->hDialogHeap, (SEGPTR)0 );
}
else
@@ -422,7 +422,7 @@
header->y * yUnit / 8,
header->cx * xUnit / 4,
header->cy * yUnit / 8,
- hwnd, (HMENU)header->id,
+ hwnd, (HMENU)((DWORD)header->id),
hInst, (SEGPTR)0 );
}
diff --git a/windows/hook.c b/windows/hook.c
index d56c93f..2460cad 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -1,24 +1,215 @@
/*
* Windows hook functions
*
- * Copyright 1994 Alexandre Julliard
+ * Copyright 1994, 1995 Alexandre Julliard
+ *
+ * Based on investigations by Alex Korobka
*/
-/* Warning!
- * HHOOK is not a real handle, but a 32-bit pointer to a HOOKDATA structure.
- * This is for compatibility with Windows 3.0 where HHOOK was a HOOKPROC.
+/*
+ * Warning!
+ * A HHOOK is a 32-bit handle for compatibility with Windows 3.0 where it was
+ * a pointer to the next function. Now it is in fact composed of a USER heap
+ * handle in the low 16 bits and of a HOOK_MAGIC value in the high 16 bits
+ * (except for WINELIB32 where it is a 32-bit handle). -- AJ
*/
#include "hook.h"
+#include "message.h"
#include "user.h"
#include "stddebug.h"
#include "debug.h"
-HHOOK systemHooks[LAST_HOOK-FIRST_HOOK+1] = { 0, };
+ /* This should probably reside in USER heap */
+static HANDLE HOOK_systemHooks[WH_NB_HOOKS] = { 0, };
- /* Task-specific hooks should probably be in the task structure */
-HHOOK taskHooks[LAST_HOOK-FIRST_HOOK+1] = { 0, };
+/***********************************************************************
+ * HOOK_GetNextHook
+ *
+ * Get the next hook of a given hook.
+ */
+static HANDLE HOOK_GetNextHook( HANDLE hook )
+{
+ HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR( hook );
+ if (!data) return 0;
+ if (data->next) return data->next;
+ if (!data->ownerQueue) return 0; /* Already system hook */
+ /* Now start enumerating the system hooks */
+ return HOOK_systemHooks[data->id - WH_FIRST_HOOK];
+}
+
+
+/***********************************************************************
+ * HOOK_GetHook
+ *
+ * Get the first hook for a given type.
+ */
+static HANDLE HOOK_GetHook( short id )
+{
+ MESSAGEQUEUE *queue;
+ HANDLE hook = 0;
+
+ if ((queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) )) != NULL)
+ hook = queue->hooks[id - WH_FIRST_HOOK];
+ if (!hook) hook = HOOK_systemHooks[id - WH_FIRST_HOOK];
+ return hook;
+}
+
+
+/***********************************************************************
+ * HOOK_SetHook
+ *
+ * Install a given hook.
+ */
+HANDLE HOOK_SetHook( short id, HOOKPROC proc, HINSTANCE hInst, HTASK hTask )
+{
+ HOOKDATA *data;
+ HANDLE handle;
+ HQUEUE hQueue = 0;
+
+ if ((id < WH_FIRST_HOOK) || (id > WH_LAST_HOOK)) return 0;
+ if (!(hInst = GetExePtr( hInst ))) return 0;
+
+ dprintf_hook( stddeb, "Setting hook %d: %08lx "NPFMT" "NPFMT"\n",
+ id, (DWORD)proc, hInst, hTask );
+
+ if (hTask) /* Task-specific hook */
+ {
+ if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
+ (id == WH_SYSMSGFILTER)) return 0; /* System-only hooks */
+ if (!(hQueue = GetTaskQueue( hTask ))) return 0;
+ }
+
+ if (id == WH_JOURNALPLAYBACK || id == WH_CBT ||
+ id == WH_DEBUG || id == WH_SHELL)
+ {
+ fprintf( stdnimp, "Unimplemented hook set: (%d,%08lx,"NPFMT","NPFMT")!\n",
+ id, (DWORD)proc, hInst, hTask );
+ }
+
+ /* Create the hook structure */
+
+ if (!(handle = (HANDLE)USER_HEAP_ALLOC( sizeof(HOOKDATA) ))) return 0;
+ data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
+ data->proc = proc;
+ data->id = id;
+ data->ownerQueue = hQueue;
+ data->ownerModule = hInst;
+ data->inHookProc = 0;
+ dprintf_hook( stddeb, "Setting hook %d: ret="NPFMT"\n", id, handle );
+
+ /* Insert it in the correct linked list */
+
+ if (hQueue)
+ {
+ MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock( hQueue );
+ data->next = queue->hooks[id - WH_FIRST_HOOK];
+ queue->hooks[id - WH_FIRST_HOOK] = handle;
+ }
+ else
+ {
+ data->next = HOOK_systemHooks[id - WH_FIRST_HOOK];
+ HOOK_systemHooks[id - WH_FIRST_HOOK] = handle;
+ }
+ return handle;
+}
+
+
+/***********************************************************************
+ * HOOK_RemoveHook
+ *
+ * Remove a hook from the list.
+ */
+static BOOL HOOK_RemoveHook( HANDLE hook )
+{
+ HOOKDATA *data;
+ HANDLE *prevHook;
+
+ dprintf_hook( stddeb, "Removing hook "NPFMT"\n", hook );
+
+ if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return FALSE;
+ if (data->inHookProc)
+ {
+ /* Mark it for deletion later on */
+ dprintf_hook( stddeb, "Hook still running, deletion delayed\n" );
+ data->proc = (FARPROC)0;
+ return TRUE;
+ }
+
+ /* Remove it from the linked list */
+
+ if (data->ownerQueue)
+ {
+ MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock( data->ownerQueue );
+ if (!queue) return FALSE;
+ prevHook = &queue->hooks[data->id - WH_FIRST_HOOK];
+ }
+ else prevHook = &HOOK_systemHooks[data->id - WH_FIRST_HOOK];
+
+ while (*prevHook && *prevHook != hook)
+ prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
+
+ if (!*prevHook) return FALSE;
+ *prevHook = data->next;
+ USER_HEAP_FREE( hook );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * HOOK_CallHook
+ *
+ * Call a hook procedure.
+ */
+static DWORD HOOK_CallHook( HANDLE hook, short code,
+ WPARAM wParam, LPARAM lParam )
+{
+ HOOKDATA *data;
+ MESSAGEQUEUE *queue;
+ HANDLE prevHook;
+ DWORD ret;
+
+ /* Find the first hook with a valid proc */
+
+ for (;;)
+ {
+ if (!hook) return 0;
+ if (!(data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook))) return 0;
+ if (data->proc) break;
+ hook = data->next;
+ }
+
+ /* Now call it */
+
+ if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
+ prevHook = queue->hCurHook;
+ queue->hCurHook = hook;
+ data->inHookProc = 1;
+
+ dprintf_hook( stddeb, "Calling hook "NPFMT": %d %04lx %08lx\n",
+ hook, code, (DWORD)wParam, lParam );
+ ret = CallHookProc( data->proc, code, wParam, lParam );
+ dprintf_hook( stddeb, "Ret hook "NPFMT" = %08lx\n", hook, ret );
+
+ data->inHookProc = 0;
+ queue->hCurHook = prevHook;
+ if (!data->proc) HOOK_RemoveHook( hook );
+ return ret;
+}
+
+
+/***********************************************************************
+ * HOOK_CallHooks
+ *
+ * Call a hook chain.
+ */
+DWORD HOOK_CallHooks( short id, short code, WPARAM wParam, LPARAM lParam )
+{
+ HANDLE hook = HOOK_GetHook( id );
+ if (!hook) return 0;
+ return HOOK_CallHook( hook, code, wParam, lParam );
+}
/***********************************************************************
@@ -26,55 +217,44 @@
*/
FARPROC SetWindowsHook( short id, HOOKPROC proc )
{
- HHOOK hhook = SetWindowsHookEx( id, proc, 0, 0 );
- HOOKDATA *data = PTR_SEG_TO_LIN(hhook);
- if (data != NULL) {
- data = PTR_SEG_TO_LIN(data->next);
- if (data != NULL) {
- return data->proc;
- }
- }
- return 0;
+#ifdef WINELIB
+ HINSTANCE hInst = 0;
+#else
+ HINSTANCE hInst = FarGetOwner( HIWORD(proc) );
+#endif
+ /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */
+ HTASK hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0;
+
+ HANDLE handle = HOOK_SetHook( id, proc, hInst, hTask );
+ if (!handle) return -1;
+ if (!((HOOKDATA *)USER_HEAP_LIN_ADDR( handle ))->next) return 0;
+ /* Not sure if the return value is correct; should not matter much
+ * since it's never used (see DefHookProc). -- AJ */
+#ifdef WINELIB32
+ return (FARPROC)handle;
+#else
+ return (FARPROC)MAKELONG( handle, HOOK_MAGIC );
+#endif
}
/***********************************************************************
* UnhookWindowsHook (USER.234)
*/
-BOOL UnhookWindowsHook( short id, FARPROC hproc )
+BOOL UnhookWindowsHook( short id, HOOKPROC proc )
{
- HHOOK *prevHook,hhook;
-
- prevHook = &TASK_HOOK(id);
- while (*prevHook) {
- HOOKDATA *data = (HOOKDATA *)PTR_SEG_TO_LIN(*prevHook);
+ HANDLE hook = HOOK_GetHook( id );
- if (data->proc == hproc) {
- hhook = *prevHook;
- *prevHook = data->next;
-#ifdef WINELIB32
- USER_HEAP_FREE((HANDLE)hhook);
-#else
- USER_HEAP_FREE(LOWORD(hhook));
-#endif
- return TRUE;
+ dprintf_hook( stddeb, "UnhookWindowsHook: %d %08lx\n", id, (DWORD)proc );
+
+ while (hook)
+ {
+ HOOKDATA *data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook);
+ if (data->proc == proc) break;
+ hook = HOOK_GetNextHook( hook );
}
- }
- prevHook = &SYSTEM_HOOK(id);
- while (*prevHook) {
- HOOKDATA *data = (HOOKDATA *)PTR_SEG_TO_LIN(*prevHook);
- if (data->proc == hproc) {
- hhook = *prevHook;
- *prevHook = data->next;
-#ifdef WINELIB32
- USER_HEAP_FREE((HANDLE)hhook);
-#else
- USER_HEAP_FREE(LOWORD(hhook));
-#endif
- return TRUE;
- }
- }
- return FALSE;
+ if (!hook) return FALSE;
+ return HOOK_RemoveHook( hook );
}
@@ -83,7 +263,14 @@
*/
DWORD DefHookProc( short code, WORD wParam, DWORD lParam, HHOOK *hhook )
{
- return CallNextHookEx( *hhook, code, wParam, lParam );
+ /* Note: the *hhook parameter is never used, since we rely on the
+ * current hook value from the task queue to find the next hook. */
+ MESSAGEQUEUE *queue;
+ HANDLE next;
+
+ if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return 0;
+ if (!(next = HOOK_GetNextHook( queue->hCurHook ))) return 0;
+ return HOOK_CallHook( next, code, wParam, lParam );
}
@@ -92,47 +279,23 @@
*/
BOOL CallMsgFilter( SEGPTR msg, short code )
{
- if (CALL_TASK_HOOK( WH_MSGFILTER, code, 0, (LPARAM)msg ))
- return TRUE;
- return CALL_SYSTEM_HOOK( WH_SYSMSGFILTER, code, 0, (LPARAM)msg );
+ if (GetSysModalWindow()) return FALSE;
+ if (HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)msg )) return TRUE;
+ return HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)msg );
}
/***********************************************************************
* SetWindowsHookEx (USER.291)
*/
-HHOOK SetWindowsHookEx( short id, HOOKPROC proc, HINSTANCE hinst, HTASK htask )
+HHOOK SetWindowsHookEx( short id, HOOKPROC proc, HINSTANCE hInst, HTASK hTask )
{
- HOOKDATA *data;
- HANDLE handle;
- HHOOK *prevHook;
-
- if ((id < FIRST_HOOK) || (id > LAST_HOOK)) return 0;
- if (id != WH_GETMESSAGE && id != WH_CALLWNDPROC) {
- fprintf( stdnimp, "Unimplemented hook set: (%d,%08lx,"NPFMT","NPFMT")!\n",
- id, (DWORD)proc, hinst, htask );
- }
- if (htask) /* Task-specific hook */
- {
- if ((id == WH_JOURNALRECORD) || (id == WH_JOURNALPLAYBACK) ||
- (id == WH_SYSMSGFILTER)) return 0;
- prevHook = &TASK_HOOK( id );
- }
- else /* System-wide hook */
- {
- prevHook = &SYSTEM_HOOK( id );
- }
-
- handle = (HANDLE) USER_HEAP_ALLOC( sizeof(*data) );
- if (!handle) return 0;
- data = (HOOKDATA *) USER_HEAP_LIN_ADDR( handle );
-
- data->next = *prevHook;
- data->proc = proc;
- data->id = id;
- data->htask = htask;
- *prevHook = (HHOOK)USER_HEAP_SEG_ADDR(handle);
- return *prevHook;
+ HANDLE handle = HOOK_SetHook( id, proc, hInst, hTask );
+#ifdef WINELIB32
+ return (HHOOK)handle;
+#else
+ return MAKELONG( handle, HOOK_MAGIC );
+#endif
}
@@ -141,22 +304,12 @@
*/
BOOL UnhookWindowsHookEx( HHOOK hhook )
{
- HOOKDATA *data = (HOOKDATA *)PTR_SEG_TO_LIN(hhook);
- HHOOK *prevHook;
-
- if (!data) return FALSE;
- prevHook = data->htask ? &TASK_HOOK(data->id) : &SYSTEM_HOOK(data->id);
- while (*prevHook && (*prevHook != hhook)) {
- prevHook = &((HOOKDATA *)*prevHook)->next;
- }
- if (!*prevHook) return FALSE;
- *prevHook = data->next;
#ifdef WINELIB32
- USER_HEAP_FREE( (HANDLE)hhook );
+ return HOOK_RemoveHook( (HANDLE)hhook );
#else
- USER_HEAP_FREE( hhook & 0xffff );
+ if (HIWORD(hhook) != HOOK_MAGIC) return FALSE; /* Not a new format hook */
+ return HOOK_RemoveHook( LOWORD(hhook) );
#endif
- return TRUE;
}
@@ -165,7 +318,8 @@
*/
DWORD CallNextHookEx( HHOOK hhook, short code, WPARAM wParam, LPARAM lParam )
{
- HOOKDATA *data = (HOOKDATA *)PTR_SEG_TO_LIN(hhook);
- if (data == NULL || !data->next) return 0;
- else return INTERNAL_CALL_HOOK( data->next, code, wParam, lParam );
+ HANDLE next;
+ if (HIWORD(hhook) != HOOK_MAGIC) return 0; /* Not a new format hook */
+ if (!(next = HOOK_GetNextHook( LOWORD(hhook) ))) return 0;
+ return HOOK_CallHook( next, code, wParam, lParam );
}
diff --git a/windows/message.c b/windows/message.c
index a309356..8360974 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -52,29 +52,12 @@
int queueSize;
queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
- if (!(hQueue = GlobalAlloc( GMEM_FIXED, queueSize ))) return 0;
+ if (!(hQueue = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
+ return 0;
msgQueue = (MESSAGEQUEUE *) GlobalLock( hQueue );
- msgQueue->next = 0;
- msgQueue->hTask = 0;
msgQueue->msgSize = sizeof(QMSG);
- msgQueue->msgCount = 0;
- msgQueue->nextMessage = 0;
- msgQueue->nextFreeMessage = 0;
msgQueue->queueSize = size;
- msgQueue->GetMessageTimeVal = 0;
- msgQueue->GetMessagePosVal = 0;
- msgQueue->GetMessageExtraInfoVal = 0;
- msgQueue->lParam = 0;
- msgQueue->wParam = 0;
- msgQueue->msg = 0;
- msgQueue->hWnd = 0;
- msgQueue->wPostQMsg = 0;
- msgQueue->wExitCode = 0;
- msgQueue->InSendMessageHandle = 0;
- msgQueue->wPaintCount = 0;
- msgQueue->wTimerCount = 0;
- msgQueue->tempStatus = 0;
- msgQueue->status = 0;
+ msgQueue->wWinVersion = 0; /* FIXME? */
GlobalUnlock( hQueue );
return hQueue;
}
@@ -292,6 +275,7 @@
static WORD lastClickMsg = 0;
static POINT lastClickPos = { 0, 0 };
POINT pt = msg->pt;
+ MOUSEHOOKSTRUCT hook = { msg->pt, 0, HTCLIENT, 0 };
BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
(msg->message == WM_RBUTTONDOWN) ||
@@ -304,7 +288,10 @@
msg->hwnd = GetCapture();
ScreenToClient( msg->hwnd, &pt );
msg->lParam = MAKELONG( pt.x, pt.y );
- return TRUE; /* No need to further process the message */
+ /* No need to further process the message */
+ hook.hwnd = msg->hwnd;
+ return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+ msg->message, (LPARAM)MAKE_SEGPTR(&hook));
}
if ((hittest = MSG_GetWindowForEvent( msg->pt, &msg->hwnd )) != HTERROR)
@@ -389,7 +376,10 @@
}
msg->lParam = MAKELONG( pt.x, pt.y );
- return TRUE;
+ hook.hwnd = msg->hwnd;
+ hook.wHitTestCode = hittest;
+ return !HOOK_CallHooks( WH_MOUSE, remove ? HC_ACTION : HC_NOREMOVE,
+ msg->message, (LPARAM)MAKE_SEGPTR(&hook));
}
@@ -400,7 +390,7 @@
* Return value indicates whether the translated message must be passed
* to the user.
*/
-static BOOL MSG_TranslateKeyboardMsg( MSG *msg )
+static BOOL MSG_TranslateKeyboardMsg( MSG *msg, BOOL remove )
{
/* Should check Ctrl-Esc and PrintScreen here */
@@ -412,7 +402,8 @@
msg->hwnd = GetActiveWindow();
msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
}
- return TRUE;
+ return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
+ msg->wParam, msg->lParam );
}
@@ -439,9 +430,15 @@
}
else if ((msg->message >= WM_KEYFIRST) && (msg->message <= WM_KEYLAST))
{
- if (!MSG_TranslateKeyboardMsg( msg )) continue;
+ if (!MSG_TranslateKeyboardMsg( msg, remove )) continue;
}
- else continue; /* Should never happen */
+ else /* Non-standard hardware event */
+ {
+ HARDWAREHOOKSTRUCT hook = { msg->hwnd, msg->message,
+ msg->wParam, msg->lParam };
+ if (HOOK_CallHooks( WH_HARDWARE, remove ? HC_ACTION : HC_NOREMOVE,
+ 0, (LPARAM)MAKE_SEGPTR(&hook) )) continue;
+ }
/* Check message against filters */
@@ -451,7 +448,13 @@
if ((msg->hwnd != GetDesktopWindow()) &&
(GetWindowTask(msg->hwnd) != GetCurrentTask()))
continue; /* Not for this task */
- if (remove) MSG_RemoveMsg( sysMsgQueue, pos );
+ if (remove)
+ {
+ MSG tmpMsg = *msg; /* FIXME */
+ HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION,
+ 0, (LPARAM)MAKE_SEGPTR(&tmpMsg) );
+ MSG_RemoveMsg( sysMsgQueue, pos );
+ }
return TRUE;
}
return FALSE;
@@ -955,8 +958,7 @@
{
MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
hwnd, first, last, PM_REMOVE, FALSE );
- CALL_TASK_HOOK( WH_GETMESSAGE, 0, 0, (LPARAM)msg );
- CALL_SYSTEM_HOOK( WH_GETMESSAGE, 0, 0, (LPARAM)msg );
+ HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)msg );
return (((MSG *)PTR_SEG_TO_LIN(msg))->message != WM_QUIT);
}
@@ -1066,8 +1068,7 @@
EnterSpyMessage(SPY_SENDMESSAGE, hwnd, msg, wParam, lParam);
- CALL_TASK_HOOK( WH_CALLWNDPROC, HC_ACTION, 1, MAKE_SEGPTR(&msgstruct) );
- CALL_SYSTEM_HOOK( WH_CALLWNDPROC, HC_ACTION, 1, MAKE_SEGPTR(&msgstruct) );
+ HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 1, MAKE_SEGPTR(&msgstruct) );
if (!(wndPtr = WIN_FindWndPtr( hwnd )))
{
ExitSpyMessage(SPY_RESULT_INVALIDHWND,hwnd,msg,0);
@@ -1142,6 +1143,7 @@
{
HINSTANCE ds = msg->hwnd ? WIN_GetWindowInstance( msg->hwnd )
: (HINSTANCE)CURRENT_DS;
+/* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
return CallWndProc( (WNDPROC)msg->lParam, ds, msg->hwnd,
msg->message, msg->wParam, GetTickCount() );
}
@@ -1152,6 +1154,7 @@
if (!wndPtr->lpfnWndProc) return 0;
painting = (msg->message == WM_PAINT);
if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
+/* HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
retval = CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message,
msg->wParam, msg->lParam );
if (painting && IsWindow(msg->hwnd) &&
@@ -1222,6 +1225,14 @@
}
/***********************************************************************
+ * GetCurrentTime (effectively identical to GetTickCount)
+ */
+DWORD GetCurrentTime(void)
+{
+ return GetTickCount();
+}
+
+/***********************************************************************
* InSendMessage (USER.192
*
* According to the book, this should return true iff the current message
diff --git a/windows/utility.c b/windows/utility.c
index 8838394..d0cb299 100644
--- a/windows/utility.c
+++ b/windows/utility.c
@@ -1,5 +1,5 @@
/* utility.c Utility functions for Wine
- * Author: acb
+ * Author: Andrew Bulhak
* Commenced: 10-9-1993
*
* This unit contains the implementations of
@@ -19,8 +19,6 @@
#include "debug.h"
-/* static char Copyright[] = "Copyright Andrew C. Bulhak, 1993"; */
-
/* MulDiv is a simple function that may as well have been
* implemented as a macro; however Microsoft, in their infinite
@@ -424,24 +422,3 @@
return result;
};
-/******************************************************************************
- * DragDetect ( USER.465 )
- *
- * Hardly ever called at all
- */
-
-
-/******************************************************************************
- * DragObject ( USER.464 )
- *
- * responsible for generation of WM_QUERYDROPOBJECT, WM_DRAGLOOP,
- * WM_DRAGMOVE, WM_DROPOBJECT
- */
-LONG DragObject(HWND hDesktop, HWND hWnd, UINT Unknown1, WORD Unknown2, WORD Unknown3, HCURSOR hCursor)
-{
-
- fprintf(stdnimp,"DragObject: EmptyStub!!!\n");
- return 0;
-}
-
-
diff --git a/windows/win.c b/windows/win.c
index 1e0d209..7153ee6 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -31,6 +31,11 @@
static HWND hwndDesktop = 0;
static HWND hWndSysModal = 0;
+static WORD wDragWidth = 8;
+static WORD wDragHeight= 6;
+
+extern HCURSOR CURSORICON_IconToCursor(HICON);
+
/***********************************************************************
* WIN_FindWndPtr
*
@@ -1205,7 +1210,16 @@
*/
BOOL AnyPopup()
{
- dprintf_win(stdnimp,"EMPTY STUB !! AnyPopup !\n");
+ WND *wndPtr = WIN_FindWndPtr(hwndDesktop);
+ HWND hwnd = wndPtr->hwndChild;
+
+ for( ; hwnd ; hwnd = wndPtr->hwndNext )
+ {
+ wndPtr = WIN_FindWndPtr(hwnd);
+ if(wndPtr->hwndOwner)
+ if(wndPtr->dwStyle & WS_VISIBLE)
+ return TRUE;
+ }
return FALSE;
}
@@ -1238,3 +1252,246 @@
{
return hWndSysModal;
}
+
+/*******************************************************************
+ * DRAG_QueryUpdate
+ *
+ * recursively find a child that contains spDragInfo->pt point
+ * and send WM_QUERYDROPOBJECT
+ */
+BOOL DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo )
+{
+ HWND hWnd;
+ BOOL wParam,bResult = 0;
+ POINT pt;
+ LPDRAGINFO ptrDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN(spDragInfo);
+ WND *ptrQueryWnd = WIN_FindWndPtr(hQueryWnd),*ptrWnd;
+ RECT tempRect; /* this sucks */
+
+ if( !ptrQueryWnd || !ptrDragInfo ) return 0;
+
+ pt = ptrDragInfo->pt;
+
+ GetWindowRect(hQueryWnd,&tempRect);
+
+ if( !PtInRect(&tempRect,pt) ||
+ (ptrQueryWnd->dwStyle & WS_DISABLED) )
+ return 0;
+
+ if( !(ptrQueryWnd->dwStyle & WS_MINIMIZE) )
+ {
+ tempRect = ptrQueryWnd->rectClient;
+ if(ptrQueryWnd->dwStyle & WS_CHILD)
+ MapWindowPoints(ptrQueryWnd->hwndParent,0,(LPPOINT)&tempRect,2);
+
+ if( PtInRect(&tempRect,pt) )
+ {
+ wParam = 0;
+ ptrWnd = WIN_FindWndPtr(hWnd = ptrQueryWnd->hwndChild);
+
+ for( ;ptrWnd ;ptrWnd = WIN_FindWndPtr(hWnd = ptrWnd->hwndNext) )
+ if( ptrWnd->dwStyle & WS_VISIBLE )
+ {
+ GetWindowRect(hWnd,&tempRect);
+
+ if( PtInRect(&tempRect,pt) )
+ break;
+ }
+
+ if(ptrWnd)
+ dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT", %i %i - %i %i\n",hWnd,
+ ptrWnd->rectWindow.left,ptrWnd->rectWindow.top,
+ ptrWnd->rectWindow.right,ptrWnd->rectWindow.bottom);
+ else
+ dprintf_msg(stddeb,"DragQueryUpdate: hwnd = "NPFMT"\n",hWnd);
+
+ if(ptrWnd)
+ if( !(ptrWnd->dwStyle & WS_DISABLED) )
+ bResult = DRAG_QueryUpdate(hWnd, spDragInfo);
+
+ if(bResult) return bResult;
+ }
+ else wParam = 1;
+ }
+ else wParam = 1;
+
+ ScreenToClient(hQueryWnd,&ptrDragInfo->pt);
+
+ ptrDragInfo->hScope = hQueryWnd;
+
+ bResult = SendMessage( hQueryWnd ,WM_QUERYDROPOBJECT ,
+ (WPARAM)wParam ,(LPARAM) spDragInfo );
+ if( !bResult )
+ ptrDragInfo->pt = pt;
+
+ return bResult;
+}
+
+/*******************************************************************
+ * DragDetect ( USER.465 )
+ *
+ */
+BOOL DragDetect(HWND hWnd, POINT pt)
+{
+ MSG msg;
+ RECT rect;
+
+ rect.left = pt.x - wDragWidth;
+ rect.right = pt.x + wDragWidth;
+
+ rect.top = pt.y - wDragHeight;
+ rect.bottom = pt.y + wDragHeight;
+
+ SetCapture(hWnd);
+
+ while(1)
+ {
+ while(PeekMessage(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
+ {
+ if( msg.message == WM_LBUTTONUP )
+ {
+ ReleaseCapture();
+ return 0;
+ }
+ if( msg.message == WM_MOUSEMOVE )
+ {
+ POINT pt = { LOWORD(msg.lParam), HIWORD(msg.lParam) };
+ if( !PtInRect( &rect, pt ) )
+ {
+ ReleaseCapture();
+ return 1;
+ }
+ }
+ }
+ WaitMessage();
+ }
+
+ return 0;
+}
+
+/******************************************************************************
+ * DragObject ( USER.464 )
+ *
+ */
+DWORD DragObject(HWND hwndScope, HWND hWnd, WORD wObj, HANDLE hOfStruct,
+ WORD szList , HCURSOR hCursor)
+{
+ MSG msg;
+ LPDRAGINFO lpDragInfo;
+ SEGPTR spDragInfo;
+ HCURSOR hDragCursor=0, hOldCursor=0, hBummer=0;
+ HANDLE hDragInfo = GlobalAlloc( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO));
+ WND *wndPtr = WIN_FindWndPtr(hWnd);
+ DWORD dwRet = 0;
+ short dragDone = 0;
+ HCURSOR hCurrentCursor = 0;
+ HWND hCurrentWnd = 0;
+ WORD btemp;
+
+ fprintf(stdnimp,"DragObject: experimental\n");
+
+ lpDragInfo = (LPDRAGINFO) GlobalLock(hDragInfo);
+ spDragInfo = (SEGPTR) WIN16_GlobalLock(hDragInfo);
+
+ if( !lpDragInfo || !spDragInfo ) return 0L;
+
+ hBummer = LoadCursor(0,IDC_BUMMER);
+
+ if( !hBummer || !wndPtr )
+ {
+ GlobalFree(hDragInfo);
+ return 0L;
+ }
+
+ if(hCursor)
+ {
+ if( !(hDragCursor = CURSORICON_IconToCursor(hCursor)) )
+ {
+ GlobalFree(hDragInfo);
+ return 0L;
+ }
+
+ if( hDragCursor == hCursor ) hDragCursor = 0;
+ else hCursor = hDragCursor;
+
+ hOldCursor = SetCursor(hDragCursor);
+ }
+
+ lpDragInfo->hWnd = hWnd;
+ lpDragInfo->hScope = 0;
+ lpDragInfo->wFlags = wObj;
+ lpDragInfo->hList = szList; /* near pointer! */
+ lpDragInfo->hOfStruct = hOfStruct;
+ lpDragInfo->l = 0L;
+
+ SetCapture(hWnd);
+ ShowCursor(1);
+
+ while( !dragDone )
+ {
+ WaitMessage();
+
+ if( !PeekMessage(&msg,0,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE) )
+ continue;
+
+ *(lpDragInfo+1) = *lpDragInfo;
+
+ lpDragInfo->pt = msg.pt;
+
+ /* update DRAGINFO struct */
+ dprintf_msg(stddeb,"drag: lpDI->hScope = "NPFMT"\n",lpDragInfo->hScope);
+
+ if( (btemp = (WORD)DRAG_QueryUpdate(hwndScope, spDragInfo)) > 0 )
+ hCurrentCursor = hCursor;
+ else
+ {
+ hCurrentCursor = hBummer;
+ lpDragInfo->hScope = 0;
+ }
+ if( hCurrentCursor )
+ SetCursor(hCurrentCursor);
+
+ dprintf_msg(stddeb,"drag: got "NPFMT"\n",btemp);
+
+ /* send WM_DRAGLOOP */
+ SendMessage( hWnd, WM_DRAGLOOP, (WPARAM)(hCurrentCursor != hBummer) ,
+ (LPARAM) spDragInfo );
+ /* send WM_DRAGSELECT or WM_DRAGMOVE */
+ if( hCurrentWnd != lpDragInfo->hScope )
+ {
+ if( hCurrentWnd )
+ SendMessage( hCurrentWnd, WM_DRAGSELECT, 0,
+ (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO),
+ HIWORD(spDragInfo)) );
+ hCurrentWnd = lpDragInfo->hScope;
+ if( hCurrentWnd )
+ SendMessage( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
+ }
+ else
+ if( hCurrentWnd )
+ SendMessage( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
+
+
+ /* check if we're done */
+ if( msg.message == WM_LBUTTONUP || msg.message == WM_NCLBUTTONUP )
+ dragDone = TRUE;
+ }
+
+ ReleaseCapture();
+ ShowCursor(0);
+
+ if( hCursor )
+ {
+ SetCursor(hOldCursor);
+ if( hDragCursor )
+ DestroyCursor(hDragCursor);
+ }
+
+ if( hCurrentCursor != hBummer )
+ dwRet = SendMessage( lpDragInfo->hScope, WM_DROPOBJECT,
+ hWnd, (LPARAM)spDragInfo );
+ GlobalFree(hDragInfo);
+
+ return dwRet;
+}
+
diff --git a/windows/winpos.c b/windows/winpos.c
index 119b265..08a499c 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -616,7 +616,7 @@
WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
if (!wndPtr || (winpos->flags & SWP_NOSIZE)) return 0;
if ((wndPtr->dwStyle & WS_THICKFRAME) ||
- (wndPtr->dwStyle & (WS_POPUP | WS_CHILD) == 0))
+ ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
{
NC_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
winpos->cx = MIN( winpos->cx, maxSize.x );