mshtml: Correct test for another unknown dispID.
[wine] / dlls / ddeml.dll16 / ddeml.c
1 /*
2  * DDEML library
3  *
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
9  *
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.
14  *
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.
19  *
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
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27
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"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(ddeml);
40
41
42 typedef HDDEDATA (CALLBACK *PFNCALLBACK16)(UINT16,UINT16,HCONV,HSZ,HSZ,HDDEDATA,
43                                            DWORD,DWORD);
44
45 typedef struct
46 {
47     UINT16  cb;
48     UINT16  wFlags;
49     UINT16  wCountryID;
50     INT16   iCodePage;
51     DWORD   dwLangID;
52     DWORD   dwSecurity;
53 } CONVCONTEXT16, *LPCONVCONTEXT16;
54
55 typedef struct
56 {
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;
72
73 static void map1632_conv_context(CONVCONTEXT* cc32, const CONVCONTEXT16* cc16)
74 {
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;
81 }
82
83 static void map3216_conv_context(CONVCONTEXT16* cc16, const CONVCONTEXT* cc32)
84 {
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;
91 }
92
93 /******************************************************************
94  *              WDML_InvokeCallback16
95  *
96  *
97  */
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)
101 {
102     DWORD               d1 = 0;
103     HDDEDATA            ret;
104     CONVCONTEXT16       cc16;
105     WORD args[16];
106
107     switch (uType)
108     {
109     case XTYP_CONNECT:
110     case XTYP_WILDCONNECT:
111         if (dwData1)
112         {
113             map3216_conv_context(&cc16, (const CONVCONTEXT*)dwData1);
114             d1 = MapLS(&cc16);
115         }
116         else
117         break;
118     default:
119         d1 = dwData1;
120         break;
121     }
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);
139
140     switch (uType)
141     {
142     case XTYP_CONNECT:
143     case XTYP_WILDCONNECT:
144         if (d1 != 0) UnMapLS(d1);
145         break;
146     }
147     return ret;
148 }
149
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
159  */
160 #include "pshpack1.h"
161 static struct ddeml_thunk
162 {
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"
172
173 static CRITICAL_SECTION ddeml_cs;
174 static CRITICAL_SECTION_DEBUG critsect_debug =
175 {
176     0, 0, &ddeml_cs,
177     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
178       0, 0, { (DWORD_PTR)(__FILE__ ": ddeml_cs") }
179 };
180 static CRITICAL_SECTION ddeml_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
181
182 static struct ddeml_thunk*      DDEML_AddThunk(DWORD instId, DWORD pfn16)
183 {
184     struct ddeml_thunk* thunk;
185
186     if (!DDEML16_Thunks)
187     {
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++)
192         {
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;
200         }
201     }
202     for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
203     {
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
206          */
207         if (thunk->instId == instId)
208         {
209             thunk->pfn16 = pfn16;
210             return thunk;
211         }
212     }
213     FIXME("Out of ddeml-thunks. Bump MAX_THUNKS\n");
214     return NULL;
215 }
216
217 /******************************************************************************
218  *            DdeInitialize   (DDEML.2)
219  */
220 UINT16 WINAPI DdeInitialize16(LPDWORD pidInst, PFNCALLBACK16 pfnCallback,
221                               DWORD afCmd, DWORD ulRes)
222 {
223     UINT16 ret;
224     struct ddeml_thunk* thunk;
225
226     EnterCriticalSection(&ddeml_cs);
227     if ((thunk = DDEML_AddThunk(*pidInst, (DWORD)pfnCallback)))
228     {
229         ret = DdeInitializeA(pidInst, (PFNCALLBACK)thunk, afCmd, ulRes);
230         if (ret == DMLERR_NO_ERROR) thunk->instId = *pidInst;
231     }
232     else ret = DMLERR_SYS_ERROR;
233     LeaveCriticalSection(&ddeml_cs);
234     return ret;
235 }
236
237 /*****************************************************************
238  *            DdeUninitialize   (DDEML.3)
239  */
240 BOOL16 WINAPI DdeUninitialize16(DWORD idInst)
241 {
242     struct ddeml_thunk* thunk;
243     BOOL16              ret = FALSE;
244
245     if (!DdeUninitialize(idInst)) return FALSE;
246     EnterCriticalSection(&ddeml_cs);
247     for (thunk = DDEML16_Thunks; thunk < &DDEML16_Thunks[MAX_THUNKS]; thunk++)
248     {
249         if (thunk->instId == idInst)
250         {
251             thunk->instId = 0;
252             ret = TRUE;
253             break;
254         }
255     }
256     LeaveCriticalSection(&ddeml_cs);
257     if (!ret) FIXME("Should never happen\n");
258     return ret;
259 }
260
261 /*****************************************************************
262  * DdeConnectList [DDEML.4]
263  */
264
265 HCONVLIST WINAPI DdeConnectList16(DWORD idInst, HSZ hszService, HSZ hszTopic,
266                                   HCONVLIST hConvList, LPCONVCONTEXT16 pCC16)
267 {
268     CONVCONTEXT         cc;
269     CONVCONTEXT*        pCC = NULL;
270
271     if (pCC16)
272         map1632_conv_context(pCC = &cc, pCC16);
273     return DdeConnectList(idInst, hszService, hszTopic, hConvList, pCC);
274 }
275
276 /*****************************************************************
277  * DdeQueryNextServer [DDEML.5]
278  */
279 HCONV WINAPI DdeQueryNextServer16(HCONVLIST hConvList, HCONV hConvPrev)
280 {
281     return DdeQueryNextServer(hConvList, hConvPrev);
282 }
283
284 /*****************************************************************
285  *            DdeDisconnectList (DDEML.6)
286  */
287 BOOL16 WINAPI DdeDisconnectList16(HCONVLIST hConvList)
288 {
289     return (BOOL16)DdeDisconnectList(hConvList);
290 }
291
292
293 /*****************************************************************
294  *              DdeQueryString (DDEML.23)
295  */
296 DWORD WINAPI DdeQueryString16(DWORD idInst, HSZ hsz, LPSTR lpsz, DWORD cchMax,
297                               INT16 codepage)
298 {
299     return DdeQueryStringA(idInst, hsz, lpsz, cchMax, codepage);
300 }
301
302 /*****************************************************************
303  *            DdeConnect   (DDEML.7)
304  */
305 HCONV WINAPI DdeConnect16(DWORD idInst, HSZ hszService, HSZ hszTopic,
306                           LPCONVCONTEXT16 pCC16)
307 {
308     CONVCONTEXT         cc;
309     CONVCONTEXT*        pCC = NULL;
310
311     if (pCC16)
312         map1632_conv_context(pCC = &cc, pCC16);
313     return DdeConnect(idInst, hszService, hszTopic, pCC);
314 }
315
316 /*****************************************************************
317  *            DdeDisconnect   (DDEML.8)
318  */
319 BOOL16 WINAPI DdeDisconnect16(HCONV hConv)
320 {
321     return (BOOL16)DdeDisconnect(hConv);
322 }
323
324 /*****************************************************************
325  *            DdeSetUserHandle (DDEML.10)
326  */
327 BOOL16 WINAPI DdeSetUserHandle16(HCONV hConv, DWORD id, DWORD hUser)
328 {
329     return DdeSetUserHandle(hConv, id, hUser);
330 }
331
332 /*****************************************************************
333  *            DdeCreateDataHandle (DDEML.14)
334  */
335 HDDEDATA WINAPI DdeCreateDataHandle16(DWORD idInst, LPBYTE pSrc, DWORD cb,
336                                       DWORD cbOff, HSZ hszItem, UINT16 wFmt,
337                                       UINT16 afCmd)
338 {
339     return DdeCreateDataHandle(idInst, pSrc, cb, cbOff, hszItem, wFmt, afCmd);
340 }
341
342 /*****************************************************************
343  *            DdeCreateStringHandle   (DDEML.21)
344  */
345 HSZ WINAPI DdeCreateStringHandle16(DWORD idInst, LPCSTR str, INT16 codepage)
346 {
347     if  (codepage)
348     {
349         return DdeCreateStringHandleA(idInst, str, codepage);
350     }
351     else
352     {
353         TRACE("Default codepage supplied\n");
354         return DdeCreateStringHandleA(idInst, str, CP_WINANSI);
355     }
356 }
357
358 /*****************************************************************
359  *            DdeFreeStringHandle   (DDEML.22)
360  */
361 BOOL16 WINAPI DdeFreeStringHandle16(DWORD idInst, HSZ hsz)
362 {
363     return (BOOL16)DdeFreeStringHandle(idInst, hsz);
364 }
365
366 /*****************************************************************
367  *            DdeFreeDataHandle   (DDEML.19)
368  */
369 BOOL16 WINAPI DdeFreeDataHandle16(HDDEDATA hData)
370 {
371     return (BOOL16)DdeFreeDataHandle(hData);
372 }
373
374 /*****************************************************************
375  *            DdeKeepStringHandle   (DDEML.24)
376  */
377 BOOL16 WINAPI DdeKeepStringHandle16(DWORD idInst, HSZ hsz)
378 {
379     return DdeKeepStringHandle(idInst, hsz);
380 }
381
382 /*****************************************************************
383  *            DdeClientTransaction  (DDEML.11)
384  */
385 HDDEDATA WINAPI DdeClientTransaction16(LPVOID pData, DWORD cbData, HCONV hConv,
386                                        HSZ hszItem, UINT16 wFmt, UINT16 wType,
387                                        DWORD dwTimeout, LPDWORD pdwResult)
388 {
389     return DdeClientTransaction(pData, cbData, hConv, hszItem,
390                                 wFmt, wType, dwTimeout, pdwResult);
391 }
392
393 /*****************************************************************
394  *
395  *            DdeAbandonTransaction (DDEML.12)
396  *
397  */
398 BOOL16 WINAPI DdeAbandonTransaction16(DWORD idInst, HCONV hConv, DWORD idTransaction)
399 {
400     return (BOOL16)DdeAbandonTransaction(idInst, hConv, idTransaction);
401 }
402
403 /*****************************************************************
404  * DdePostAdvise [DDEML.13]
405  */
406 BOOL16 WINAPI DdePostAdvise16(DWORD idInst, HSZ hszTopic, HSZ hszItem)
407 {
408     return (BOOL16)DdePostAdvise(idInst, hszTopic, hszItem);
409 }
410
411 /*****************************************************************
412  *            DdeAddData (DDEML.15)
413  */
414 HDDEDATA WINAPI DdeAddData16(HDDEDATA hData, LPBYTE pSrc, DWORD cb, DWORD cbOff)
415 {
416     return DdeAddData(hData, pSrc, cb, cbOff);
417 }
418
419 /*****************************************************************
420  * DdeGetData [DDEML.16]
421  */
422 DWORD WINAPI DdeGetData16(HDDEDATA hData, LPBYTE pDst, DWORD cbMax, DWORD cbOff)
423 {
424     return DdeGetData(hData, pDst, cbMax, cbOff);
425 }
426
427 /*****************************************************************
428  *            DdeAccessData (DDEML.17)
429  */
430 LPBYTE WINAPI DdeAccessData16(HDDEDATA hData, LPDWORD pcbDataSize)
431 {
432     FIXME("expect trouble\n");
433     /* FIXME: there's a memory leak here... */
434     return (LPBYTE)MapLS(DdeAccessData(hData, pcbDataSize));
435 }
436
437 /*****************************************************************
438  *            DdeUnaccessData (DDEML.18)
439  */
440 BOOL16 WINAPI DdeUnaccessData16(HDDEDATA hData)
441 {
442     return DdeUnaccessData(hData);
443 }
444
445 /*****************************************************************
446  *            DdeEnableCallback (DDEML.26)
447  */
448 BOOL16 WINAPI DdeEnableCallback16(DWORD idInst, HCONV hConv, UINT16 wCmd)
449 {
450     return DdeEnableCallback(idInst, hConv, wCmd);
451 }
452
453 /*****************************************************************
454  *            DdeNameService  (DDEML.27)
455  */
456 HDDEDATA WINAPI DdeNameService16(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT16 afCmd)
457 {
458     return DdeNameService(idInst, hsz1, hsz2, afCmd);
459 }
460
461 /*****************************************************************
462  *            DdeGetLastError  (DDEML.20)
463  */
464 UINT16 WINAPI DdeGetLastError16(DWORD idInst)
465 {
466     return (UINT16)DdeGetLastError(idInst);
467 }
468
469 /*****************************************************************
470  *            DdeCmpStringHandles (DDEML.36)
471  */
472 INT16 WINAPI DdeCmpStringHandles16(HSZ hsz1, HSZ hsz2)
473 {
474     return DdeCmpStringHandles(hsz1, hsz2);
475 }
476
477 /******************************************************************
478  *              DdeQueryConvInfo (DDEML.9)
479  *
480  */
481 UINT16 WINAPI DdeQueryConvInfo16(HCONV hConv, DWORD idTransaction,
482                                  LPCONVINFO16 lpConvInfo)
483 {
484     CONVINFO    ci32;
485     CONVINFO16  ci16;
486     UINT        ret;
487
488     ci32.cb = sizeof(ci32);
489     ci32.ConvCtxt.cb = sizeof(ci32.ConvCtxt);
490
491     ret = DdeQueryConvInfo(hConv, idTransaction, &ci32);
492     if (ret == 0) return 0;
493
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;
506
507     map3216_conv_context(&ci16.ConvCtxt, &ci32.ConvCtxt);
508
509     memcpy(lpConvInfo, &ci16, lpConvInfo->cb);
510     return lpConvInfo->cb;
511 }