1 /* 2 * DDEML library 3 * 4 * Copyright 1997 Alexandre Julliard 5 * Copyright 1997 Len White 6 * Copyright 1999 Keith Matthews 7 * Copyright 2000 Corel 8 * Copyright 2001 Eric Pouech 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 */ 24 25 #ifndef __WINE_DDEML_PRIVATE_H 26 #define __WINE_DDEML_PRIVATE_H 27 28 /* defined in atom.c file. 29 */ 30 #define MAX_ATOM_LEN 255 31 32 /* Maximum buffer size ( including the '\0' ). 33 */ 34 #define MAX_BUFFER_LEN (MAX_ATOM_LEN + 1) 35 36 /* The internal structures (prefixed by WDML) are used as follows: 37 * + a WDML_INSTANCE is created for each instance creation (DdeInitialize) 38 * - a popup window (InstanceClass) is created for each instance. 39 * - this window is used to receive all the DDEML events (server registration, 40 * conversation confirmation...). See the WM_WDML_???? messages for details 41 * + when registering a server (DdeNameService) a WDML_SERVER is created 42 * - a popup window (ServerNameClass) is created 43 * + a conversation is represented by two WDML_CONV structures: 44 * - one on the client side, the other one on the server side 45 * - this is needed because the address spaces may be different 46 * - therefore, two lists of links are kept for each instance 47 * - two windows are created for a conversation: 48 * o a popup window on client side (ClientConvClass) 49 * o a child window (of the ServerName) on the server side 50 * (ServerConvClass) 51 * - all the exchanges then take place between those two windows 52 * - windows for the conversation exist in two forms (Ansi & Unicode). This 53 * is only needed when a partner in a conv is not handled by DDEML. The 54 * type (A/W) of the window is used to handle the ansi <=> unicode 55 * transformations 56 * - two handles are created for a conversation (on each side). Each handle 57 * is linked to a structure. To help differentiate those handles, the 58 * local one has an even value, whereas the remote one has an odd value. 59 * + a (warm or link) is represented by two WDML_LINK structures: 60 * - one on client side, the other one on server side 61 * - therefore, two lists of links are kept for each instance 62 * 63 * To help getting back to data, WDML windows store information: 64 * - offset 0: the DDE instance 65 * - offset 4: the current conversation (for ClientConv and ServerConv only) 66 * 67 * All the implementation (client & server) makes the assumption that the other side 68 * is not always a DDEML partner. However, if it's the case, supplementary services 69 * are available (most notably the REGISTER/UNREGISTER and CONNECT_CONFIRM messages 70 * to the callback function). To be correct in every situation, all the basic 71 * exchanges are made using the 'pure' DDE protocol. A (future !) enhancement would 72 * be to provide a new protocol in the case were both partners are handled by DDEML. 73 * 74 * The StringHandles are in fact stored as local atoms. So an HSZ and a (local) atom 75 * can be used interchangeably. However, in order to keep track of the allocated HSZ, 76 * and to free them upon instance termination, all HSZ are stored in a link list. 77 * When the HSZ need to be passed through DDE messages, we need to convert them back and 78 * forth to global atoms. 79 */ 80 81 /* this struct has the same mapping as all the DDE??? structures */ 82 typedef struct { 83 unsigned short unused:12, 84 fResponse:1, 85 fRelease:1, 86 fDeferUpd:1, 87 fAckReq:1; 88 short cfFormat; 89 } WINE_DDEHEAD; 90 91 typedef struct tagHSZNode 92 { 93 struct tagHSZNode* next; 94 HSZ hsz; 95 unsigned refCount; 96 } HSZNode; 97 98 typedef struct tagWDML_SERVER 99 { 100 struct tagWDML_SERVER* next; 101 HSZ hszService; 102 HSZ hszServiceSpec; 103 ATOM atomService; 104 ATOM atomServiceSpec; 105 BOOL filterOn; 106 HWND hwndServer; 107 } WDML_SERVER; 108 109 typedef struct tagWDML_XACT { 110 struct tagWDML_XACT* next; /* list of transactions in conversation */ 111 DWORD xActID; 112 UINT ddeMsg; 113 HDDEDATA hDdeData; 114 DWORD dwTimeout; 115 DWORD hUser; 116 UINT wType; 117 UINT wFmt; 118 HSZ hszItem; 119 ATOM atom; /* as converted from or to hszItem */ 120 HGLOBAL hMem; 121 LPARAM lParam; /* useful for reusing */ 122 } WDML_XACT; 123 124 typedef struct tagWDML_CONV 125 { 126 struct tagWDML_CONV* next; /* to link all the conversations */ 127 struct tagWDML_INSTANCE* instance; 128 HSZ hszService; /* pmt used for connection */ 129 HSZ hszTopic; /* pmt used for connection */ 130 UINT magic; /* magic number to check validity */ 131 UINT afCmd; /* service name flag */ 132 CONVCONTEXT convContext; 133 HWND hwndClient; /* source of conversation (ClientConvClass) */ 134 HWND hwndServer; /* destination of conversation (ServerConvClass) */ 135 WDML_XACT* transactions; /* pending transactions */ 136 DWORD hUser; /* user defined value */ 137 DWORD wStatus; /* same bits as convinfo.wStatus */ 138 DWORD wConvst; /* same values as convinfo.wConvst */ 139 } WDML_CONV; 140 141 #define WDML_CONV_MAGIC 0xbabe1234 142 143 /* DDE_LINK struct defines hot, warm, and cold links */ 144 typedef struct tagWDML_LINK { 145 struct tagWDML_LINK* next; /* to link all the active links */ 146 HCONV hConv; /* to get back to the conversation */ 147 UINT transactionType;/* 0 for no link */ 148 HSZ hszItem; /* item targeted for (hot/warm) link */ 149 UINT uFmt; /* format for data */ 150 } WDML_LINK; 151 152 typedef struct tagWDML_INSTANCE 153 { 154 struct tagWDML_INSTANCE* next; 155 DWORD instanceID; /* needed to track monitor usage */ 156 DWORD threadID; /* needed to keep instance linked to a unique thread */ 157 BOOL monitor; /* have these two as full Booleans cos they'll be tested frequently */ 158 BOOL clientOnly; /* bit wasteful of space but it will be faster */ 159 BOOL unicode; /* Flag to indicate Win32 API used to initialise */ 160 HSZNode* nodeList; /* for cleaning upon exit */ 161 PFNCALLBACK callback; 162 DWORD CBFflags; 163 DWORD monitorFlags; 164 DWORD lastError; 165 HWND hwndEvent; 166 DWORD wStatus; /* global instance status */ 167 WDML_SERVER* servers; /* list of registered servers */ 168 WDML_CONV* convs[2]; /* active conversations for this instance (client and server) */ 169 WDML_LINK* links[2]; /* active links for this instance (client and server) */ 170 } WDML_INSTANCE; 171 172 /* header for the DDE Data objects */ 173 typedef struct tagDDE_DATAHANDLE_HEAD 174 { 175 WORD cfFormat; 176 WORD bAppOwned; 177 } DDE_DATAHANDLE_HEAD; 178 179 typedef enum tagWDML_SIDE 180 { 181 WDML_CLIENT_SIDE = 0, WDML_SERVER_SIDE = 1 182 } WDML_SIDE; 183 184 typedef enum { 185 WDML_QS_ERROR, WDML_QS_HANDLED, WDML_QS_PASS, WDML_QS_SWALLOWED, WDML_QS_BLOCK, 186 } WDML_QUEUE_STATE; 187 188 extern HDDEDATA WDML_InvokeCallback(WDML_INSTANCE* pInst, UINT uType, UINT uFmt, HCONV hConv, 189 HSZ hsz1, HSZ hsz2, HDDEDATA hdata, 190 ULONG_PTR dwData1, ULONG_PTR dwData2) DECLSPEC_HIDDEN; 191 extern WDML_SERVER* WDML_AddServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic) DECLSPEC_HIDDEN; 192 extern void WDML_RemoveServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic) DECLSPEC_HIDDEN; 193 extern WDML_SERVER* WDML_FindServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic) DECLSPEC_HIDDEN; 194 /* transaction handler on the server side */ 195 extern WDML_QUEUE_STATE WDML_ServerHandle(WDML_CONV* pConv, WDML_XACT* pXAct) DECLSPEC_HIDDEN; 196 /* transaction handler on the client side */ 197 HDDEDATA WDML_ClientHandle(WDML_CONV *pConv, WDML_XACT *pXAct, DWORD dwTimeout, LPDWORD pdwResult) DECLSPEC_HIDDEN; 198 /* called both in DdeClientTransaction and server side. */ 199 extern WDML_CONV* WDML_AddConv(WDML_INSTANCE* pInstance, WDML_SIDE side, 200 HSZ hszService, HSZ hszTopic, HWND hwndClient, HWND hwndServer) DECLSPEC_HIDDEN; 201 extern void WDML_RemoveConv(WDML_CONV* pConv, WDML_SIDE side) DECLSPEC_HIDDEN; 202 extern WDML_CONV* WDML_GetConv(HCONV hConv, BOOL checkConnected) DECLSPEC_HIDDEN; 203 extern WDML_CONV* WDML_GetConvFromWnd(HWND hWnd) DECLSPEC_HIDDEN; 204 extern WDML_CONV* WDML_FindConv(WDML_INSTANCE* pInstance, WDML_SIDE side, 205 HSZ hszService, HSZ hszTopic) DECLSPEC_HIDDEN; 206 extern BOOL WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode, 207 BOOL fBusy, BOOL fAck, UINT_PTR pmt, LPARAM lParam, UINT oldMsg) DECLSPEC_HIDDEN; 208 extern void WDML_AddLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, 209 UINT wType, HSZ hszItem, UINT wFmt) DECLSPEC_HIDDEN; 210 extern WDML_LINK* WDML_FindLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, 211 HSZ hszItem, BOOL use_fmt, UINT uFmt) DECLSPEC_HIDDEN; 212 extern void WDML_RemoveLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, 213 HSZ hszItem, UINT wFmt) DECLSPEC_HIDDEN; 214 /* string internals */ 215 extern BOOL WDML_DecHSZ(WDML_INSTANCE* pInstance, HSZ hsz) DECLSPEC_HIDDEN; 216 extern BOOL WDML_IncHSZ(WDML_INSTANCE* pInstance, HSZ hsz) DECLSPEC_HIDDEN; 217 extern ATOM WDML_MakeAtomFromHsz(HSZ hsz) DECLSPEC_HIDDEN; 218 extern HSZ WDML_MakeHszFromAtom(const WDML_INSTANCE* pInstance, ATOM atom) DECLSPEC_HIDDEN; 219 /* client calls these */ 220 extern WDML_XACT* WDML_AllocTransaction(WDML_INSTANCE* pInstance, UINT ddeMsg, UINT wFmt, HSZ hszItem) DECLSPEC_HIDDEN; 221 extern void WDML_QueueTransaction(WDML_CONV* pConv, WDML_XACT* pXAct) DECLSPEC_HIDDEN; 222 extern BOOL WDML_UnQueueTransaction(WDML_CONV* pConv, WDML_XACT* pXAct) DECLSPEC_HIDDEN; 223 extern void WDML_FreeTransaction(WDML_INSTANCE* pInstance, WDML_XACT* pXAct, BOOL doFreePmt) DECLSPEC_HIDDEN; 224 extern HGLOBAL WDML_DataHandle2Global(HDDEDATA hDdeData, BOOL fResponse, BOOL fRelease, 225 BOOL fDeferUpd, BOOL dAckReq) DECLSPEC_HIDDEN; 226 extern HDDEDATA WDML_Global2DataHandle(WDML_CONV* pConv, HGLOBAL hMem, WINE_DDEHEAD* da) DECLSPEC_HIDDEN; 227 extern BOOL WDML_IsAppOwned(HDDEDATA hDdeData) DECLSPEC_HIDDEN; 228 extern WDML_INSTANCE* WDML_GetInstance(DWORD InstId) DECLSPEC_HIDDEN; 229 extern WDML_INSTANCE* WDML_GetInstanceFromWnd(HWND hWnd) DECLSPEC_HIDDEN; 230 /* broadcasting to DDE windows */ 231 extern void WDML_BroadcastDDEWindows(LPCWSTR clsName, UINT uMsg, 232 WPARAM wParam, LPARAM lParam) DECLSPEC_HIDDEN; 233 extern void WDML_NotifyThreadExit(DWORD tid) DECLSPEC_HIDDEN; 234 extern void WDML_NotifyThreadDetach(void) DECLSPEC_HIDDEN; 235 236 237 static __inline void WDML_ExtractAck(WORD status, DDEACK* da) 238 { 239 *da = *((DDEACK*)&status); 240 } 241 242 extern const WCHAR WDML_szEventClass[] DECLSPEC_HIDDEN; /* class of window for events (aka instance) */ 243 extern const char WDML_szServerConvClassA[] DECLSPEC_HIDDEN; /* ANSI class of window for server side conv */ 244 extern const WCHAR WDML_szServerConvClassW[] DECLSPEC_HIDDEN; /* unicode class of window for server side conv */ 245 extern const char WDML_szClientConvClassA[] DECLSPEC_HIDDEN; /* ANSI class of window for client side conv */ 246 extern const WCHAR WDML_szClientConvClassW[] DECLSPEC_HIDDEN; /* unicode class of window for client side conv */ 247 248 #define WM_WDML_REGISTER (WM_USER + 0x200) 249 #define WM_WDML_UNREGISTER (WM_USER + 0x201) 250 #define WM_WDML_CONNECT_CONFIRM (WM_USER + 0x202) 251 252 /* parameters for messages: 253 * wParam lParam 254 * Register atom for service name atom for service spec 255 * Unregister atom for service name atom for service spec 256 * ConnectConfirm client window handle server window handle 257 */ 258 259 #define GWL_WDML_INSTANCE (0) 260 #define GWL_WDML_CONVERSATION (sizeof(ULONG_PTR)) 261 #define GWL_WDML_SERVER (sizeof(ULONG_PTR)) 262 263 #endif /* __WINE_DDEML_PRIVATE_H */ 264