mf/session: Forward more events to the application.
[wine/zf.git] / dlls / ddeml.dll16 / ddeml.c
blobc1ca8f75e1d1954fdf2815a29e3a89256caf19e1
1 /*
2 * DDEML library
4 * Copyright 1997 Alexandre Julliard
5 * Copyright 1997 Len White
6 * Copyright 1999 Keith Matthews
7 * Copyright 2000 Corel
8 * Copyright 2001,2002,2009 Eric Pouech
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.
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.
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
26 #include <stdarg.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/windef16.h"
31 #include "wine/winbase16.h"
32 #include "wownt32.h"
33 #include "dde.h"
34 #include "ddeml.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ddeml);
40 typedef HDDEDATA (CALLBACK *PFNCALLBACK16)(UINT16,UINT16,HCONV,HSZ,HSZ,HDDEDATA,
41 DWORD,DWORD);
43 typedef struct
45 UINT16 cb;
46 UINT16 wFlags;
47 UINT16 wCountryID;
48 INT16 iCodePage;
49 DWORD dwLangID;
50 DWORD dwSecurity;
51 } CONVCONTEXT16, *LPCONVCONTEXT16;
53 typedef struct
55 DWORD cb;
56 DWORD hUser;
57 HCONV hConvPartner;
58 HSZ hszSvcPartner;
59 HSZ hszServiceReq;
60 HSZ hszTopic;
61 HSZ hszItem;
62 UINT16 wFmt;
63 UINT16 wType;
64 UINT16 wStatus;
65 UINT16 wConvst;
66 UINT16 wLastError;
67 HCONVLIST hConvList;
68 CONVCONTEXT16 ConvCtxt;
69 } CONVINFO16, *LPCONVINFO16;
71 static void map1632_conv_context(CONVCONTEXT* cc32, const CONVCONTEXT16* cc16)
73 cc32->cb = sizeof(*cc32);
74 cc32->wFlags = cc16->wFlags;
75 cc32->wCountryID = cc16->wCountryID;
76 cc32->iCodePage = cc16->iCodePage;
77 cc32->dwLangID = cc16->dwLangID;
78 cc32->dwSecurity = cc16->dwSecurity;
81 static void map3216_conv_context(CONVCONTEXT16* cc16, const CONVCONTEXT* cc32)
83 cc16->cb = sizeof(*cc16);
84 cc16->wFlags = cc32->wFlags;
85 cc16->wCountryID = cc32->wCountryID;
86 cc16->iCodePage = cc32->iCodePage;
87 cc16->dwLangID = cc32->dwLangID;
88 cc16->dwSecurity = cc32->dwSecurity;
91 /******************************************************************
92 * WDML_InvokeCallback16
96 static HDDEDATA CALLBACK WDML_InvokeCallback16(DWORD pfn16, UINT uType, UINT uFmt,
97 HCONV hConv, HSZ hsz1, HSZ hsz2,
98 HDDEDATA hdata, ULONG_PTR dwData1, ULONG_PTR dwData2)
100 DWORD d1 = 0;
101 HDDEDATA ret;
102 CONVCONTEXT16 cc16;
103 WORD args[16];
105 switch (uType)
107 case XTYP_CONNECT:
108 case XTYP_WILDCONNECT:
109 if (dwData1)
111 map3216_conv_context(&cc16, (const CONVCONTEXT*)dwData1);
112 d1 = MapLS(&cc16);
114 break;
115 default:
116 d1 = dwData1;
117 break;
119 args[15] = HIWORD(uType);
120 args[14] = LOWORD(uType);
121 args[13] = HIWORD(uFmt);
122 args[12] = LOWORD(uFmt);
123 args[11] = HIWORD(hConv);
124 args[10] = LOWORD(hConv);
125 args[9] = HIWORD(hsz1);
126 args[8] = LOWORD(hsz1);
127 args[7] = HIWORD(hsz2);
128 args[6] = LOWORD(hsz2);
129 args[5] = HIWORD(hdata);
130 args[4] = LOWORD(hdata);
131 args[3] = HIWORD(d1);
132 args[2] = LOWORD(d1);
133 args[1] = HIWORD(dwData2);
134 args[0] = LOWORD(dwData2);
135 WOWCallback16Ex(pfn16, WCB16_PASCAL, sizeof(args), args, (DWORD *)&ret);
137 switch (uType)
139 case XTYP_CONNECT:
140 case XTYP_WILDCONNECT:
141 if (d1 != 0) UnMapLS(d1);
142 break;
144 return ret;
147 #define MAX_THUNKS 32
148 /* As DDEML doesn't provide a way to get back to an InstanceID when
149 * a callback is run, we use thunk in order to implement simply the
150 * 32bit->16bit callback mechanism.
151 * For each 16bit instance, we create a thunk, which will be passed as
152 * a 32bit callback. This thunk also stores (in the code!) the 16bit
153 * address of the 16bit callback, and passes it back to
154 * WDML_InvokeCallback16.
155 * The code below is mainly to create the thunks themselves
157 #include "pshpack1.h"
158 static struct ddeml_thunk
160 BYTE popl_eax; /* popl %eax (return address) */
161 BYTE pushl_func; /* pushl $pfn16 (16bit callback function) */
162 SEGPTR pfn16;
163 BYTE pushl_eax; /* pushl %eax */
164 BYTE jmp; /* ljmp WDML_InvokeCallback16 */
165 DWORD callback;
166 DWORD instId; /* instance ID */
167 } *DDEML16_Thunks;
168 #include "poppack.h"
170 static CRITICAL_SECTION ddeml_cs;
171 static CRITICAL_SECTION_DEBUG critsect_debug =
173 0, 0, &ddeml_cs,
174 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
175 0, 0, { (DWORD_PTR)(__FILE__ ": ddeml_cs") }
177 static CRITICAL_SECTION ddeml_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
179 static struct ddeml_thunk* DDEML_AddThunk(DWORD instId, DWORD pfn16)
181 struct ddeml_thunk* thunk;
183 if (!DDEML16_Thunks)
185 DDEML16_Thunks = VirtualAlloc(NULL, MAX_THUNKS * sizeof(*DDEML16_Thunks), MEM_COMMIT,
186 PAGE_EXECUTE_READWRITE);
187 if (!DDEML16_Thunks) return NULL;
188 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
190 thunk->popl_eax = 0x58; /* popl %eax */
191 thunk->pushl_func = 0x68; /* pushl $pfn16 */
192 thunk->pfn16 = 0;
193 thunk->pushl_eax = 0x50; /* pushl %eax */
194 thunk->jmp = 0xe9; /* jmp WDML_InvokeCallback16 */
195 thunk->callback = (char *)WDML_InvokeCallback16 - (char *)(&thunk->callback + 1);
196 thunk->instId = 0;
199 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
201 /* either instId is 0, and we're looking for an empty slot, or
202 * instId is an already existing instance, and we should find its thunk
204 if (thunk->instId == instId)
206 thunk->pfn16 = pfn16;
207 return thunk;
210 FIXME("Out of ddeml-thunks. Bump MAX_THUNKS\n");
211 return NULL;
214 /******************************************************************************
215 * DdeInitialize (DDEML.2)
217 UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
218 DWORD afCmd, DWORD ulRes)
220 UINT16 ret;
221 struct ddeml_thunk* thunk;
223 EnterCriticalSection(&ddeml_cs);
224 if ((thunk = DDEML_AddThunk(*pidInst, (DWORD)pfnCallback)))
226 ret = DdeInitializeA(pidInst, (PFNCALLBACK)thunk, afCmd, ulRes);
227 if (ret == DMLERR_NO_ERROR) thunk->instId = *pidInst;
229 else ret = DMLERR_SYS_ERROR;
230 LeaveCriticalSection(&ddeml_cs);
231 return ret;
234 /*****************************************************************
235 * DdeUninitialize (DDEML.3)
237 BOOL16 WINAPI DdeUninitialize16(DWORD idInst)
239 struct ddeml_thunk* thunk;
240 BOOL16 ret = FALSE;
242 if (!DdeUninitialize(idInst)) return FALSE;
243 EnterCriticalSection(&ddeml_cs);
244 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
246 if (thunk->instId == idInst)
248 thunk->instId = 0;
249 ret = TRUE;
250 break;
253 LeaveCriticalSection(&ddeml_cs);
254 if (!ret) FIXME("Should never happen\n");
255 return ret;
258 /*****************************************************************
259 * DdeConnectList [DDEML.4]
262 HCONVLIST WINAPI DdeConnectList16(DWORD idInst, HSZ hszService, HSZ hszTopic,
263 HCONVLIST hConvList, LPCONVCONTEXT16 pCC16)
265 CONVCONTEXT cc;
266 CONVCONTEXT* pCC = NULL;
268 if (pCC16)
269 map1632_conv_context(pCC = &cc, pCC16);
270 return DdeConnectList(idInst, hszService, hszTopic, hConvList, pCC);
273 /*****************************************************************
274 * DdeQueryNextServer [DDEML.5]
276 HCONV WINAPI DdeQueryNextServer16(HCONVLIST hConvList, HCONV hConvPrev)
278 return DdeQueryNextServer(hConvList, hConvPrev);
281 /*****************************************************************
282 * DdeDisconnectList (DDEML.6)
284 BOOL16 WINAPI DdeDisconnectList16(HCONVLIST hConvList)
286 return (BOOL16)DdeDisconnectList(hConvList);
290 /*****************************************************************
291 * DdeQueryString (DDEML.23)
293 DWORD WINAPI DdeQueryString16(DWORD idInst, HSZ hsz, LPSTR lpsz, DWORD cchMax,
294 INT16 codepage)
296 return DdeQueryStringA(idInst, hsz, lpsz, cchMax, codepage);
299 /*****************************************************************
300 * DdeConnect (DDEML.7)
302 HCONV WINAPI DdeConnect16(DWORD idInst, HSZ hszService, HSZ hszTopic,
303 LPCONVCONTEXT16 pCC16)
305 CONVCONTEXT cc;
306 CONVCONTEXT* pCC = NULL;
308 if (pCC16)
309 map1632_conv_context(pCC = &cc, pCC16);
310 return DdeConnect(idInst, hszService, hszTopic, pCC);
313 /*****************************************************************
314 * DdeDisconnect (DDEML.8)
316 BOOL16 WINAPI DdeDisconnect16(HCONV hConv)
318 return (BOOL16)DdeDisconnect(hConv);
321 /*****************************************************************
322 * DdeSetUserHandle (DDEML.10)
324 BOOL16 WINAPI DdeSetUserHandle16(HCONV hConv, DWORD id, DWORD hUser)
326 return DdeSetUserHandle(hConv, id, hUser);
329 /*****************************************************************
330 * DdeCreateDataHandle (DDEML.14)
332 HDDEDATA WINAPI DdeCreateDataHandle16(DWORD idInst, LPBYTE pSrc, DWORD cb,
333 DWORD cbOff, HSZ hszItem, UINT16 wFmt,
334 UINT16 afCmd)
336 return DdeCreateDataHandle(idInst, pSrc, cb, cbOff, hszItem, wFmt, afCmd);
339 /*****************************************************************
340 * DdeCreateStringHandle (DDEML.21)
342 HSZ WINAPI DdeCreateStringHandle16(DWORD idInst, LPCSTR str, INT16 codepage)
344 if (codepage)
346 return DdeCreateStringHandleA(idInst, str, codepage);
348 else
350 TRACE("Default codepage supplied\n");
351 return DdeCreateStringHandleA(idInst, str, CP_WINANSI);
355 /*****************************************************************
356 * DdeFreeStringHandle (DDEML.22)
358 BOOL16 WINAPI DdeFreeStringHandle16(DWORD idInst, HSZ hsz)
360 return (BOOL16)DdeFreeStringHandle(idInst, hsz);
363 /*****************************************************************
364 * DdeFreeDataHandle (DDEML.19)
366 BOOL16 WINAPI DdeFreeDataHandle16(HDDEDATA hData)
368 return (BOOL16)DdeFreeDataHandle(hData);
371 /*****************************************************************
372 * DdeKeepStringHandle (DDEML.24)
374 BOOL16 WINAPI DdeKeepStringHandle16(DWORD idInst, HSZ hsz)
376 return DdeKeepStringHandle(idInst, hsz);
379 /*****************************************************************
380 * DdeClientTransaction (DDEML.11)
382 HDDEDATA WINAPI DdeClientTransaction16(LPVOID pData, DWORD cbData, HCONV hConv,
383 HSZ hszItem, UINT16 wFmt, UINT16 wType,
384 DWORD dwTimeout, LPDWORD pdwResult)
386 if (cbData != (DWORD)-1)
388 /* pData is not a pointer if cbData is -1, so we linearize the address
389 * here rather than in the calling code. */
390 pData = MapSL((SEGPTR)pData);
392 return DdeClientTransaction(pData, cbData, hConv, hszItem,
393 wFmt, wType, dwTimeout, pdwResult);
396 /*****************************************************************
398 * DdeAbandonTransaction (DDEML.12)
401 BOOL16 WINAPI DdeAbandonTransaction16(DWORD idInst, HCONV hConv, DWORD idTransaction)
403 return (BOOL16)DdeAbandonTransaction(idInst, hConv, idTransaction);
406 /*****************************************************************
407 * DdePostAdvise [DDEML.13]
409 BOOL16 WINAPI DdePostAdvise16(DWORD idInst, HSZ hszTopic, HSZ hszItem)
411 return (BOOL16)DdePostAdvise(idInst, hszTopic, hszItem);
414 /*****************************************************************
415 * DdeAddData (DDEML.15)
417 HDDEDATA WINAPI DdeAddData16(HDDEDATA hData, LPBYTE pSrc, DWORD cb, DWORD cbOff)
419 return DdeAddData(hData, pSrc, cb, cbOff);
422 /*****************************************************************
423 * DdeGetData [DDEML.16]
425 DWORD WINAPI DdeGetData16(HDDEDATA hData, LPBYTE pDst, DWORD cbMax, DWORD cbOff)
427 return DdeGetData(hData, pDst, cbMax, cbOff);
430 /*****************************************************************
431 * DdeAccessData (DDEML.17)
433 LPBYTE WINAPI DdeAccessData16(HDDEDATA hData, LPDWORD pcbDataSize)
435 FIXME("expect trouble\n");
436 /* FIXME: there's a memory leak here... */
437 return (LPBYTE)MapLS(DdeAccessData(hData, pcbDataSize));
440 /*****************************************************************
441 * DdeUnaccessData (DDEML.18)
443 BOOL16 WINAPI DdeUnaccessData16(HDDEDATA hData)
445 return DdeUnaccessData(hData);
448 /*****************************************************************
449 * DdeEnableCallback (DDEML.26)
451 BOOL16 WINAPI DdeEnableCallback16(DWORD idInst, HCONV hConv, UINT16 wCmd)
453 return DdeEnableCallback(idInst, hConv, wCmd);
456 /*****************************************************************
457 * DdeNameService (DDEML.27)
459 HDDEDATA WINAPI DdeNameService16(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT16 afCmd)
461 return DdeNameService(idInst, hsz1, hsz2, afCmd);
464 /*****************************************************************
465 * DdeGetLastError (DDEML.20)
467 UINT16 WINAPI DdeGetLastError16(DWORD idInst)
469 return (UINT16)DdeGetLastError(idInst);
472 /*****************************************************************
473 * DdeCmpStringHandles (DDEML.36)
475 INT16 WINAPI DdeCmpStringHandles16(HSZ hsz1, HSZ hsz2)
477 return DdeCmpStringHandles(hsz1, hsz2);
480 /******************************************************************
481 * DdeQueryConvInfo (DDEML.9)
484 UINT16 WINAPI DdeQueryConvInfo16(HCONV hConv, DWORD idTransaction,
485 LPCONVINFO16 lpConvInfo)
487 CONVINFO ci32;
488 CONVINFO16 ci16;
489 UINT ret;
491 ci32.cb = sizeof(ci32);
492 ci32.ConvCtxt.cb = sizeof(ci32.ConvCtxt);
494 ret = DdeQueryConvInfo(hConv, idTransaction, &ci32);
495 if (ret == 0) return 0;
497 ci16.cb = lpConvInfo->cb;
498 ci16.hUser = ci32.hUser;
499 ci16.hConvPartner = ci32.hConvPartner;
500 ci16.hszSvcPartner = ci32.hszSvcPartner;
501 ci16.hszServiceReq = ci32.hszServiceReq;
502 ci16.hszTopic = ci32.hszTopic;
503 ci16.hszItem = ci32.hszItem;
504 ci16.wFmt = ci32.wFmt;
505 ci16.wType = ci32.wType;
506 ci16.wStatus = ci32.wStatus;
507 ci16.wConvst = ci32.wConvst;
508 ci16.wLastError = ci32.wLastError;
509 ci16.hConvList = ci32.hConvList;
511 map3216_conv_context(&ci16.ConvCtxt, &ci32.ConvCtxt);
513 memcpy(lpConvInfo, &ci16, lpConvInfo->cb);
514 return lpConvInfo->cb;