4 * Copyright 1997 Alexandre Julliard
5 * Copyright 1997 Len White
6 * Copyright 1999 Keith Matthews
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 "wine/port.h"
32 #include "wine/windef16.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ddeml);
41 typedef HDDEDATA (CALLBACK *PFNCALLBACK16)(UINT16,UINT16,HCONV,HSZ,HSZ,HDDEDATA,
52 } CONVCONTEXT16, *LPCONVCONTEXT16;
69 CONVCONTEXT16 ConvCtxt;
70 } CONVINFO16, *LPCONVINFO16;
72 static void map1632_conv_context(CONVCONTEXT* cc32, const CONVCONTEXT16* cc16)
74 cc32->cb = sizeof(*cc32);
75 cc32->wFlags = cc16->wFlags;
76 cc32->wCountryID = cc16->wCountryID;
77 cc32->iCodePage = cc16->iCodePage;
78 cc32->dwLangID = cc16->dwLangID;
79 cc32->dwSecurity = cc16->dwSecurity;
82 static void map3216_conv_context(CONVCONTEXT16* cc16, const CONVCONTEXT* cc32)
84 cc16->cb = sizeof(*cc16);
85 cc16->wFlags = cc32->wFlags;
86 cc16->wCountryID = cc32->wCountryID;
87 cc16->iCodePage = cc32->iCodePage;
88 cc16->dwLangID = cc32->dwLangID;
89 cc16->dwSecurity = cc32->dwSecurity;
92 /******************************************************************
93 * WDML_InvokeCallback16
97 static HDDEDATA CALLBACK WDML_InvokeCallback16(DWORD pfn16, UINT uType, UINT uFmt,
98 HCONV hConv, HSZ hsz1, HSZ hsz2,
99 HDDEDATA hdata, ULONG_PTR dwData1, ULONG_PTR dwData2)
109 case XTYP_WILDCONNECT:
112 map3216_conv_context(&cc16, (const CONVCONTEXT*)dwData1);
121 args[15] = HIWORD(uType);
122 args[14] = LOWORD(uType);
123 args[13] = HIWORD(uFmt);
124 args[12] = LOWORD(uFmt);
125 args[11] = HIWORD(hConv);
126 args[10] = LOWORD(hConv);
127 args[9] = HIWORD(hsz1);
128 args[8] = LOWORD(hsz1);
129 args[7] = HIWORD(hsz2);
130 args[6] = LOWORD(hsz2);
131 args[5] = HIWORD(hdata);
132 args[4] = LOWORD(hdata);
133 args[3] = HIWORD(d1);
134 args[2] = LOWORD(d1);
135 args[1] = HIWORD(dwData2);
136 args[0] = LOWORD(dwData2);
137 WOWCallback16Ex(pfn16, WCB16_PASCAL, sizeof(args), args, (DWORD *)&ret);
142 case XTYP_WILDCONNECT:
143 if (d1 != 0) UnMapLS(d1);
149 #define MAX_THUNKS 32
150 /* As DDEML doesn't provide a way to get back to an InstanceID when
151 * a callback is run, we use thunk in order to implement simply the
152 * 32bit->16bit callback mechanism.
153 * For each 16bit instance, we create a thunk, which will be passed as
154 * a 32bit callback. This thunk also stores (in the code!) the 16bit
155 * address of the 16bit callback, and passes it back to
156 * WDML_InvokeCallback16.
157 * The code below is mainly to create the thunks themselved
159 #include "pshpack1.h"
160 static struct ddeml_thunk
162 BYTE popl_eax; /* popl %eax (return address) */
163 BYTE pushl_func; /* pushl $pfn16 (16bit callback function) */
165 BYTE pushl_eax; /* pushl %eax */
166 BYTE jmp; /* ljmp WDML_InvokeCallback16 */
168 DWORD instId; /* instance ID */
172 static CRITICAL_SECTION ddeml_cs;
173 static CRITICAL_SECTION_DEBUG critsect_debug =
176 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
177 0, 0, { (DWORD_PTR)(__FILE__ ": ddeml_cs") }
179 static CRITICAL_SECTION ddeml_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
181 static struct ddeml_thunk* DDEML_AddThunk(DWORD instId, DWORD pfn16)
183 struct ddeml_thunk* thunk;
187 DDEML16_Thunks = VirtualAlloc(NULL, MAX_THUNKS * sizeof(*DDEML16_Thunks), MEM_COMMIT,
188 PAGE_EXECUTE_READWRITE);
189 if (!DDEML16_Thunks) return NULL;
190 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
192 thunk->popl_eax = 0x58; /* popl %eax */
193 thunk->pushl_func = 0x68; /* pushl $pfn16 */
195 thunk->pushl_eax = 0x50; /* pushl %eax */
196 thunk->jmp = 0xe9; /* jmp WDML_InvokeCallback16 */
197 thunk->callback = (char *)WDML_InvokeCallback16 - (char *)(&thunk->callback + 1);
201 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
203 /* either instId is 0, and we're looking for an empty slot, or
204 * instId is an already existing instance, and we should find its thunk
206 if (thunk->instId == instId)
208 thunk->pfn16 = pfn16;
212 FIXME("Out of ddeml-thunks. Bump MAX_THUNKS\n");
216 /******************************************************************************
217 * DdeInitialize (DDEML.2)
219 UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
220 DWORD afCmd, DWORD ulRes)
223 struct ddeml_thunk* thunk;
225 EnterCriticalSection(&ddeml_cs);
226 if ((thunk = DDEML_AddThunk(*pidInst, (DWORD)pfnCallback)))
228 ret = DdeInitializeA(pidInst, (PFNCALLBACK)thunk, afCmd, ulRes);
229 if (ret == DMLERR_NO_ERROR) thunk->instId = *pidInst;
231 else ret = DMLERR_SYS_ERROR;
232 LeaveCriticalSection(&ddeml_cs);
236 /*****************************************************************
237 * DdeUninitialize (DDEML.3)
239 BOOL16 WINAPI DdeUninitialize16(DWORD idInst)
241 struct ddeml_thunk* thunk;
244 if (!DdeUninitialize(idInst)) return FALSE;
245 EnterCriticalSection(&ddeml_cs);
246 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
248 if (thunk->instId == idInst)
255 LeaveCriticalSection(&ddeml_cs);
256 if (!ret) FIXME("Should never happen\n");
260 /*****************************************************************
261 * DdeConnectList [DDEML.4]
264 HCONVLIST WINAPI DdeConnectList16(DWORD idInst, HSZ hszService, HSZ hszTopic,
265 HCONVLIST hConvList, LPCONVCONTEXT16 pCC16)
268 CONVCONTEXT* pCC = NULL;
271 map1632_conv_context(pCC = &cc, pCC16);
272 return DdeConnectList(idInst, hszService, hszTopic, hConvList, pCC);
275 /*****************************************************************
276 * DdeQueryNextServer [DDEML.5]
278 HCONV WINAPI DdeQueryNextServer16(HCONVLIST hConvList, HCONV hConvPrev)
280 return DdeQueryNextServer(hConvList, hConvPrev);
283 /*****************************************************************
284 * DdeDisconnectList (DDEML.6)
286 BOOL16 WINAPI DdeDisconnectList16(HCONVLIST hConvList)
288 return (BOOL16)DdeDisconnectList(hConvList);
292 /*****************************************************************
293 * DdeQueryString (DDEML.23)
295 DWORD WINAPI DdeQueryString16(DWORD idInst, HSZ hsz, LPSTR lpsz, DWORD cchMax,
298 return DdeQueryStringA(idInst, hsz, lpsz, cchMax, codepage);
301 /*****************************************************************
302 * DdeConnect (DDEML.7)
304 HCONV WINAPI DdeConnect16(DWORD idInst, HSZ hszService, HSZ hszTopic,
305 LPCONVCONTEXT16 pCC16)
308 CONVCONTEXT* pCC = NULL;
311 map1632_conv_context(pCC = &cc, pCC16);
312 return DdeConnect(idInst, hszService, hszTopic, pCC);
315 /*****************************************************************
316 * DdeDisconnect (DDEML.8)
318 BOOL16 WINAPI DdeDisconnect16(HCONV hConv)
320 return (BOOL16)DdeDisconnect(hConv);
323 /*****************************************************************
324 * DdeSetUserHandle (DDEML.10)
326 BOOL16 WINAPI DdeSetUserHandle16(HCONV hConv, DWORD id, DWORD hUser)
328 return DdeSetUserHandle(hConv, id, hUser);
331 /*****************************************************************
332 * DdeCreateDataHandle (DDEML.14)
334 HDDEDATA WINAPI DdeCreateDataHandle16(DWORD idInst, LPBYTE pSrc, DWORD cb,
335 DWORD cbOff, HSZ hszItem, UINT16 wFmt,
338 return DdeCreateDataHandle(idInst, pSrc, cb, cbOff, hszItem, wFmt, afCmd);
341 /*****************************************************************
342 * DdeCreateStringHandle (DDEML.21)
344 HSZ WINAPI DdeCreateStringHandle16(DWORD idInst, LPCSTR str, INT16 codepage)
348 return DdeCreateStringHandleA(idInst, str, codepage);
352 TRACE("Default codepage supplied\n");
353 return DdeCreateStringHandleA(idInst, str, CP_WINANSI);
357 /*****************************************************************
358 * DdeFreeStringHandle (DDEML.22)
360 BOOL16 WINAPI DdeFreeStringHandle16(DWORD idInst, HSZ hsz)
362 return (BOOL16)DdeFreeStringHandle(idInst, hsz);
365 /*****************************************************************
366 * DdeFreeDataHandle (DDEML.19)
368 BOOL16 WINAPI DdeFreeDataHandle16(HDDEDATA hData)
370 return (BOOL16)DdeFreeDataHandle(hData);
373 /*****************************************************************
374 * DdeKeepStringHandle (DDEML.24)
376 BOOL16 WINAPI DdeKeepStringHandle16(DWORD idInst, HSZ hsz)
378 return DdeKeepStringHandle(idInst, hsz);
381 /*****************************************************************
382 * DdeClientTransaction (DDEML.11)
384 HDDEDATA WINAPI DdeClientTransaction16(LPVOID pData, DWORD cbData, HCONV hConv,
385 HSZ hszItem, UINT16 wFmt, UINT16 wType,
386 DWORD dwTimeout, LPDWORD pdwResult)
388 return DdeClientTransaction(pData, cbData, hConv, hszItem,
389 wFmt, wType, dwTimeout, pdwResult);
392 /*****************************************************************
394 * DdeAbandonTransaction (DDEML.12)
397 BOOL16 WINAPI DdeAbandonTransaction16(DWORD idInst, HCONV hConv, DWORD idTransaction)
399 return (BOOL16)DdeAbandonTransaction(idInst, hConv, idTransaction);
402 /*****************************************************************
403 * DdePostAdvise [DDEML.13]
405 BOOL16 WINAPI DdePostAdvise16(DWORD idInst, HSZ hszTopic, HSZ hszItem)
407 return (BOOL16)DdePostAdvise(idInst, hszTopic, hszItem);
410 /*****************************************************************
411 * DdeAddData (DDEML.15)
413 HDDEDATA WINAPI DdeAddData16(HDDEDATA hData, LPBYTE pSrc, DWORD cb, DWORD cbOff)
415 return DdeAddData(hData, pSrc, cb, cbOff);
418 /*****************************************************************
419 * DdeGetData [DDEML.16]
421 DWORD WINAPI DdeGetData16(HDDEDATA hData, LPBYTE pDst, DWORD cbMax, DWORD cbOff)
423 return DdeGetData(hData, pDst, cbMax, cbOff);
426 /*****************************************************************
427 * DdeAccessData (DDEML.17)
429 LPBYTE WINAPI DdeAccessData16(HDDEDATA hData, LPDWORD pcbDataSize)
431 FIXME("expect trouble\n");
432 /* FIXME: there's a memory leak here... */
433 return (LPBYTE)MapLS(DdeAccessData(hData, pcbDataSize));
436 /*****************************************************************
437 * DdeUnaccessData (DDEML.18)
439 BOOL16 WINAPI DdeUnaccessData16(HDDEDATA hData)
441 return DdeUnaccessData(hData);
444 /*****************************************************************
445 * DdeEnableCallback (DDEML.26)
447 BOOL16 WINAPI DdeEnableCallback16(DWORD idInst, HCONV hConv, UINT16 wCmd)
449 return DdeEnableCallback(idInst, hConv, wCmd);
452 /*****************************************************************
453 * DdeNameService (DDEML.27)
455 HDDEDATA WINAPI DdeNameService16(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT16 afCmd)
457 return DdeNameService(idInst, hsz1, hsz2, afCmd);
460 /*****************************************************************
461 * DdeGetLastError (DDEML.20)
463 UINT16 WINAPI DdeGetLastError16(DWORD idInst)
465 return (UINT16)DdeGetLastError(idInst);
468 /*****************************************************************
469 * DdeCmpStringHandles (DDEML.36)
471 INT16 WINAPI DdeCmpStringHandles16(HSZ hsz1, HSZ hsz2)
473 return DdeCmpStringHandles(hsz1, hsz2);
476 /******************************************************************
477 * DdeQueryConvInfo (DDEML.9)
480 UINT16 WINAPI DdeQueryConvInfo16(HCONV hConv, DWORD idTransaction,
481 LPCONVINFO16 lpConvInfo)
487 ci32.cb = sizeof(ci32);
488 ci32.ConvCtxt.cb = sizeof(ci32.ConvCtxt);
490 ret = DdeQueryConvInfo(hConv, idTransaction, &ci32);
491 if (ret == 0) return 0;
493 ci16.hUser = ci32.hUser;
494 ci16.hConvPartner = ci32.hConvPartner;
495 ci16.hszSvcPartner = ci32.hszSvcPartner;
496 ci16.hszServiceReq = ci32.hszServiceReq;
497 ci16.hszTopic = ci32.hszTopic;
498 ci16.hszItem = ci32.hszItem;
499 ci16.wFmt = ci32.wFmt;
500 ci16.wType = ci32.wType;
501 ci16.wStatus = ci32.wStatus;
502 ci16.wConvst = ci32.wConvst;
503 ci16.wLastError = ci32.wLastError;
504 ci16.hConvList = ci32.hConvList;
506 map3216_conv_context(&ci16.ConvCtxt, &ci32.ConvCtxt);
508 memcpy(lpConvInfo, &ci16, lpConvInfo->cb);
509 return lpConvInfo->cb;