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