- implemented correctly the HSZ as local atoms and added the needed

conversions to global atoms
- enhanced internal handle <=> pointer conversions, as well as
  validity of such objects (life time, destruction, mutual access...)
- fixed a few ANSI/Unicode issues, stores most of the data as Unicode
- started having both Ansi/Unicode DDE window procs for message A/W
  transformation
- fixed a few segmented pointer issues (mainly in DdeInitialize &
  DdeGetData)
- added most of the CBF_ flags handling
- implemented the conversation announcement (XTYP_CONNECT_CONFIRM) on
  server side
- enhanced DdeQueryConfig and implemented DdeReconnect
- implemented conversation termination (including XTYP_UNREGISTER)
- several others code clean up
- added transaction support on server side too
This commit is contained in:
Eric Pouech 2001-08-09 22:07:22 +00:00 committed by Alexandre Julliard
parent 7b3495ac93
commit 78a4134e51
10 changed files with 2440 additions and 1929 deletions

View File

@ -37,7 +37,9 @@ RC_SRCS16 = \
resources/mouse.rc \
resources/version16.rc
GLUE = thunk.c
GLUE = \
dde/ddeml16.c \
thunk.c
EXTRA_OBJS = \
$(TOPOBJDIR)/controls/controls.o \

1
dlls/user/dde/.cvsignore Normal file
View File

@ -0,0 +1 @@
ddeml16.glue.c

File diff suppressed because it is too large Load Diff

View File

@ -15,27 +15,17 @@
/* defined in atom.c file.
*/
#define MAX_ATOM_LEN 255
/* Maximum buffer size ( including the '\0' ).
*/
#define MAX_BUFFER_LEN (MAX_ATOM_LEN + 1)
/* This is a simple list to keep track of the strings created
* by DdeCreateStringHandle. The list is used to free
* the strings whenever DdeUninitialize is called.
* This mechanism is not complete and does not handle multiple instances.
* Most of the DDE API use a DWORD parameter indicating which instance
* of a given program is calling them. The API are supposed to
* associate the data to the instance that created it.
*/
/* The internal structures (prefixed by WDML) are used as follows:
* + a WDML_INSTANCE is created for each instance creation (DdeInitialize)
* - a popup windows (InstanceClass) is created for each instance. It will be
* used to receive all the DDEML events (server registration, conversation
* confirmation...)
* - a popup window (InstanceClass) is created for each instance.
* - this window is used to receive all the DDEML events (server registration,
* conversation confirmation...). See the WM_WDML_???? messages for details
* + when registring a server (DdeNameService) a WDML_SERVER is created
* - a popup window (ServerNameClass) is created
* + a conversation is represented by two WDML_CONV structures:
@ -47,6 +37,13 @@
* o a child window (of the ServerName) on the server side
* (ServerConvClass)
* - all the exchanges then take place between those two windows
* - windows for the conversation exist in two forms (Ansi & Unicode). This
* is only needed when a partner in a conv is not handled by DDEML. The
* type (A/W) of the window is used to handle the ansi <=> unicode
* transformations
* - two handles are created for a conversation (on each side). Each handle
* is linked to a structure. To help differentiate those handles, the
* local one has an even value, whereas the remote one has an odd value.
* + a (warm or link) is represented by two WDML_LINK structures:
* - one on client side, the other one on server side
* - therefore, two lists of links are kept for each instance
@ -55,67 +52,77 @@
* - offset 0: the DDE instance
* - offset 4: the current conversation (for ClientConv and ServerConv only)
*
* All the implementation (client & server) makes the assumption that the other side
* is not always a DDEML partner. However, if it's the case, supplementary services
* are available (most notably the REGISTER/UNREGISTER and CONNECT_CONFIRM messages
* to the callback function). To be correct in every situation, all the basic
* exchanges are made using the 'pure' DDE protocol. A (future !) enhancement would
* be to provide a new protocol in the case were both partners are handled by DDEML.
*
* The StringHandles are in fact stored as local atoms. So an HSZ and a (local) atom
* can be used interchangably. However, in order to keep track of the allocated HSZ,
* and to free them upon instance termination, all HSZ are stored in a link list.
* When the HSZ need to be passed thru DDE messages, we need to convert them back and
* forth to global atoms.
*/
/* this struct has the same mapping as all the DDE??? structures */
typedef struct {
unsigned short unused:12,
fResponse:1,
fRelease:1,
fDeferUpd:1,
fAckReq:1;
short cfFormat;
} WINE_DDEHEAD;
typedef struct tagHSZNode
{
struct tagHSZNode* next;
struct tagHSZNode* next;
HSZ hsz;
HSZ hsz2;
unsigned refCount;
} HSZNode;
typedef struct tagWDML_SERVER
{
struct tagWDML_SERVER* next;
HSZ hszService;
HSZ hszTopic;
HSZ hszServiceSpec;
ATOM atomService;
ATOM atomServiceSpec;
BOOL filterOn;
HWND hwndServer;
} WDML_SERVER;
typedef struct tagWDML_XACT {
struct tagWDML_XACT* next;
struct tagWDML_XACT* next; /* list of transactions in conversation */
DWORD xActID;
UINT ddeMsg;
HDDEDATA hDdeData;
DWORD dwTimeout;
DWORD hUser;
union {
struct {
UINT wType;
UINT wFmt;
HSZ hszItem;
HGLOBAL hDdeAdvise;
} advise;
struct {
UINT wFmt;
HSZ hszItem;
} unadvise;
struct {
HGLOBAL hMem;
} execute;
struct {
HGLOBAL hMem;
HSZ hszItem;
} poke;
struct {
HSZ hszItem;
} request;
} u;
UINT wType;
UINT wFmt;
HSZ hszItem;
ATOM atom; /* as converted from or to hszItem */
HGLOBAL hMem;
LPARAM lParam; /* useful for reusing */
} WDML_XACT;
typedef struct tagWDML_CONV
{
struct tagWDML_CONV* next; /* to link all the conversations */
struct tagWDML_INSTANCE* thisInstance;
struct tagWDML_INSTANCE* instance;
HSZ hszService; /* pmt used for connection */
HSZ hszTopic; /* pmt used for connection */
UINT afCmd; /* service name flag */
CONVCONTEXT convContext;
HWND hwndClient; /* source of conversation (ClientConvClass) */
HWND hwndServer; /* destination of conversation (ServerConvClass) */
WDML_XACT* transactions; /* pending transactions (client only) */
WDML_XACT* transactions; /* pending transactions */
DWORD hUser; /* user defined value */
DWORD wStatus; /* same bits as convinfo.wStatus */
DWORD wConvst; /* same values as convinfo.wConvst */
} WDML_CONV;
/* DDE_LINK struct defines hot, warm, and cold links */
@ -132,6 +139,7 @@ typedef struct tagWDML_INSTANCE
{
struct tagWDML_INSTANCE* next;
DWORD instanceID; /* needed to track monitor usage */
DWORD threadID; /* needed to keep instance linked to a unique thread */
BOOL monitor; /* have these two as full Booleans cos they'll be tested frequently */
BOOL clientOnly; /* bit wasteful of space but it will be faster */
BOOL unicode; /* Flag to indicate Win32 API used to initialise */
@ -140,7 +148,6 @@ typedef struct tagWDML_INSTANCE
PFNCALLBACK callback;
DWORD CBFflags;
DWORD monitorFlags;
UINT txnCount; /* count transactions open to simplify closure */
DWORD lastError;
HWND hwndEvent;
WDML_SERVER* servers; /* list of registered servers */
@ -148,9 +155,7 @@ typedef struct tagWDML_INSTANCE
WDML_LINK* links[2]; /* active links for this instance (client and server) */
} WDML_INSTANCE;
extern WDML_INSTANCE* WDML_InstanceList; /* list of created instances, a process can create many */
extern DWORD WDML_MaxInstanceID; /* FIXME: OK for present, may have to worry about wrap-around later */
extern HANDLE handle_mutex;
extern CRITICAL_SECTION WDML_CritSect; /* protection for instance list */
/* header for the DDE Data objects */
typedef struct tagDDE_DATAHANDLE_HEAD
@ -163,46 +168,80 @@ typedef enum tagWDML_SIDE
WDML_CLIENT_SIDE = 0, WDML_SERVER_SIDE = 1
} WDML_SIDE;
/* server calls this. */
extern WDML_SERVER* WDML_AddServer(WDML_INSTANCE* thisInstance, HSZ hszService, HSZ hszTopic);
extern void WDML_RemoveServer(WDML_INSTANCE* thisInstance, HSZ hszService, HSZ hszTopic);
extern WDML_SERVER* WDML_FindServer(WDML_INSTANCE* thisInstance, HSZ hszService, HSZ hszTopic);
typedef enum {
WDML_QS_ERROR, WDML_QS_HANDLED, WDML_QS_PASS, WDML_QS_SWALLOWED, WDML_QS_BLOCK,
} WDML_QUEUE_STATE;
extern HDDEDATA WDML_InvokeCallback(WDML_INSTANCE* pInst, UINT uType, UINT uFmt, HCONV hConv,
HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
DWORD dwData1, DWORD dwData2);
extern HDDEDATA WDML_InvokeCallback16(PFNCALLBACK pfn, UINT uType, UINT uFmt, HCONV hConv,
HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
DWORD dwData1, DWORD dwData2);
extern WDML_SERVER* WDML_AddServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic);
extern void WDML_RemoveServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic);
extern WDML_SERVER* WDML_FindServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic);
/* called both in DdeClientTransaction and server side. */
extern WDML_CONV* WDML_AddConv(WDML_INSTANCE* thisInstance, WDML_SIDE side,
extern UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
DWORD afCmd, DWORD ulRes, BOOL bUnicode, BOOL b16);
extern WDML_CONV* WDML_AddConv(WDML_INSTANCE* pInstance, WDML_SIDE side,
HSZ hszService, HSZ hszTopic, HWND hwndClient, HWND hwndServer);
extern void WDML_RemoveConv(WDML_INSTANCE* thisInstance, WDML_SIDE side, HCONV hConv);
extern WDML_CONV* WDML_GetConv(HCONV hConv);
extern WDML_CONV* WDML_FindConv(WDML_INSTANCE* thisInstance, WDML_SIDE side,
extern void WDML_RemoveConv(WDML_CONV* pConv, WDML_SIDE side);
extern WDML_CONV* WDML_GetConv(HCONV hConv, BOOL checkConnected);
extern WDML_CONV* WDML_GetConvFromWnd(HWND hWnd);
extern WDML_CONV* WDML_FindConv(WDML_INSTANCE* pInstance, WDML_SIDE side,
HSZ hszService, HSZ hszTopic);
extern void WDML_AddLink(WDML_INSTANCE* thisInstance, HCONV hConv, WDML_SIDE side,
extern LPARAM WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode,
BOOL fBusy, BOOL fAck, ATOM atom, LPARAM lParam, UINT oldMsg);
extern void WDML_AddLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
UINT wType, HSZ hszItem, UINT wFmt);
extern WDML_LINK* WDML_FindLink(WDML_INSTANCE* thisInstance, HCONV hConv, WDML_SIDE side,
extern WDML_LINK* WDML_FindLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
HSZ hszItem, UINT uFmt);
extern void WDML_RemoveLink(WDML_INSTANCE* thisInstance, HCONV hConv, WDML_SIDE side,
extern void WDML_RemoveLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
HSZ hszItem, UINT wFmt);
extern void WDML_RemoveAllLinks(WDML_INSTANCE* thisInstance, HCONV hConv, WDML_SIDE side);
extern inline void WDML_ExtractAck(WORD status, DDEACK* da) {*da = *((DDEACK*)&status);}
extern void WDML_RemoveAllLinks(WDML_INSTANCE* pInstance, WDML_CONV* pConv, WDML_SIDE side);
/* string internals */
extern void WDML_FreeAllHSZ(WDML_INSTANCE* pInstance);
extern BOOL WDML_DecHSZ(WDML_INSTANCE* pInstance, HSZ hsz);
extern BOOL WDML_IncHSZ(WDML_INSTANCE* pInstance, HSZ hsz);
extern ATOM WDML_MakeAtomFromHsz(HSZ hsz);
extern HSZ WDML_MakeHszFromAtom(WDML_INSTANCE* pInstance, ATOM atom);
/* client calls these */
extern WDML_XACT* WDML_AllocTransaction(WDML_INSTANCE* thisInstance, UINT ddeMsg);
extern WDML_XACT* WDML_AllocTransaction(WDML_INSTANCE* pInstance, UINT ddeMsg, UINT wFmt, HSZ hszItem);
extern void WDML_QueueTransaction(WDML_CONV* pConv, WDML_XACT* pXAct);
extern BOOL WDML_UnQueueTransaction(WDML_CONV* pConv, WDML_XACT* pXAct);
extern void WDML_FreeTransaction(WDML_XACT* pXAct);
extern void WDML_FreeTransaction(WDML_INSTANCE* pInstance, WDML_XACT* pXAct, BOOL doFreePmt);
extern WDML_XACT* WDML_FindTransaction(WDML_CONV* pConv, DWORD tid);
extern HGLOBAL WDML_DataHandle2Global(HDDEDATA hDdeData, BOOL fResponse, BOOL fRelease,
BOOL fDeferUpd, BOOL dAckReq);
extern HDDEDATA WDML_Global2DataHandle(HGLOBAL hMem);
extern WDML_INSTANCE* WDML_FindInstance(DWORD InstId);
extern BOOL WDML_WaitForMutex(HANDLE mutex);
extern DWORD WDML_ReleaseMutex(HANDLE mutex, LPSTR mutex_name, BOOL release_handle_m);
extern void WDML_FreeAllHSZ(WDML_INSTANCE* thisInstance);
extern void WDML_ReleaseAtom(WDML_INSTANCE* thisInstance, HSZ hsz);
extern void WDML_ReserveAtom(WDML_INSTANCE* thisInstance, HSZ hsz);
extern HDDEDATA WDML_Global2DataHandle(HGLOBAL hMem, WINE_DDEHEAD* da);
extern WDML_INSTANCE* WDML_GetInstance(DWORD InstId);
extern WDML_INSTANCE* WDML_GetInstanceFromWnd(HWND hWnd);
/* broadcasting to DDE windows */
extern void WDML_BroadcastDDEWindows(const char* clsName, UINT uMsg,
WPARAM wParam, LPARAM lParam);
extern void WDML_NotifyThreadExit(DWORD tid);
extern const char WDML_szEventClass[]; /* class of window for events (aka instance) */
extern const char WDML_szEventClass[]; /* class of window for events (aka instance) */
extern const char WDML_szServerConvClassA[]; /* class of window for server side conv (ansi) */
extern const WCHAR WDML_szServerConvClassW[]; /* class of window for server side conv (unicode) */
extern const char WDML_szClientConvClassA[]; /* class of window for client side conv (ansi) */
extern const WCHAR WDML_szClientConvClassW[]; /* class of window for client side conv (unicode) */
#define WM_WDML_REGISTER (WM_USER + 0x200)
#define WM_WDML_UNREGISTER (WM_USER + 0x201)
#define WM_WDML_CONNECT_CONFIRM (WM_USER + 0x202)
/* parameters for messages:
* wParam lParam
* Register atom for service name atom for service spec
* Unregister atom for service name atom for service spec
* ConnectConfirm client window handle server window handle
*/
#define GWL_WDML_INSTANCE (0)
#define GWL_WDML_CONVERSATION (4)
#define GWL_WDML_SERVER (4)
#endif /* __WINE_DDEML_PRIVATE_H */

View File

@ -19,6 +19,7 @@
#include "winerror.h"
#include "dde.h"
#include "ddeml.h"
#include "dde/dde_private.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(ddeml);
@ -54,6 +55,22 @@ typedef struct
CONVCONTEXT16 ConvCtxt;
} CONVINFO16, *LPCONVINFO16;
/* ### start build ### */
extern LONG CALLBACK WDML_CallTo16_long_llllllll (FARPROC16,LONG,LONG,LONG,LONG,LONG,LONG,LONG,LONG);
/* ### stop build ### */
/******************************************************************
* WDML_InvokeCallback16
*
*
*/
HDDEDATA WDML_InvokeCallback16(PFNCALLBACK pfn, UINT uType, UINT uFmt, HCONV hConv,
HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
DWORD dwData1, DWORD dwData2)
{
return WDML_CallTo16_long_llllllll((FARPROC16)pfn, uType, uFmt, hConv,
hsz1, hsz2, hdata, dwData1, dwData2);
}
/******************************************************************************
* DdeInitialize (DDEML.2)
@ -61,8 +78,7 @@ typedef struct
UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
DWORD afCmd, DWORD ulRes)
{
return (UINT16)DdeInitializeA(pidInst,(PFNCALLBACK)pfnCallback,
afCmd, ulRes);
return WDML_Initialize(pidInst, (PFNCALLBACK)pfnCallback, afCmd, ulRes, FALSE, TRUE);
}
/*****************************************************************
@ -145,8 +161,7 @@ BOOL16 WINAPI DdeDisconnect16(HCONV hConv)
*/
BOOL16 WINAPI DdeSetUserHandle16(HCONV hConv, DWORD id, DWORD hUser)
{
FIXME("(%d,%ld,%ld): stub\n",hConv,id, hUser);
return 0;
return DdeSetUserHandle(hConv, id, hUser);
}
/*****************************************************************
@ -167,7 +182,9 @@ HSZ WINAPI DdeCreateStringHandle16(DWORD idInst, LPCSTR str, INT16 codepage)
if (codepage)
{
return DdeCreateStringHandleA(idInst, str, codepage);
} else {
}
else
{
TRACE("Default codepage supplied\n");
return DdeCreateStringHandleA(idInst, str, CP_WINANSI);
}
@ -178,7 +195,7 @@ HSZ WINAPI DdeCreateStringHandle16(DWORD idInst, LPCSTR str, INT16 codepage)
*/
BOOL16 WINAPI DdeFreeStringHandle16(DWORD idInst, HSZ hsz)
{
FIXME("idInst %ld hsz 0x%x\n",idInst,hsz);
TRACE("idInst %ld hsz 0x%x\n",idInst,hsz);
return (BOOL)DdeFreeStringHandle(idInst, hsz);
}
@ -218,8 +235,7 @@ HDDEDATA WINAPI DdeClientTransaction16(LPVOID pData, DWORD cbData,
BOOL16 WINAPI DdeAbandonTransaction16(DWORD idInst, HCONV hConv,
DWORD idTransaction)
{
FIXME("empty stub\n");
return TRUE;
return DdeAbandonTransaction(idInst, hConv, idTransaction);
}
/*****************************************************************
@ -256,7 +272,8 @@ DWORD WINAPI DdeGetData16(
*/
LPBYTE WINAPI DdeAccessData16(HDDEDATA hData, LPDWORD pcbDataSize)
{
return DdeAccessData(hData, pcbDataSize);
/* FIXME: there's a memory leak here... */
return (LPBYTE)MapLS(DdeAccessData(hData, pcbDataSize));
}
/*****************************************************************
@ -264,7 +281,7 @@ LPBYTE WINAPI DdeAccessData16(HDDEDATA hData, LPDWORD pcbDataSize)
*/
BOOL16 WINAPI DdeUnaccessData16(HDDEDATA hData)
{
return DdeUnaccessData(hData);
return DdeUnaccessData(hData);
}
/*****************************************************************
@ -272,7 +289,7 @@ BOOL16 WINAPI DdeUnaccessData16(HDDEDATA hData)
*/
BOOL16 WINAPI DdeEnableCallback16(DWORD idInst, HCONV hConv, UINT16 wCmd)
{
return DdeEnableCallback(idInst, hConv, wCmd);
return DdeEnableCallback(idInst, hConv, wCmd);
}
/*****************************************************************
@ -281,7 +298,7 @@ BOOL16 WINAPI DdeEnableCallback16(DWORD idInst, HCONV hConv, UINT16 wCmd)
HDDEDATA WINAPI DdeNameService16(DWORD idInst, HSZ hsz1, HSZ hsz2,
UINT16 afCmd)
{
return DdeNameService(idInst, hsz1, hsz2, afCmd);
return DdeNameService(idInst, hsz1, hsz2, afCmd);
}
/*****************************************************************
@ -289,7 +306,7 @@ HDDEDATA WINAPI DdeNameService16(DWORD idInst, HSZ hsz1, HSZ hsz2,
*/
UINT16 WINAPI DdeGetLastError16(DWORD idInst)
{
return (UINT16)DdeGetLastError(idInst);
return (UINT16)DdeGetLastError(idInst);
}
/*****************************************************************
@ -297,7 +314,7 @@ UINT16 WINAPI DdeGetLastError16(DWORD idInst)
*/
INT16 WINAPI DdeCmpStringHandles16(HSZ hsz1, HSZ hsz2)
{
return DdeCmpStringHandles(hsz1, hsz2);
return DdeCmpStringHandles(hsz1, hsz2);
}
/******************************************************************

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ debug_channels (accel caret class clipboard combo cursor dc dde ddeml dialog dri
@ stdcall BringWindowToTop(long) BringWindowToTop
@ stdcall BroadcastSystemMessage(long ptr long long long) BroadcastSystemMessage
@ stdcall CalcChildScroll(long long) CalcChildScroll
@ stub CallMsgFilter
@ stdcall CallMsgFilter(ptr long) CallMsgFilterA
@ stdcall CallMsgFilterA(ptr long) CallMsgFilterA
@ stdcall CallMsgFilterW(ptr long) CallMsgFilterW
@ stdcall CallNextHookEx(long long long long) CallNextHookEx
@ -107,8 +107,8 @@ debug_channels (accel caret class clipboard combo cursor dc dde ddeml dialog dri
@ stdcall DdeConnect(long long long ptr) DdeConnect
@ stdcall DdeConnectList(long long long long ptr) DdeConnectList
@ stdcall DdeCreateDataHandle(long ptr long long long long long) DdeCreateDataHandle
@ stdcall DdeCreateStringHandleA(long str long) DdeCreateStringHandleA
@ stdcall DdeCreateStringHandleW(long wstr long) DdeCreateStringHandleW
@ stdcall DdeCreateStringHandleA(long ptr long) DdeCreateStringHandleA
@ stdcall DdeCreateStringHandleW(long ptr long) DdeCreateStringHandleW
@ stdcall DdeDisconnect(long) DdeDisconnect
@ stdcall DdeDisconnectList(long) DdeDisconnectList
@ stdcall DdeEnableCallback(long long long) DdeEnableCallback

View File

@ -262,6 +262,9 @@ static void thread_detach(void)
{
HQUEUE16 hQueue = GetThreadQueue16( 0 );
extern void WDML_NotifyThreadDetach(void);
WDML_NotifyThreadDetach();
if (hQueue)
{
TIMER_RemoveQueueTimers( hQueue );

View File

@ -177,6 +177,8 @@ extern "C" {
#define TIMEOUT_ASYNC 0xFFFFFFFF
#define CADV_LATEACK 0xFFFF
/**************************************************
End of Message Types Section
@ -332,6 +334,7 @@ BOOL WINAPI DdeFreeStringHandle(DWORD,HSZ);
BOOL WINAPI DdeFreeDataHandle(HDDEDATA);
BOOL WINAPI DdeKeepStringHandle(DWORD,HSZ);
HDDEDATA WINAPI DdeClientTransaction(LPBYTE,DWORD,HCONV,HSZ,UINT,UINT,DWORD,LPDWORD);
BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction);
BOOL WINAPI DdeImpersonateClient(HCONV);
BOOL WINAPI DdePostAdvise(DWORD,HSZ,HSZ);
HDDEDATA WINAPI DdeAddData(HDDEDATA,LPBYTE,DWORD,DWORD);