mirror of
https://github.com/reactos/wine.git
synced 2024-11-30 07:00:30 +00:00
a845b88ead
Sun May 31 13:40:13 1998 Alexandre Julliard <julliard@lrc.epfl.ch> * [if1632/signal.c] Added display of exception name. * [loader/task.c] Yet another attempt at fixing SwitchStackTo/SwitchStackBack. * [memory/selector.c] [relay32/builtin32.c] [tools/build.c] [win32/kernel32.c] Generate an assembly stub for Win32 register functions to make their names available at link time. * [programs/*/Makefile.in] Added hacks to support old resource compiler. Fri May 29 16:27:14 1998 Marcus Meissner <marcus@jet.franken.de> * [tools/testrun] Merge of my testscripts at home into one single perl program (tested with perl5). Works only on Linux due to 'ps' and 'ipcs' magic. * [controls/menu.c] Added some DefaultMenuItem stubs. * [debugger/stabs.c] Fixed stabs loading, now supports (int,int) typeinfo format used by gcc-2.8 and egcs-1. If it still crashes, please mail me. * [if1632/][relay32/] Added msvideo.dll (stubs only) Replaced some ptr by str for stringcases Added some new stubs (VxDCall, FindCloseNotif....) * [misc/network.c] Some argument fixes. * [misc/registry.c][misc/cpu.c] Registry initialization partially rewritten and enhanced. * [scheduler/*.c] Some additions so we don't do kill(0,SIGUSR1) (kill processgroup instead of targeted thread) Added SetThreadContext. Thu May 28 23:59:59 1998 Bertho Stultiens <bertho@akhphd.au.dk> * [tools/wrc/*] New resource compiler version 1.0.0 (28-May-1998) * [Make.rules.in] [Makefile.in] Changed and added rc rules to point to tools/wrc/wrc. * [configure.in] [include/config.h.in] Added check for function 'stricmp'. * [include/resource.h] Commented out the old resource structure to catch references. It also includes wrc_rsc.h. * [include/wrc_rsc.h] New file. Definitions for the resources generated with wrc. * [include/windows.h] Added #ifdef RC_INVOKED to exclude stdarg.h. Added SS_NOTIFY flag. * [include/winnls.h] Added SUBLANG_* definitions and corrected some defaults. * [loader/libres.c] Changed the sysres load functions to support wrc generated resources. * [resource/sysres_*.rc] Added #include <windows.h> * [resource/sysres.c] Changed declarations to match wrc's output * [resource/Makefile.in] Changed rules to work with wrc. * [tools/makedep.c] Changed generation of .rc file dependencies to .s target. Thu May 28 22:28:39 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de> * [files/file.c][include/windows.c][relay32/kernel32.spec] Implemented GetFileAttributesEx32A/W. * [misc/imagelist.h][include/commctrl.h][relay32/comctl32.spec] Added ImageList_Read and ImageList_Write stubs. Added ImageList_AddIcon function. Added ImageList_LoadImage. It is the same as ImageList_LoadImage32A. * [controls/header.c] Fixed bitmap drawing bug. Added full bitmap support. * [include/commctrl.h] Added missing header macros. * [controls/toolbar.c][include/toolbar.h][include/commctrl.h] [controls/commctrl.c] [relay32/comctl32.spec] First implementation of toolbar control. Implemented CreateToolbar, CreateToolbarEx and CreateMappedBitmap. * [controls/progress.c][controls/status.c] Some code cleanup. * [controls/commctrl.c][include/commctrl.h][relay32/comctl32.spec] Removed CreateStatusWindow16 and DrawStatusText16. CreateStatusWindow is the same as CreateStatusWindow32A. DrawStatusText is the same as DrawStatusText32A. Thu May 28 16:01:28 1998 Matthew J. Francis <asbel@dial.pipex.com> * [objects/bitmap.c] [objects/bitmap.h] [objects/oembitmap.c] [objects/dc.c] [graphics/x11drv/bitblt.c] Added partial implementation of CreateDIBSection, with great thanks to Ulrich Weigand <weigand@informatik.uni-erlangen.de> for contributing the bulk of the patch. Wed May 27 19:04:31 1998 Ulrich Weigand <weigand@informatik.uni-erlangen.de> * [win32/kernel32.c] [if1632/thunk.c] [include/flatthunk.h] ThunkConnect16 and related functions moved to emulator. * [loader/ne/segment.c] Call DllEntryPoint with correct arguments. * [relay32/builtin32.c] Bugfix: Relay debugging did not work for multiple processes. * [controls/menu.c] Bugfix: dwItemData was not set for MF_OWNERDRAW menus. * [if1632/relay.c] [relay32/relay386.c] Relay messages converted to use DPRINTF. * [controls/desktop.c] [relay32/user32.spec] Implemented PaintDesktop. * [files/profile.c] [if1632/kernel.spec] [misc/network.c] [misc/printdrv.c] [relay32/winspool.spec] [win32/ordinals.c] [relay32/kernel32.spec] Some stubs added. * [relay32/mpr.spec] All ordinals were off by one. Tue May 26 13:32:57 1998 Bill Hawes <whawes@star.net> * [misc/lstr.c] [include/casemap.h] [tools/unimap.pl] Added Unicode case conversion routines towupper/towlower, with mapping tables casemap.h created by tools/unimap.pl. * [misc/ntdll.c] [include/winnls.h] [relay32/ntdll.spec] [relay32/advapi.spec] Minimal implementation of IsTextUnicode, just enough to get NT4 notepad to open ascii/unicode files. * [Make.rules.in] [resources/sysres_En.rc] Added include file dlgs.h for building resource files, so that resources can refer to defined values (e.g. pshHelp). * [misc/crtdll.c] [relay32/crtdll.spec] Use towupper/towlower for 32W case conversions. * [memory/string.c] Use towupper for 32W case conversions. * [ole/ole2nls.c] Use towupper for 32W case conversions; fix mem leak; minor cleanup * [controls/edit.c] Added soft break flag to edit state. Print unknown action values for WM_VSCROLL (action 190 occurs when running NT4 notepad.) Mon May 25 22:42:40 1998 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de> * [files/file.c] Care for a pathological case in SetFilePointer. * [graphics/x11drv/xfont.c] Handle longer Font names in LFD_ComposeLFD and try to catch errors. * [loader/pe_image.c] Unload Dummymodule when PE_LoadLibraryEx32A fails with PE_LoadImage (makes Encarta 98 installer proceed). * [misc/registry.c] Move a check for a special case in RegCreateKeyEx32W after the check for existence. Tue May 25 20:18:26 1998 Matthew Becker <mbecker@glasscity.net> * [misc/ntdll.c] Added some stubs, just guessing at the size of their param lists. * [misc/registry.c] Added stubs for RegUnLoadKey, RegSetKeySecurity, RegSaveKey, RegRestoreKey, and RegReplaceKey * [programs/regtest/regtest.c] Updated registry testing program. Sun May 24 18:11:40 1998 Alex Priem <alexp@sci.kun.nl> * [file/profile.c] Added flag 'return_values' to PROFILE_GetSection. Sun May 24 13:41:10 1998 James Juran <jrj120@psu.edu> * [misc/shell.c] [files/directory.c] Documentation/debugging info additions. * [*/*.c] [include/*.h] Moved many extern function definitions to appropriate header files. Cleaned up a few compile warnings. If #include "debug.h" is present, removed #include <stdio.h>. debug.h includes stdio.h, so it is not necessary to include both. * [graphics/*.c] [if1632/signal.c] [ipc/*.c] [scheduler/*.c] [win32/*.c] [windows/*.c] Final patch to convert fprintf statements to new debugging interface. Some fprintfs are still left, especially in the debugger/ directory. However, IMHO, it's not worth the effort to change the rest. Fri May 22 21:58:35 1998 Morten Welinder <terra@diku.dk> * [windows/keyboard.c] Correct handling of keys "`-=[]\;',./". Fri May 22 12:06:00 1998 Per Lindström <pelinstr@algonet.se> * [include/windows.h] [relay32/kernel32.spec] [win32/console.c] Added stub for ReadConsoleOutputCharacter32A. Thu May 21 16:45:48 1998 Pascal Cuoq <pcuoq@ens-lyon.fr> * [ole/ole2nls.c] Began better implementation of LCMapString32A. Not very well tested yet, and still need improvements. * [controls/scroll.c] Documented functions. Wed May 20 21:37:56 1998 Peter Hunnisett <hunnise@nortel.ca> * [include/windows.h][misc/main.c] Change SystemParameterInfo to support SPI_GETHIGHCONTRAST. Also include some missing SPI_ definitions. * [include/dsound.h][multimedia/dsound.c][relay32/dplayx.spec] Added stubs for DirectPlayLobbyCreate[AW]. Not sure if these should go into a new files dplayx.c? Anyone care? * [include/winnls.h] Added two missing flags for the CompareString32 functions.
717 lines
18 KiB
C
717 lines
18 KiB
C
/***************************************************************************
|
|
* Copyright 1995, Technion, Israel Institute of Technology
|
|
* Electrical Eng, Software Lab.
|
|
* Author: Michael Veksler.
|
|
***************************************************************************
|
|
* File: dde_proc.c
|
|
* Purpose : DDE signals and processes functionality for DDE
|
|
***************************************************************************
|
|
*/
|
|
#ifdef CONFIG_IPC
|
|
|
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
|
#define msgbuf mymsg
|
|
#endif
|
|
|
|
#include <sys/time.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
#include <sys/msg.h>
|
|
#include "wintypes.h"
|
|
#include "win.h"
|
|
#include "shm_semaph.h"
|
|
#include "shm_main_blk.h"
|
|
#include "dde_proc.h"
|
|
#include "dde_mem.h"
|
|
#include "dde.h"
|
|
#include "debug.h"
|
|
#include "xmalloc.h"
|
|
|
|
int curr_proc_idx= -1;
|
|
|
|
enum stop_wait_op stop_wait_op=CONT;
|
|
int had_SIGUSR2 = 0;
|
|
sigjmp_buf env_get_ack;
|
|
sigjmp_buf env_wait_x;
|
|
|
|
#define IDX_TO_HWND(idx) (0xfffe - (idx))
|
|
#define HWND_TO_IDX(wnd) (0xfffe - (wnd))
|
|
#define DDE_WIN_INFO(win) ( main_block->windows[HWND_TO_IDX(win)] )
|
|
#define DDE_WIN2PROC(win) ( DDE_WIN_INFO(win).proc_idx )
|
|
#define DDE_IsRemoteWindow(win) ( (win)<0xffff && (win)>=(0xffff-DDE_PROCS))
|
|
#define DDE_SEND 1
|
|
#define DDE_POST 2
|
|
#define DDE_ACK 3
|
|
#define DDE_MSG_SIZE sizeof(MSG16)
|
|
#define FREE_WND (WORD)(-2)
|
|
#define DELETED_WND (WORD)(-3)
|
|
static char *msg_type[4]={"********", "DDE_SEND", "DDE_POST", "DDE_ACK"};
|
|
|
|
struct msg_dat {
|
|
struct msgbuf dat;
|
|
char filler[DDE_MSG_SIZE];
|
|
} ;
|
|
|
|
typedef struct fifo_element {
|
|
int value;
|
|
struct fifo_element *next;
|
|
} fifo_element;
|
|
|
|
struct fifo {
|
|
fifo_element *first; /* first element in the fifo or NULL */
|
|
fifo_element *last; /* last element in the fifo or NULL */
|
|
};
|
|
static struct fifo fifo = {NULL,NULL};
|
|
|
|
void dde_proc_delete(int proc_idx);
|
|
|
|
void dde_proc_add_fifo(int val)
|
|
{
|
|
fifo_element *created;
|
|
|
|
created= (fifo_element*) xmalloc( sizeof(fifo_element) );
|
|
created->value = val;
|
|
created->next = NULL;
|
|
|
|
if (fifo.first==NULL)
|
|
fifo.first= created;
|
|
else
|
|
fifo.last->next= created;
|
|
fifo.last = created;
|
|
}
|
|
|
|
/* get an item from the fifo, and return it.
|
|
* If fifo is empty, return -1
|
|
*/
|
|
int dde_proc_shift_fifo()
|
|
{
|
|
int val;
|
|
fifo_element *deleted;
|
|
|
|
if (fifo.first == NULL)
|
|
return -1;
|
|
|
|
deleted= fifo.first;
|
|
val= deleted->value;
|
|
fifo.first= deleted->next;
|
|
if (fifo.first == NULL)
|
|
fifo.last= NULL;
|
|
|
|
free(deleted);
|
|
return val;
|
|
}
|
|
|
|
static void print_dde_message(char *desc, MSG16 *msg);
|
|
|
|
/* This should be run only when main_block is first allocated. */
|
|
void dde_proc_init(dde_proc proc)
|
|
{
|
|
int proc_num;
|
|
|
|
for (proc_num=0 ; proc_num<DDE_PROCS ; proc_num++, proc++) {
|
|
proc->msg=-1;
|
|
proc->sem=-1;
|
|
proc->shmid=-1;
|
|
proc->pid=-1;
|
|
}
|
|
}
|
|
|
|
/* add current process to the list of processes */
|
|
void dde_proc_add(dde_proc procs)
|
|
{
|
|
dde_proc proc;
|
|
int proc_idx;
|
|
TRACE(dde,"(..)\n");
|
|
shm_write_wait(main_block->sem);
|
|
|
|
/* find free proc_idx and allocate it */
|
|
for (proc_idx=0, proc=procs ; proc_idx<DDE_PROCS ; proc_idx++, proc++)
|
|
if (proc->pid==-1)
|
|
break; /* found! */
|
|
|
|
if (proc_idx<DDE_PROCS) { /* got here beacuse a free was found ? */
|
|
dde_msg_setup(&proc->msg);
|
|
proc->pid=getpid();
|
|
curr_proc_idx=proc_idx;
|
|
shm_sem_init(&proc->sem);
|
|
}
|
|
else {
|
|
fflush(stdout);
|
|
WARN(dde,"Can't allocate process\n");
|
|
}
|
|
shm_write_signal(main_block->sem);
|
|
}
|
|
|
|
/* wait for dde - acknowledge message - or timout */
|
|
static BOOL32 get_ack()
|
|
{
|
|
struct timeval timeout;
|
|
int size;
|
|
struct msg_dat ack_buff;
|
|
|
|
/* timeout after exactly one seconf */
|
|
timeout.tv_sec = 1;
|
|
timeout.tv_usec = 0;
|
|
|
|
sigsetjmp(env_get_ack, 1);
|
|
/* get here after normal execution, or after siglongjmp */
|
|
|
|
do { /* loop to wait for DDE_ACK */
|
|
had_SIGUSR2=0;
|
|
stop_wait_op=CONT; /* sensitive code: disallow siglongjmp */
|
|
size= msgrcv( main_block->proc[curr_proc_idx].msg , &ack_buff.dat,
|
|
1, DDE_ACK, IPC_NOWAIT);
|
|
if (size>=0) {
|
|
TRACE(msg,"get_ack: received DDE_ACK message\n");
|
|
return TRUE;
|
|
}
|
|
if (DDE_GetRemoteMessage()) {
|
|
had_SIGUSR2=1; /* might have recieved SIGUSR2 */
|
|
}
|
|
stop_wait_op=STOP_WAIT_ACK; /* allow siglongjmp */
|
|
|
|
} while (had_SIGUSR2); /* loop if SIGUSR2 was recieved */
|
|
|
|
/* siglongjmp should be enabled at this moment */
|
|
select( 0, NULL, NULL, NULL, &timeout );
|
|
stop_wait_op=CONT; /* disallow further siglongjmp */
|
|
|
|
/* timeout !! (otherwise there would have been a siglongjmp) */
|
|
return FALSE;
|
|
}
|
|
|
|
/* Transfer one message to a given process */
|
|
static BOOL32 DDE_DoOneMessage (int proc_idx, int size, struct msgbuf *msgbuf)
|
|
{
|
|
dde_proc proc= &main_block->proc[ proc_idx ];
|
|
|
|
|
|
if (proc_idx == curr_proc_idx)
|
|
return FALSE;
|
|
|
|
if (kill(proc->pid,0) < 0) {
|
|
/* pid does not exist, or not our */
|
|
dde_proc_delete(proc_idx);
|
|
return FALSE;
|
|
}
|
|
|
|
if (TRACE_ON(dde) || WARN_ON_dde) {
|
|
MSG16 *msg=(MSG16*) &msgbuf->mtext;
|
|
char *title;
|
|
if (msgbuf->mtype==DDE_SEND)
|
|
title="sending dde:";
|
|
else if (msgbuf->mtype==DDE_POST)
|
|
title="posting dde:";
|
|
else
|
|
title=NULL;
|
|
if (title)
|
|
print_dde_message(title, msg);
|
|
else
|
|
WARN(dde, "Unknown message type=0x%lx\n", msgbuf->mtype);
|
|
}
|
|
TRACE(msg, "to proc_idx=%d (pid=%d), queue=%u\n",
|
|
proc_idx, proc->pid, (unsigned)proc->msg);
|
|
if ( proc->msg != -1) {
|
|
TRACE(msg, "doing...(type=%s)\n", msg_type[msgbuf->mtype]);
|
|
size=msgsnd (proc->msg, msgbuf, size, 0);
|
|
|
|
if (size<0) {
|
|
fflush(stdout);
|
|
perror("msgsnd");
|
|
}
|
|
kill(proc->pid,SIGUSR2); /* tell the process there is a message */
|
|
|
|
TRACE(msg, "Trying to get acknowledgment from msg queue=%d\n",
|
|
proc->msg);
|
|
Yield16(); /* force task switch, and */
|
|
/* acknowledgment sending */
|
|
if (get_ack()) {
|
|
return TRUE;
|
|
} else {
|
|
fflush(stdout);
|
|
WARN(dde,"get_ack: DDE_DoOneMessage: timeout\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
WARN(msg, "message not sent, target has no message queue\n");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/* Do some sort of premitive hash table */
|
|
static HWND16 HWND_Local2Remote(HWND16 orig)
|
|
{
|
|
int dde_wnd_idx;
|
|
int deleted_idx= -1;
|
|
WND_DATA *tested;
|
|
WND_DATA *deleted= NULL;
|
|
int i;
|
|
|
|
dde_wnd_idx= orig % DDE_WINDOWS;
|
|
for ( i=0 ; i < DDE_WINDOWS ; i++, dde_wnd_idx++) {
|
|
if (dde_wnd_idx >= DDE_WINDOWS)
|
|
dde_wnd_idx -= DDE_WINDOWS; /* wrap-around */
|
|
|
|
tested= &main_block->windows[ dde_wnd_idx ];
|
|
if (tested->proc_idx == FREE_WND)
|
|
break;
|
|
|
|
if (deleted == NULL && tested->proc_idx == DELETED_WND) {
|
|
deleted= tested;
|
|
deleted_idx= dde_wnd_idx;
|
|
} else if (tested->wnd == orig && tested->proc_idx == curr_proc_idx) {
|
|
return IDX_TO_HWND(dde_wnd_idx);
|
|
}
|
|
}
|
|
if (deleted != NULL) { /* deleted is preferable */
|
|
/* free item, allocate it */
|
|
deleted->proc_idx= curr_proc_idx;
|
|
deleted->wnd = orig;
|
|
return IDX_TO_HWND(deleted_idx);
|
|
}
|
|
if (tested->proc_idx == FREE_WND) {
|
|
tested->proc_idx= curr_proc_idx;
|
|
tested->wnd = orig;
|
|
return IDX_TO_HWND(dde_wnd_idx);
|
|
}
|
|
|
|
WARN(dde, "Can't map any more windows to DDE windows\n");
|
|
return 0;
|
|
}
|
|
|
|
static BOOL32 DDE_DoMessage( MSG16 *msg, int type )
|
|
{
|
|
int proc_idx;
|
|
|
|
MSG16 *remote_message;
|
|
struct msg_dat msg_dat;
|
|
BOOL32 success;
|
|
|
|
if (msg->wParam == 0)
|
|
return FALSE;
|
|
|
|
if (main_block==NULL) {
|
|
if (msg->message >= WM_DDE_FIRST && msg->message <= WM_DDE_LAST)
|
|
DDE_IPC_init();
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (msg->wParam == (HWND16)-1)
|
|
return FALSE;
|
|
|
|
if ( ! DDE_IsRemoteWindow(msg->hwnd) && msg->hwnd!= (HWND16)-1)
|
|
return FALSE;
|
|
|
|
TRACE(msg, "(hwnd=0x%x,msg=0x%x,..) - %s\n",
|
|
(int)msg->hwnd,(int)msg->message,msg_type[type]);
|
|
|
|
|
|
TRACE(msg, "(hwnd=0x%x,msg=0x%x,..) -- HWND_BROADCAST !\n",
|
|
(int)msg->hwnd,(int)msg->message);
|
|
remote_message=(void*)&msg_dat.dat.mtext;
|
|
|
|
memcpy(remote_message, msg, sizeof(*msg));
|
|
remote_message->wParam= HWND_Local2Remote(msg->wParam);
|
|
if (remote_message->wParam == 0)
|
|
return FALSE;
|
|
|
|
msg_dat.dat.mtype=type;
|
|
|
|
if (msg->hwnd == (HWND16)-1) {
|
|
success= FALSE;
|
|
for ( proc_idx=0; proc_idx < DDE_PROCS ; proc_idx++) {
|
|
if (proc_idx == curr_proc_idx)
|
|
continue;
|
|
if (main_block->proc[ proc_idx ].msg != -1)
|
|
success|=DDE_DoOneMessage(proc_idx, DDE_MSG_SIZE, &msg_dat.dat);
|
|
}
|
|
return success;
|
|
} else {
|
|
return DDE_DoOneMessage(DDE_WIN2PROC(msg->hwnd), DDE_MSG_SIZE,
|
|
&msg_dat.dat);
|
|
}
|
|
}
|
|
|
|
BOOL32 DDE_SendMessage( MSG16 *msg)
|
|
{
|
|
return DDE_DoMessage(msg, DDE_SEND);
|
|
}
|
|
|
|
BOOL32 DDE_PostMessage( MSG16 *msg)
|
|
{
|
|
return DDE_DoMessage(msg, DDE_POST);
|
|
}
|
|
|
|
|
|
void dde_proc_send_ack(HWND16 wnd, BOOL32 val) {
|
|
int proc,msg;
|
|
|
|
static struct msgbuf msg_ack={DDE_ACK,{'0'}};
|
|
|
|
proc=DDE_WIN2PROC(wnd);
|
|
msg=main_block->proc[proc].msg;
|
|
TRACE(msg,"sending ACK to wnd=%4x, proc=%d,msg=%d, pid=%d\n",
|
|
wnd,proc,msg,main_block->proc[proc].pid);
|
|
|
|
msg_ack.mtext[0]=val;
|
|
msgsnd (msg, &msg_ack, 1, 0);
|
|
kill(main_block->proc[proc].pid, SIGUSR2);
|
|
}
|
|
|
|
/* return true (non zero) if had a remote message */
|
|
#undef DDE_GetRemoteMessage
|
|
|
|
int DDE_GetRemoteMessage()
|
|
{
|
|
static int nesting=0; /* to avoid infinite recursion */
|
|
|
|
MSG16 *remote_message;
|
|
int size;
|
|
struct msg_dat msg_dat;
|
|
BOOL32 was_sent; /* sent/received */
|
|
BOOL32 passed;
|
|
WND *wndPtr;
|
|
|
|
if (curr_proc_idx==-1) /* do we have DDE initialized ? */
|
|
return 0;
|
|
|
|
if (nesting>10) {
|
|
fflush(stdout);
|
|
ERR(msg, "suspecting infinite recursion, exiting");
|
|
return 0;
|
|
}
|
|
|
|
remote_message=(void*)&msg_dat.dat.mtext;
|
|
|
|
/* test for SendMessage */
|
|
size= msgrcv( main_block->proc[curr_proc_idx].msg , &msg_dat.dat,
|
|
DDE_MSG_SIZE, DDE_SEND, IPC_NOWAIT);
|
|
|
|
if (size==DDE_MSG_SIZE) { /* is this a correct message (if any) ?*/
|
|
was_sent=TRUE;
|
|
TRACE(msg, "DDE:receive sent message. msg=%04x wPar=%04x"
|
|
" lPar=%08lx\n",
|
|
remote_message->message, remote_message->wParam,
|
|
remote_message->lParam);
|
|
} else {
|
|
size= msgrcv( main_block->proc[curr_proc_idx].msg , &msg_dat.dat,
|
|
DDE_MSG_SIZE, DDE_POST, IPC_NOWAIT);
|
|
|
|
if (size==DDE_MSG_SIZE) { /* is this a correct message (if any) ?*/
|
|
was_sent=FALSE;
|
|
TRACE(msg, "DDE:receive posted message. "
|
|
"msg=%04x wPar=%04x lPar=%08lx\n",
|
|
remote_message->message, remote_message->wParam,
|
|
remote_message->lParam);
|
|
}
|
|
else
|
|
return 0; /* no DDE message found */
|
|
}
|
|
|
|
/* At this point we are sure that there is a DDE message,
|
|
* was_sent is TRUE is the message was sent, and false if it was posted
|
|
*/
|
|
|
|
nesting++;
|
|
|
|
if (TRACE_ON(dde)) {
|
|
char *title;
|
|
if (was_sent)
|
|
title="receive sent dde:";
|
|
else
|
|
title="receive posted dde:";
|
|
print_dde_message(title, remote_message);
|
|
}
|
|
|
|
if (remote_message->hwnd != (HWND16) -1 ) {
|
|
HWND16 dde_window= DDE_WIN_INFO(remote_message->hwnd).wnd;
|
|
/* we should know exactly where to send the message (locally)*/
|
|
if (was_sent) {
|
|
TRACE(dde, "SendMessage(wnd=0x%04x, msg=0x%04x, wPar=0x%04x,"
|
|
"lPar=0x%08x\n", dde_window, remote_message->message,
|
|
remote_message->wParam, (int)remote_message->lParam);
|
|
|
|
/* execute the recieved message */
|
|
passed= SendMessage16(dde_window, remote_message->message,
|
|
remote_message->wParam, remote_message->lParam);
|
|
|
|
/* Tell the sended, that the message is here */
|
|
dde_proc_send_ack(remote_message->wParam, passed);
|
|
}
|
|
else {
|
|
passed= PostMessage16(dde_window, remote_message->message,
|
|
remote_message->wParam, remote_message->lParam);
|
|
if (passed == FALSE) {
|
|
/* Tell the sender, that the message is here, and failed */
|
|
dde_proc_send_ack(remote_message->wParam, FALSE);
|
|
}
|
|
else {
|
|
/* ack will be sent later, at the first peek/get message */
|
|
dde_proc_add_fifo(remote_message->wParam);
|
|
}
|
|
}
|
|
nesting--;
|
|
return 1;
|
|
}
|
|
|
|
/* iterate through all the windows */
|
|
for (wndPtr = WIN_FindWndPtr(GetTopWindow32(GetDesktopWindow32()));
|
|
wndPtr != NULL;
|
|
wndPtr = wndPtr->next)
|
|
{
|
|
if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION) {
|
|
if (was_sent)
|
|
SendMessage16( wndPtr->hwndSelf, remote_message->message,
|
|
remote_message->wParam, remote_message->lParam );
|
|
else
|
|
PostMessage16( wndPtr->hwndSelf, remote_message->message,
|
|
remote_message->wParam, remote_message->lParam );
|
|
} /* if */
|
|
} /* for */
|
|
|
|
/* replay with DDE_ACK after broadcasting in DDE_GetRemoteMessage */
|
|
dde_proc_send_ack(remote_message->wParam, TRUE);
|
|
|
|
nesting--;
|
|
return 1;
|
|
}
|
|
|
|
int dde_reschedule()
|
|
{
|
|
int ack_wnd;
|
|
|
|
ack_wnd= dde_proc_shift_fifo();
|
|
if (ack_wnd != -1) {
|
|
dde_proc_send_ack(ack_wnd, TRUE);
|
|
usleep(10000); /* force unix task switch */
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
void dde_msg_setup(int *msg_ptr)
|
|
{
|
|
*msg_ptr= msgget (IPC_PRIVATE, IPC_CREAT | 0700);
|
|
if (*msg_ptr==-1)
|
|
perror("dde_msg_setup fails to get message queue");
|
|
}
|
|
|
|
/* do we have dde handling in the window ?
|
|
* If we have, atom usage will make this instance of wine set up
|
|
* it's IPC stuff.
|
|
*/
|
|
void DDE_TestDDE(HWND16 hwnd)
|
|
{
|
|
static in_test = 0;
|
|
if (in_test++) return;
|
|
if (main_block != NULL) {
|
|
in_test--;
|
|
return;
|
|
}
|
|
TRACE(msg,"(0x%04x)\n", hwnd);
|
|
if (hwnd==0)
|
|
hwnd=-1;
|
|
/* just send a message to see how things are going */
|
|
SendMessage16( hwnd, WM_DDE_INITIATE, 0, 0);
|
|
in_test--;
|
|
}
|
|
|
|
void dde_proc_delete(int proc_idx)
|
|
{
|
|
dde_proc_done(&main_block->proc[proc_idx]);
|
|
}
|
|
void stop_wait(int a)
|
|
{
|
|
|
|
had_SIGUSR2=1;
|
|
switch(stop_wait_op) {
|
|
case STOP_WAIT_ACK:
|
|
siglongjmp(env_get_ack,1);
|
|
break; /* never reached */
|
|
case STOP_WAIT_X:
|
|
siglongjmp(env_wait_x,1);
|
|
break; /* never reached */
|
|
case CONT:
|
|
/* do nothing */
|
|
}
|
|
}
|
|
|
|
static void print_dde_message(char *desc, MSG16 *msg)
|
|
{
|
|
/* extern const char *MessageTypeNames[];*/
|
|
extern int debug_last_handle_size;
|
|
WORD wStatus,hWord;
|
|
void *ptr;
|
|
DDEACK *ddeack;
|
|
DDEADVISE *ddeadvise;
|
|
DDEDATA *ddedata;
|
|
DDEPOKE *ddepoke;
|
|
dbg_decl_str(dde, 2048);
|
|
|
|
if (is_dde_handle(msg->lParam & 0xffff) )
|
|
ptr=DDE_AttachHandle(msg->lParam&0xffff, NULL);
|
|
else
|
|
ptr =NULL;
|
|
wStatus=LOWORD(msg->lParam);
|
|
hWord=HIWORD(msg->lParam);
|
|
|
|
dsprintf(dde,"%s", desc);
|
|
dsprintf(dde,"%04x %04x==%s %04x %08lx ",
|
|
msg->hwnd, msg->message,"",/*MessageTypeNames[msg->message],*/
|
|
msg->wParam, msg->lParam);
|
|
switch(msg->message) {
|
|
case WM_DDE_INITIATE:
|
|
case WM_DDE_REQUEST:
|
|
case WM_DDE_EXECUTE:
|
|
case WM_DDE_TERMINATE:
|
|
/* nothing to do */
|
|
break;
|
|
case WM_DDE_ADVISE:
|
|
/* DDEADVISE: hOptions in WM_DDE_ADVISE message */
|
|
if (ptr) {
|
|
ddeadvise=ptr;
|
|
dsprintf(dde,"fDeferUpd=%d,fAckReq=%d,cfFormat=0x%x",
|
|
ddeadvise->fDeferUpd, ddeadvise->fAckReq,
|
|
ddeadvise->cfFormat);
|
|
} else
|
|
dsprintf(dde,"NO-DATA");
|
|
dsprintf(dde," atom=0x%x",hWord);
|
|
break;
|
|
|
|
case WM_DDE_UNADVISE:
|
|
dsprintf(dde,"format=0x%x, atom=0x%x",wStatus,hWord);
|
|
break;
|
|
case WM_DDE_ACK:
|
|
ddeack=(DDEACK*)&wStatus;
|
|
dsprintf(dde,"bAppReturnCode=%d,fBusy=%d,fAck=%d",
|
|
ddeack->bAppReturnCode, ddeack->fBusy, ddeack->fAck);
|
|
if (ddeack->fAck)
|
|
dsprintf(dde,"(True)");
|
|
else
|
|
dsprintf(dde,"(False)");
|
|
break;
|
|
|
|
case WM_DDE_DATA:
|
|
if (ptr) {
|
|
ddedata=ptr;
|
|
dsprintf(dde,"fResponse=%d,fRelease=%d,"
|
|
"fAckReq=%d,cfFormat=0x%x,value=\"%.*s\"",
|
|
ddedata->fResponse, ddedata->fRelease,
|
|
ddedata->fAckReq, ddedata->cfFormat,
|
|
debug_last_handle_size- (int)sizeof(*ddedata)+1,
|
|
ddedata->Value);
|
|
} else
|
|
dsprintf(dde,"NO-DATA");
|
|
dsprintf(dde," atom=0x%04x",hWord);
|
|
break;
|
|
|
|
case WM_DDE_POKE:
|
|
if (ptr) {
|
|
ddepoke=ptr;
|
|
dsprintf(dde,"fRelease=%d,cfFormat=0x%x,value[0]='%c'",
|
|
ddepoke->fRelease, ddepoke->cfFormat, ddepoke->Value[0]);
|
|
} else
|
|
dsprintf(dde,"NO-DATA");
|
|
dsprintf(dde," atom=0x%04x",hWord);
|
|
break;
|
|
}
|
|
TRACE(dde,"%s\n", dbg_str(dde));
|
|
}
|
|
|
|
void dde_proc_done(dde_proc proc)
|
|
{
|
|
if (proc->msg != -1)
|
|
msgctl(proc->msg, IPC_RMID, NULL);
|
|
proc->msg=-1;
|
|
proc->pid=-1;
|
|
shm_delete_chain(&proc->shmid);
|
|
shm_sem_done(&proc->sem);
|
|
}
|
|
|
|
/* delete entry, if old junk */
|
|
void dde_proc_refresh(dde_proc proc)
|
|
{
|
|
if (proc->pid == -1)
|
|
return;
|
|
|
|
if (kill(proc->pid, 0) != -1)
|
|
return;
|
|
|
|
/* get here if entry non empty, and the process does not exist */
|
|
dde_proc_done(proc);
|
|
}
|
|
|
|
void dde_wnd_setup()
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i < DDE_WINDOWS ; i++)
|
|
main_block->windows[i].proc_idx = FREE_WND;
|
|
}
|
|
|
|
static BOOL32 DDE_ProcHasWindows(int proc_idx)
|
|
{
|
|
WND_DATA *tested;
|
|
int i;
|
|
|
|
for ( i=0 ; i < DDE_WINDOWS ; i++) {
|
|
tested= &main_block->windows[ i ];
|
|
|
|
if (tested->proc_idx == proc_idx)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
/* Look for hwnd in the hash table of DDE windows,
|
|
* Delete it from there. If there are no more windows for this
|
|
* process, remove the process from the DDE data-structure.
|
|
* If there are no more processes - delete the whole DDE struff.
|
|
*
|
|
* This is inefficient, but who cares for the efficiency of this rare
|
|
* operation...
|
|
*/
|
|
void DDE_DestroyWindow(HWND16 hwnd)
|
|
{
|
|
int dde_wnd_idx;
|
|
WND_DATA *tested;
|
|
int i;
|
|
|
|
if (main_block == NULL)
|
|
return;
|
|
|
|
dde_wnd_idx= hwnd % DDE_WINDOWS;
|
|
|
|
for ( i=0 ; i < DDE_WINDOWS ; i++, dde_wnd_idx++) {
|
|
if (dde_wnd_idx >= DDE_WINDOWS)
|
|
dde_wnd_idx -= DDE_WINDOWS; /* wrap-around */
|
|
|
|
tested= &main_block->windows[ dde_wnd_idx ];
|
|
if (tested->proc_idx == FREE_WND)
|
|
return; /* No window will get deleted here */
|
|
|
|
if (tested->wnd == hwnd && tested->proc_idx == curr_proc_idx) {
|
|
dde_reschedule();
|
|
tested->proc_idx= DELETED_WND;
|
|
if (DDE_ProcHasWindows( curr_proc_idx ))
|
|
return;
|
|
while (dde_reschedule()) /* make sure there are no other */
|
|
/* processes waiting for acknowledgment */
|
|
;
|
|
dde_proc_delete( curr_proc_idx );
|
|
if (DDE_no_of_attached() == 1)
|
|
shm_delete_all(-1);
|
|
else {
|
|
shmdt( (void *) main_block);
|
|
main_block= NULL;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* CONFIG_IPC */
|