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 static struct ddeml_thunk
161 BYTE popl_eax; /* popl %eax (return address) */
162 BYTE pushl_func; /* pushl $pfn16 (16bit callback function) */
164 BYTE pushl_eax; /* pushl %eax */
165 BYTE jmp; /* ljmp WDML_InvokeCallback16 */
167 DWORD instId; /* instance ID */
170 static CRITICAL_SECTION ddeml_cs;
171 static CRITICAL_SECTION_DEBUG critsect_debug =
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;
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 */
193 thunk->pushl_eax = 0x50; /* pushl %eax */
194 thunk->jmp = 0xe9; /* jmp WDML_InvokeCallback16 */
195 thunk->callback = (char *)WDML_InvokeCallback16 - (char *)(&thunk->callback + 1);
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;
210 FIXME("Out of ddeml-thunks. Bump MAX_THUNKS\n");
214 /******************************************************************************
215 * DdeInitialize (DDEML.2)
217 UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
218 DWORD afCmd, DWORD ulRes)
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);
234 /*****************************************************************
235 * DdeUninitialize (DDEML.3)
237 BOOL16 WINAPI DdeUninitialize16(DWORD idInst)
239 struct ddeml_thunk* thunk;
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)
253 LeaveCriticalSection(&ddeml_cs);
254 if (!ret) FIXME("Should never happen\n");
258 /*****************************************************************
259 * DdeConnectList [DDEML.4]
262 HCONVLIST WINAPI DdeConnectList16(DWORD idInst, HSZ hszService, HSZ hszTopic,
263 HCONVLIST hConvList, LPCONVCONTEXT16 pCC16)
266 CONVCONTEXT* pCC = NULL;
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,
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)
306 CONVCONTEXT* pCC = NULL;
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,
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)
346 return DdeCreateStringHandleA(idInst, str, codepage);
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 return DdeClientTransaction(pData, cbData, hConv, hszItem,
387 wFmt, wType, dwTimeout, pdwResult);
390 /*****************************************************************
392 * DdeAbandonTransaction (DDEML.12)
395 BOOL16 WINAPI DdeAbandonTransaction16(DWORD idInst, HCONV hConv, DWORD idTransaction)
397 return (BOOL16)DdeAbandonTransaction(idInst, hConv, idTransaction);
400 /*****************************************************************
401 * DdePostAdvise [DDEML.13]
403 BOOL16 WINAPI DdePostAdvise16(DWORD idInst, HSZ hszTopic, HSZ hszItem)
405 return (BOOL16)DdePostAdvise(idInst, hszTopic, hszItem);
408 /*****************************************************************
409 * DdeAddData (DDEML.15)
411 HDDEDATA WINAPI DdeAddData16(HDDEDATA hData, LPBYTE pSrc, DWORD cb, DWORD cbOff)
413 return DdeAddData(hData, pSrc, cb, cbOff);
416 /*****************************************************************
417 * DdeGetData [DDEML.16]
419 DWORD WINAPI DdeGetData16(HDDEDATA hData, LPBYTE pDst, DWORD cbMax, DWORD cbOff)
421 return DdeGetData(hData, pDst, cbMax, cbOff);
424 /*****************************************************************
425 * DdeAccessData (DDEML.17)
427 LPBYTE WINAPI DdeAccessData16(HDDEDATA hData, LPDWORD pcbDataSize)
429 FIXME("expect trouble\n");
430 /* FIXME: there's a memory leak here... */
431 return (LPBYTE)MapLS(DdeAccessData(hData, pcbDataSize));
434 /*****************************************************************
435 * DdeUnaccessData (DDEML.18)
437 BOOL16 WINAPI DdeUnaccessData16(HDDEDATA hData)
439 return DdeUnaccessData(hData);
442 /*****************************************************************
443 * DdeEnableCallback (DDEML.26)
445 BOOL16 WINAPI DdeEnableCallback16(DWORD idInst, HCONV hConv, UINT16 wCmd)
447 return DdeEnableCallback(idInst, hConv, wCmd);
450 /*****************************************************************
451 * DdeNameService (DDEML.27)
453 HDDEDATA WINAPI DdeNameService16(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT16 afCmd)
455 return DdeNameService(idInst, hsz1, hsz2, afCmd);
458 /*****************************************************************
459 * DdeGetLastError (DDEML.20)
461 UINT16 WINAPI DdeGetLastError16(DWORD idInst)
463 return (UINT16)DdeGetLastError(idInst);
466 /*****************************************************************
467 * DdeCmpStringHandles (DDEML.36)
469 INT16 WINAPI DdeCmpStringHandles16(HSZ hsz1, HSZ hsz2)
471 return DdeCmpStringHandles(hsz1, hsz2);
474 /******************************************************************
475 * DdeQueryConvInfo (DDEML.9)
478 UINT16 WINAPI DdeQueryConvInfo16(HCONV hConv, DWORD idTransaction,
479 LPCONVINFO16 lpConvInfo)
485 ci32.cb = sizeof(ci32);
486 ci32.ConvCtxt.cb = sizeof(ci32.ConvCtxt);
488 ret = DdeQueryConvInfo(hConv, idTransaction, &ci32);
489 if (ret == 0) return 0;
491 ci16.hUser = ci32.hUser;
492 ci16.hConvPartner = ci32.hConvPartner;
493 ci16.hszSvcPartner = ci32.hszSvcPartner;
494 ci16.hszServiceReq = ci32.hszServiceReq;
495 ci16.hszTopic = ci32.hszTopic;
496 ci16.hszItem = ci32.hszItem;
497 ci16.wFmt = ci32.wFmt;
498 ci16.wType = ci32.wType;
499 ci16.wStatus = ci32.wStatus;
500 ci16.wConvst = ci32.wConvst;
501 ci16.wLastError = ci32.wLastError;
502 ci16.hConvList = ci32.hConvList;
504 map3216_conv_context(&ci16.ConvCtxt, &ci32.ConvCtxt);
506 memcpy(lpConvInfo, &ci16, lpConvInfo->cb);
507 return lpConvInfo->cb;