msi/tests: Move test coverage for standard actions to a separate module.
[wine.git] / dlls / ddeml.dll16 / ddeml.c
blobe0a9dda330dc431638813b390ac8db66bfd6bf00
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
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdarg.h>
29 #include <string.h>
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wine/windef16.h"
33 #include "wine/winbase16.h"
34 #include "wownt32.h"
35 #include "dde.h"
36 #include "ddeml.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddeml);
42 typedef HDDEDATA (CALLBACK *PFNCALLBACK16)(UINT16,UINT16,HCONV,HSZ,HSZ,HDDEDATA,
43 DWORD,DWORD);
45 typedef struct
47 UINT16 cb;
48 UINT16 wFlags;
49 UINT16 wCountryID;
50 INT16 iCodePage;
51 DWORD dwLangID;
52 DWORD dwSecurity;
53 } CONVCONTEXT16, *LPCONVCONTEXT16;
55 typedef struct
57 DWORD cb;
58 DWORD hUser;
59 HCONV hConvPartner;
60 HSZ hszSvcPartner;
61 HSZ hszServiceReq;
62 HSZ hszTopic;
63 HSZ hszItem;
64 UINT16 wFmt;
65 UINT16 wType;
66 UINT16 wStatus;
67 UINT16 wConvst;
68 UINT16 wLastError;
69 HCONVLIST hConvList;
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)
102 DWORD d1 = 0;
103 HDDEDATA ret;
104 CONVCONTEXT16 cc16;
105 WORD args[16];
107 switch (uType)
109 case XTYP_CONNECT:
110 case XTYP_WILDCONNECT:
111 if (dwData1)
113 map3216_conv_context(&cc16, (const CONVCONTEXT*)dwData1);
114 d1 = MapLS(&cc16);
116 else
117 break;
118 default:
119 d1 = dwData1;
120 break;
122 args[15] = HIWORD(uType);
123 args[14] = LOWORD(uType);
124 args[13] = HIWORD(uFmt);
125 args[12] = LOWORD(uFmt);
126 args[11] = HIWORD(hConv);
127 args[10] = LOWORD(hConv);
128 args[9] = HIWORD(hsz1);
129 args[8] = LOWORD(hsz1);
130 args[7] = HIWORD(hsz2);
131 args[6] = LOWORD(hsz2);
132 args[5] = HIWORD(hdata);
133 args[4] = LOWORD(hdata);
134 args[3] = HIWORD(d1);
135 args[2] = LOWORD(d1);
136 args[1] = HIWORD(dwData2);
137 args[0] = LOWORD(dwData2);
138 WOWCallback16Ex(pfn16, WCB16_PASCAL, sizeof(args), args, (DWORD *)&ret);
140 switch (uType)
142 case XTYP_CONNECT:
143 case XTYP_WILDCONNECT:
144 if (d1 != 0) UnMapLS(d1);
145 break;
147 return ret;
150 #define MAX_THUNKS 32
151 /* As DDEML doesn't provide a way to get back to an InstanceID when
152 * a callback is run, we use thunk in order to implement simply the
153 * 32bit->16bit callback mechanism.
154 * For each 16bit instance, we create a thunk, which will be passed as
155 * a 32bit callback. This thunk also stores (in the code!) the 16bit
156 * address of the 16bit callback, and passes it back to
157 * WDML_InvokeCallback16.
158 * The code below is mainly to create the thunks themselved
160 #include "pshpack1.h"
161 static struct ddeml_thunk
163 BYTE popl_eax; /* popl %eax (return address) */
164 BYTE pushl_func; /* pushl $pfn16 (16bit callback function) */
165 SEGPTR pfn16;
166 BYTE pushl_eax; /* pushl %eax */
167 BYTE jmp; /* ljmp WDML_InvokeCallback16 */
168 DWORD callback;
169 DWORD instId; /* instance ID */
170 } *DDEML16_Thunks;
171 #include "poppack.h"
173 static CRITICAL_SECTION ddeml_cs;
174 static CRITICAL_SECTION_DEBUG critsect_debug =
176 0, 0, &ddeml_cs,
177 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
178 0, 0, { (DWORD_PTR)(__FILE__ ": ddeml_cs") }
180 static CRITICAL_SECTION ddeml_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
182 static struct ddeml_thunk* DDEML_AddThunk(DWORD instId, DWORD pfn16)
184 struct ddeml_thunk* thunk;
186 if (!DDEML16_Thunks)
188 DDEML16_Thunks = VirtualAlloc(NULL, MAX_THUNKS * sizeof(*DDEML16_Thunks), MEM_COMMIT,
189 PAGE_EXECUTE_READWRITE);
190 if (!DDEML16_Thunks) return NULL;
191 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
193 thunk->popl_eax = 0x58; /* popl %eax */
194 thunk->pushl_func = 0x68; /* pushl $pfn16 */
195 thunk->pfn16 = 0;
196 thunk->pushl_eax = 0x50; /* pushl %eax */
197 thunk->jmp = 0xe9; /* jmp WDML_InvokeCallback16 */
198 thunk->callback = (char *)WDML_InvokeCallback16 - (char *)(&thunk->callback + 1);
199 thunk->instId = 0;
202 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
204 /* either instId is 0, and we're looking for an empty slot, or
205 * instId is an already existing instance, and we should find its thunk
207 if (thunk->instId == instId)
209 thunk->pfn16 = pfn16;
210 return thunk;
213 FIXME("Out of ddeml-thunks. Bump MAX_THUNKS\n");
214 return NULL;
217 /******************************************************************************
218 * DdeInitialize (DDEML.2)
220 UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
221 DWORD afCmd, DWORD ulRes)
223 UINT16 ret;
224 struct ddeml_thunk* thunk;
226 EnterCriticalSection(&ddeml_cs);
227 if ((thunk = DDEML_AddThunk(*pidInst, (DWORD)pfnCallback)))
229 ret = DdeInitializeA(pidInst, (PFNCALLBACK)thunk, afCmd, ulRes);
230 if (ret == DMLERR_NO_ERROR) thunk->instId = *pidInst;
232 else ret = DMLERR_SYS_ERROR;
233 LeaveCriticalSection(&ddeml_cs);
234 return ret;
237 /*****************************************************************
238 * DdeUninitialize (DDEML.3)
240 BOOL16 WINAPI DdeUninitialize16(DWORD idInst)
242 struct ddeml_thunk* thunk;
243 BOOL16 ret = FALSE;
245 if (!DdeUninitialize(idInst)) return FALSE;
246 EnterCriticalSection(&ddeml_cs);
247 for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
249 if (thunk->instId == idInst)
251 thunk->instId = 0;
252 ret = TRUE;
253 break;
256 LeaveCriticalSection(&ddeml_cs);
257 if (!ret) FIXME("Should never happen\n");
258 return ret;
261 /*****************************************************************
262 * DdeConnectList [DDEML.4]
265 HCONVLIST WINAPI DdeConnectList16(DWORD idInst, HSZ hszService, HSZ hszTopic,
266 HCONVLIST hConvList, LPCONVCONTEXT16 pCC16)
268 CONVCONTEXT cc;
269 CONVCONTEXT* pCC = NULL;
271 if (pCC16)
272 map1632_conv_context(pCC = &cc, pCC16);
273 return DdeConnectList(idInst, hszService, hszTopic, hConvList, pCC);
276 /*****************************************************************
277 * DdeQueryNextServer [DDEML.5]
279 HCONV WINAPI DdeQueryNextServer16(HCONVLIST hConvList, HCONV hConvPrev)
281 return DdeQueryNextServer(hConvList, hConvPrev);
284 /*****************************************************************
285 * DdeDisconnectList (DDEML.6)
287 BOOL16 WINAPI DdeDisconnectList16(HCONVLIST hConvList)
289 return (BOOL16)DdeDisconnectList(hConvList);
293 /*****************************************************************
294 * DdeQueryString (DDEML.23)
296 DWORD WINAPI DdeQueryString16(DWORD idInst, HSZ hsz, LPSTR lpsz, DWORD cchMax,
297 INT16 codepage)
299 return DdeQueryStringA(idInst, hsz, lpsz, cchMax, codepage);
302 /*****************************************************************
303 * DdeConnect (DDEML.7)
305 HCONV WINAPI DdeConnect16(DWORD idInst, HSZ hszService, HSZ hszTopic,
306 LPCONVCONTEXT16 pCC16)
308 CONVCONTEXT cc;
309 CONVCONTEXT* pCC = NULL;
311 if (pCC16)
312 map1632_conv_context(pCC = &cc, pCC16);
313 return DdeConnect(idInst, hszService, hszTopic, pCC);
316 /*****************************************************************
317 * DdeDisconnect (DDEML.8)
319 BOOL16 WINAPI DdeDisconnect16(HCONV hConv)
321 return (BOOL16)DdeDisconnect(hConv);
324 /*****************************************************************
325 * DdeSetUserHandle (DDEML.10)
327 BOOL16 WINAPI DdeSetUserHandle16(HCONV hConv, DWORD id, DWORD hUser)
329 return DdeSetUserHandle(hConv, id, hUser);
332 /*****************************************************************
333 * DdeCreateDataHandle (DDEML.14)
335 HDDEDATA WINAPI DdeCreateDataHandle16(DWORD idInst, LPBYTE pSrc, DWORD cb,
336 DWORD cbOff, HSZ hszItem, UINT16 wFmt,
337 UINT16 afCmd)
339 return DdeCreateDataHandle(idInst, pSrc, cb, cbOff, hszItem, wFmt, afCmd);
342 /*****************************************************************
343 * DdeCreateStringHandle (DDEML.21)
345 HSZ WINAPI DdeCreateStringHandle16(DWORD idInst, LPCSTR str, INT16 codepage)
347 if (codepage)
349 return DdeCreateStringHandleA(idInst, str, codepage);
351 else
353 TRACE("Default codepage supplied\n");
354 return DdeCreateStringHandleA(idInst, str, CP_WINANSI);
358 /*****************************************************************
359 * DdeFreeStringHandle (DDEML.22)
361 BOOL16 WINAPI DdeFreeStringHandle16(DWORD idInst, HSZ hsz)
363 return (BOOL16)DdeFreeStringHandle(idInst, hsz);
366 /*****************************************************************
367 * DdeFreeDataHandle (DDEML.19)
369 BOOL16 WINAPI DdeFreeDataHandle16(HDDEDATA hData)
371 return (BOOL16)DdeFreeDataHandle(hData);
374 /*****************************************************************
375 * DdeKeepStringHandle (DDEML.24)
377 BOOL16 WINAPI DdeKeepStringHandle16(DWORD idInst, HSZ hsz)
379 return DdeKeepStringHandle(idInst, hsz);
382 /*****************************************************************
383 * DdeClientTransaction (DDEML.11)
385 HDDEDATA WINAPI DdeClientTransaction16(LPVOID pData, DWORD cbData, HCONV hConv,
386 HSZ hszItem, UINT16 wFmt, UINT16 wType,
387 DWORD dwTimeout, LPDWORD pdwResult)
389 return DdeClientTransaction(pData, cbData, hConv, hszItem,
390 wFmt, wType, dwTimeout, pdwResult);
393 /*****************************************************************
395 * DdeAbandonTransaction (DDEML.12)
398 BOOL16 WINAPI DdeAbandonTransaction16(DWORD idInst, HCONV hConv, DWORD idTransaction)
400 return (BOOL16)DdeAbandonTransaction(idInst, hConv, idTransaction);
403 /*****************************************************************
404 * DdePostAdvise [DDEML.13]
406 BOOL16 WINAPI DdePostAdvise16(DWORD idInst, HSZ hszTopic, HSZ hszItem)
408 return (BOOL16)DdePostAdvise(idInst, hszTopic, hszItem);
411 /*****************************************************************
412 * DdeAddData (DDEML.15)
414 HDDEDATA WINAPI DdeAddData16(HDDEDATA hData, LPBYTE pSrc, DWORD cb, DWORD cbOff)
416 return DdeAddData(hData, pSrc, cb, cbOff);
419 /*****************************************************************
420 * DdeGetData [DDEML.16]
422 DWORD WINAPI DdeGetData16(HDDEDATA hData, LPBYTE pDst, DWORD cbMax, DWORD cbOff)
424 return DdeGetData(hData, pDst, cbMax, cbOff);
427 /*****************************************************************
428 * DdeAccessData (DDEML.17)
430 LPBYTE WINAPI DdeAccessData16(HDDEDATA hData, LPDWORD pcbDataSize)
432 FIXME("expect trouble\n");
433 /* FIXME: there's a memory leak here... */
434 return (LPBYTE)MapLS(DdeAccessData(hData, pcbDataSize));
437 /*****************************************************************
438 * DdeUnaccessData (DDEML.18)
440 BOOL16 WINAPI DdeUnaccessData16(HDDEDATA hData)
442 return DdeUnaccessData(hData);
445 /*****************************************************************
446 * DdeEnableCallback (DDEML.26)
448 BOOL16 WINAPI DdeEnableCallback16(DWORD idInst, HCONV hConv, UINT16 wCmd)
450 return DdeEnableCallback(idInst, hConv, wCmd);
453 /*****************************************************************
454 * DdeNameService (DDEML.27)
456 HDDEDATA WINAPI DdeNameService16(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT16 afCmd)
458 return DdeNameService(idInst, hsz1, hsz2, afCmd);
461 /*****************************************************************
462 * DdeGetLastError (DDEML.20)
464 UINT16 WINAPI DdeGetLastError16(DWORD idInst)
466 return (UINT16)DdeGetLastError(idInst);
469 /*****************************************************************
470 * DdeCmpStringHandles (DDEML.36)
472 INT16 WINAPI DdeCmpStringHandles16(HSZ hsz1, HSZ hsz2)
474 return DdeCmpStringHandles(hsz1, hsz2);
477 /******************************************************************
478 * DdeQueryConvInfo (DDEML.9)
481 UINT16 WINAPI DdeQueryConvInfo16(HCONV hConv, DWORD idTransaction,
482 LPCONVINFO16 lpConvInfo)
484 CONVINFO ci32;
485 CONVINFO16 ci16;
486 UINT ret;
488 ci32.cb = sizeof(ci32);
489 ci32.ConvCtxt.cb = sizeof(ci32.ConvCtxt);
491 ret = DdeQueryConvInfo(hConv, idTransaction, &ci32);
492 if (ret == 0) return 0;
494 ci16.hUser = ci32.hUser;
495 ci16.hConvPartner = ci32.hConvPartner;
496 ci16.hszSvcPartner = ci32.hszSvcPartner;
497 ci16.hszServiceReq = ci32.hszServiceReq;
498 ci16.hszTopic = ci32.hszTopic;
499 ci16.hszItem = ci32.hszItem;
500 ci16.wFmt = ci32.wFmt;
501 ci16.wType = ci32.wType;
502 ci16.wStatus = ci32.wStatus;
503 ci16.wConvst = ci32.wConvst;
504 ci16.wLastError = ci32.wLastError;
505 ci16.hConvList = ci32.hConvList;
507 map3216_conv_context(&ci16.ConvCtxt, &ci32.ConvCtxt);
509 memcpy(lpConvInfo, &ci16, lpConvInfo->cb);
510 return lpConvInfo->cb;