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"
33 #include "wine/winbase16.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddeml
);
42 typedef HDDEDATA (CALLBACK
*PFNCALLBACK16
)(UINT16
,UINT16
,HCONV
,HSZ
,HSZ
,HDDEDATA
,
53 } CONVCONTEXT16
, *LPCONVCONTEXT16
;
70 CONVCONTEXT16 ConvCtxt
;
71 } CONVINFO16
, *LPCONVINFO16
;
73 static void map1632_conv_context(CONVCONTEXT
* cc32
, const CONVCONTEXT16
* cc16
)
75 cc32
->cb
= sizeof(*cc32
);
76 cc32
->wFlags
= cc16
->wFlags
;
77 cc32
->wCountryID
= cc16
->wCountryID
;
78 cc32
->iCodePage
= cc16
->iCodePage
;
79 cc32
->dwLangID
= cc16
->dwLangID
;
80 cc32
->dwSecurity
= cc16
->dwSecurity
;
83 static void map3216_conv_context(CONVCONTEXT16
* cc16
, const CONVCONTEXT
* cc32
)
85 cc16
->cb
= sizeof(*cc16
);
86 cc16
->wFlags
= cc32
->wFlags
;
87 cc16
->wCountryID
= cc32
->wCountryID
;
88 cc16
->iCodePage
= cc32
->iCodePage
;
89 cc16
->dwLangID
= cc32
->dwLangID
;
90 cc16
->dwSecurity
= cc32
->dwSecurity
;
93 /******************************************************************
94 * WDML_InvokeCallback16
98 static HDDEDATA CALLBACK
WDML_InvokeCallback16(DWORD pfn16
, UINT uType
, UINT uFmt
,
99 HCONV hConv
, HSZ hsz1
, HSZ hsz2
,
100 HDDEDATA hdata
, ULONG_PTR dwData1
, ULONG_PTR dwData2
)
110 case XTYP_WILDCONNECT
:
113 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 themselves
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 if (cbData
!= (DWORD
)-1)
390 /* pData is not a pointer if cbData is -1, so we linearize the address
391 * here rather than in the calling code. */
392 pData
= MapSL((SEGPTR
)pData
);
394 return DdeClientTransaction(pData
, cbData
, hConv
, hszItem
,
395 wFmt
, wType
, dwTimeout
, pdwResult
);
398 /*****************************************************************
400 * DdeAbandonTransaction (DDEML.12)
403 BOOL16 WINAPI
DdeAbandonTransaction16(DWORD idInst
, HCONV hConv
, DWORD idTransaction
)
405 return (BOOL16
)DdeAbandonTransaction(idInst
, hConv
, idTransaction
);
408 /*****************************************************************
409 * DdePostAdvise [DDEML.13]
411 BOOL16 WINAPI
DdePostAdvise16(DWORD idInst
, HSZ hszTopic
, HSZ hszItem
)
413 return (BOOL16
)DdePostAdvise(idInst
, hszTopic
, hszItem
);
416 /*****************************************************************
417 * DdeAddData (DDEML.15)
419 HDDEDATA WINAPI
DdeAddData16(HDDEDATA hData
, LPBYTE pSrc
, DWORD cb
, DWORD cbOff
)
421 return DdeAddData(hData
, pSrc
, cb
, cbOff
);
424 /*****************************************************************
425 * DdeGetData [DDEML.16]
427 DWORD WINAPI
DdeGetData16(HDDEDATA hData
, LPBYTE pDst
, DWORD cbMax
, DWORD cbOff
)
429 return DdeGetData(hData
, pDst
, cbMax
, cbOff
);
432 /*****************************************************************
433 * DdeAccessData (DDEML.17)
435 LPBYTE WINAPI
DdeAccessData16(HDDEDATA hData
, LPDWORD pcbDataSize
)
437 FIXME("expect trouble\n");
438 /* FIXME: there's a memory leak here... */
439 return (LPBYTE
)MapLS(DdeAccessData(hData
, pcbDataSize
));
442 /*****************************************************************
443 * DdeUnaccessData (DDEML.18)
445 BOOL16 WINAPI
DdeUnaccessData16(HDDEDATA hData
)
447 return DdeUnaccessData(hData
);
450 /*****************************************************************
451 * DdeEnableCallback (DDEML.26)
453 BOOL16 WINAPI
DdeEnableCallback16(DWORD idInst
, HCONV hConv
, UINT16 wCmd
)
455 return DdeEnableCallback(idInst
, hConv
, wCmd
);
458 /*****************************************************************
459 * DdeNameService (DDEML.27)
461 HDDEDATA WINAPI
DdeNameService16(DWORD idInst
, HSZ hsz1
, HSZ hsz2
, UINT16 afCmd
)
463 return DdeNameService(idInst
, hsz1
, hsz2
, afCmd
);
466 /*****************************************************************
467 * DdeGetLastError (DDEML.20)
469 UINT16 WINAPI
DdeGetLastError16(DWORD idInst
)
471 return (UINT16
)DdeGetLastError(idInst
);
474 /*****************************************************************
475 * DdeCmpStringHandles (DDEML.36)
477 INT16 WINAPI
DdeCmpStringHandles16(HSZ hsz1
, HSZ hsz2
)
479 return DdeCmpStringHandles(hsz1
, hsz2
);
482 /******************************************************************
483 * DdeQueryConvInfo (DDEML.9)
486 UINT16 WINAPI
DdeQueryConvInfo16(HCONV hConv
, DWORD idTransaction
,
487 LPCONVINFO16 lpConvInfo
)
493 ci32
.cb
= sizeof(ci32
);
494 ci32
.ConvCtxt
.cb
= sizeof(ci32
.ConvCtxt
);
496 ret
= DdeQueryConvInfo(hConv
, idTransaction
, &ci32
);
497 if (ret
== 0) return 0;
499 ci16
.cb
= lpConvInfo
->cb
;
500 ci16
.hUser
= ci32
.hUser
;
501 ci16
.hConvPartner
= ci32
.hConvPartner
;
502 ci16
.hszSvcPartner
= ci32
.hszSvcPartner
;
503 ci16
.hszServiceReq
= ci32
.hszServiceReq
;
504 ci16
.hszTopic
= ci32
.hszTopic
;
505 ci16
.hszItem
= ci32
.hszItem
;
506 ci16
.wFmt
= ci32
.wFmt
;
507 ci16
.wType
= ci32
.wType
;
508 ci16
.wStatus
= ci32
.wStatus
;
509 ci16
.wConvst
= ci32
.wConvst
;
510 ci16
.wLastError
= ci32
.wLastError
;
511 ci16
.hConvList
= ci32
.hConvList
;
513 map3216_conv_context(&ci16
.ConvCtxt
, &ci32
.ConvCtxt
);
515 memcpy(lpConvInfo
, &ci16
, lpConvInfo
->cb
);
516 return lpConvInfo
->cb
;