oleaut32/tests: COM cleanup for usrmarshal.c.
[wine] / dlls / shell.dll16 / shell.c
1 /*
2  *                              Shell Library Functions
3  *
4  * Copyright 1998 Marcus Meissner
5  * Copyright 2000 Juergen Schmied
6  * Copyright 2002 Eric Pouech
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32 #include <ctype.h>
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winreg.h"
37 #include "wownt32.h"
38 #include "shellapi.h"
39 #include "winuser.h"
40 #include "wingdi.h"
41 #include "shlobj.h"
42 #include "shlwapi.h"
43
44 #include "wine/winbase16.h"
45 #include "wine/winuser16.h"
46
47 #include "wine/debug.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(shell);
50
51 extern HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpOperation,LPCSTR lpFile,
52                                         LPCSTR lpParameters,LPCSTR lpDirectory,
53                                         INT iShowCmd, void *callback);
54
55 #define HINSTANCE_32(h16)       ((HINSTANCE)(ULONG_PTR)(h16))
56 #define HINSTANCE_16(h32)       (LOWORD(h32))
57
58 typedef struct {     /* structure for dropped files */
59  WORD     wSize;
60  POINT16  ptMousePos;
61  BOOL16   fInNonClientArea;
62  /* memory block with filenames follows */
63 } DROPFILESTRUCT16, *LPDROPFILESTRUCT16;
64
65 static const char lpstrMsgWndCreated[] = "OTHERWINDOWCREATED";
66 static const char lpstrMsgWndDestroyed[] = "OTHERWINDOWDESTROYED";
67 static const char lpstrMsgShellActivate[] = "ACTIVATESHELLWINDOW";
68
69 static HWND     SHELL_hWnd = 0;
70 static HHOOK    SHELL_hHook = 0;
71 static UINT     uMsgWndCreated = 0;
72 static UINT     uMsgWndDestroyed = 0;
73 static UINT     uMsgShellActivate = 0;
74
75 static HICON convert_icon_to_32( HICON16 icon16 )
76 {
77     CURSORICONINFO *info = GlobalLock16( icon16 );
78     void *and_bits = info + 1;
79     void *xor_bits = (BYTE *)and_bits + info->nHeight * 2 * ((info->nWidth + 15) / 16);
80     HICON ret = CreateIcon( 0, info->nWidth, info->nHeight, info->bPlanes, info->bBitsPerPixel,
81                             and_bits, xor_bits );
82     GlobalUnlock16( icon16 );
83     return ret;
84 }
85
86 static HICON16 convert_icon_to_16( HINSTANCE16 inst, HICON icon )
87 {
88     static HICON16 (WINAPI *pCreateIcon16)(HINSTANCE16,INT16,INT16,BYTE,BYTE,LPCVOID,LPCVOID);
89     ICONINFO info;
90     BITMAP bm;
91     UINT and_size, xor_size;
92     void *xor_bits = NULL, *and_bits;
93     HICON16 handle = 0;
94
95     if (!pCreateIcon16 &&
96         !(pCreateIcon16 = (void *)GetProcAddress( GetModuleHandleA("user.exe16"), "CreateIcon16" )))
97         return 0;
98
99     if (!(GetIconInfo( icon, &info ))) return 0;
100     GetObjectW( info.hbmMask, sizeof(bm), &bm );
101     and_size = bm.bmHeight * bm.bmWidthBytes;
102     if (!(and_bits = HeapAlloc( GetProcessHeap(), 0, and_size ))) goto done;
103     GetBitmapBits( info.hbmMask, and_size, and_bits );
104     if (info.hbmColor)
105     {
106         GetObjectW( info.hbmColor, sizeof(bm), &bm );
107         xor_size = bm.bmHeight * bm.bmWidthBytes;
108         if (!(xor_bits = HeapAlloc( GetProcessHeap(), 0, xor_size ))) goto done;
109         GetBitmapBits( info.hbmColor, xor_size, xor_bits );
110     }
111     else
112     {
113         bm.bmHeight /= 2;
114         xor_bits = (char *)and_bits + and_size / 2;
115     }
116     handle = pCreateIcon16( inst, bm.bmWidth, bm.bmHeight, bm.bmPlanes, bm.bmBitsPixel,
117                             and_bits, xor_bits );
118 done:
119     HeapFree( GetProcessHeap(), 0, and_bits );
120     if (info.hbmColor)
121     {
122         HeapFree( GetProcessHeap(), 0, xor_bits );
123         DeleteObject( info.hbmColor );
124     }
125     DeleteObject( info.hbmMask );
126     DestroyIcon( icon );
127     return handle;
128 }
129
130 /***********************************************************************
131  * DllEntryPoint [SHELL.101]
132  *
133  * Initialization code for shell.dll. Automatically loads the
134  * 32-bit shell32.dll to allow thunking up to 32-bit code.
135  *
136  * RETURNS
137  *  Success: TRUE. Initialization completed successfully.
138  *  Failure: FALSE.
139  */
140 BOOL WINAPI SHELL_DllEntryPoint(DWORD Reason, HINSTANCE16 hInst,
141                                 WORD ds, WORD HeapSize, DWORD res1, WORD res2)
142 {
143     return TRUE;
144 }
145
146 /*************************************************************************
147  *                              DragAcceptFiles         [SHELL.9]
148  */
149 void WINAPI DragAcceptFiles16(HWND16 hWnd, BOOL16 b)
150 {
151   DragAcceptFiles(HWND_32(hWnd), b);
152 }
153
154 /*************************************************************************
155  *                              DragQueryFile           [SHELL.11]
156  */
157 UINT16 WINAPI DragQueryFile16(
158         HDROP16 hDrop,
159         WORD wFile,
160         LPSTR lpszFile,
161         WORD wLength)
162 {
163         LPSTR lpDrop;
164         UINT i = 0;
165         LPDROPFILESTRUCT16 lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop);
166
167         TRACE("(%04x, %x, %p, %u)\n", hDrop,wFile,lpszFile,wLength);
168
169         if(!lpDropFileStruct) goto end;
170
171         lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
172
173         while (i++ < wFile)
174         {
175           while (*lpDrop++); /* skip filename */
176           if (!*lpDrop)
177           {
178             i = (wFile == 0xFFFF) ? i : 0;
179             goto end;
180           }
181         }
182
183         i = strlen(lpDrop);
184         if (!lpszFile ) goto end;   /* needed buffer size */
185         lstrcpynA (lpszFile, lpDrop, wLength);
186 end:
187         GlobalUnlock16(hDrop);
188         return i;
189 }
190
191 /*************************************************************************
192  *                              DragFinish              [SHELL.12]
193  */
194 void WINAPI DragFinish16(HDROP16 h)
195 {
196     TRACE("\n");
197     GlobalFree16(h);
198 }
199
200
201 /*************************************************************************
202  *                              DragQueryPoint          [SHELL.13]
203  */
204 BOOL16 WINAPI DragQueryPoint16(HDROP16 hDrop, POINT16 *p)
205 {
206   LPDROPFILESTRUCT16 lpDropFileStruct;
207   BOOL16           bRet;
208   TRACE("\n");
209   lpDropFileStruct = (LPDROPFILESTRUCT16) GlobalLock16(hDrop);
210
211   memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
212   bRet = lpDropFileStruct->fInNonClientArea;
213
214   GlobalUnlock16(hDrop);
215   return bRet;
216 }
217
218 /*************************************************************************
219  *             FindExecutable   (SHELL.21)
220  */
221 HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory,
222                                      LPSTR lpResult )
223 { return HINSTANCE_16(FindExecutableA( lpFile, lpDirectory, lpResult ));
224 }
225
226 /*************************************************************************
227  *             AboutDlgProc   (SHELL.33)
228  */
229 BOOL16 WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam,
230                                LPARAM lParam )
231 {
232     FIXME( "stub\n" );
233     return FALSE;
234 }
235
236
237 /*************************************************************************
238  *             ShellAbout   (SHELL.22)
239  */
240 BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON16 icon16 )
241 {
242     HICON icon = convert_icon_to_32( icon16 );
243     BOOL ret = ShellAboutA( HWND_32(hWnd), szApp, szOtherStuff, icon );
244     DestroyIcon( icon );
245     return ret;
246 }
247
248 /*************************************************************************
249  *                      InternalExtractIcon             [SHELL.39]
250  *
251  * This abortion is called directly by Progman
252  */
253 HGLOBAL16 WINAPI InternalExtractIcon16(HINSTANCE16 hInstance,
254                                      LPCSTR lpszExeFileName, UINT16 nIconIndex, WORD n )
255 {
256     HGLOBAL16 hRet = 0;
257     HICON16 *RetPtr = NULL;
258
259         TRACE("(%04x,file %s,start %d,extract %d\n",
260                        hInstance, lpszExeFileName, nIconIndex, n);
261
262         if (!n)
263           return 0;
264
265         hRet = GlobalAlloc16(GMEM_FIXED | GMEM_ZEROINIT, sizeof(*RetPtr) * n);
266         RetPtr = GlobalLock16(hRet);
267
268         if (nIconIndex == (UINT16)-1)  /* get number of icons */
269         {
270           RetPtr[0] = PrivateExtractIconsA(lpszExeFileName, 0, 0, 0, NULL, NULL, 0, LR_DEFAULTCOLOR);
271         }
272         else
273         {
274           UINT ret;
275           HICON *icons;
276
277           icons = HeapAlloc(GetProcessHeap(), 0, n * sizeof(*icons));
278           ret = PrivateExtractIconsA(lpszExeFileName, nIconIndex,
279                                      GetSystemMetrics(SM_CXICON),
280                                      GetSystemMetrics(SM_CYICON),
281                                      icons, NULL, n, LR_DEFAULTCOLOR);
282           if ((ret != 0xffffffff) && ret)
283           {
284             int i;
285             for (i = 0; i < n; i++) RetPtr[i] = convert_icon_to_16(hInstance, icons[i]);
286           }
287           else
288           {
289             GlobalFree16(hRet);
290             hRet = 0;
291           }
292           HeapFree(GetProcessHeap(), 0, icons);
293         }
294         return hRet;
295 }
296
297 /*************************************************************************
298  *             ExtractIcon   (SHELL.34)
299  */
300 HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
301         UINT16 nIconIndex )
302 {   TRACE("\n");
303     return convert_icon_to_16( hInstance, ExtractIconA(NULL, lpszExeFileName, nIconIndex) );
304 }
305
306 /*************************************************************************
307  *             ExtractIconEx   (SHELL.40)
308  */
309 UINT16 WINAPI ExtractIconEx16(
310         LPCSTR lpszFile, INT16 nIconIndex, HICON16 *phiconLarge,
311         HICON16 *phiconSmall, UINT16 nIcons
312 ) {
313     HICON       *ilarge,*ismall;
314     int         i, ret;
315
316     if (phiconLarge)
317         ilarge = HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON));
318     else
319         ilarge = NULL;
320     if (phiconSmall)
321         ismall = HeapAlloc(GetProcessHeap(),0,nIcons*sizeof(HICON));
322     else
323         ismall = NULL;
324     ret = ExtractIconExA(lpszFile,nIconIndex,ilarge,ismall,nIcons);
325     if (ilarge) {
326         for (i=0;i<ret;i++)
327             phiconLarge[i] = convert_icon_to_16(0, ilarge[i]);
328         HeapFree(GetProcessHeap(),0,ilarge);
329     }
330     if (ismall) {
331         for (i=0;i<ret;i++)
332             phiconSmall[i] = convert_icon_to_16(0, ismall[i]);
333         HeapFree(GetProcessHeap(),0,ismall);
334     }
335     return ret;
336 }
337
338 /*************************************************************************
339  *                              ExtractAssociatedIcon   [SHELL.36]
340  *
341  * Return icon for given file (either from file itself or from associated
342  * executable) and patch parameters if needed.
343  */
344 HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst, LPSTR lpIconPath, LPWORD lpiIcon)
345 {
346     return convert_icon_to_16( hInst, ExtractAssociatedIconA(NULL, lpIconPath, lpiIcon) );
347 }
348
349 /*************************************************************************
350  *                              FindEnvironmentString   [SHELL.38]
351  *
352  * Returns a pointer into the DOS environment... Ugh.
353  */
354 static LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
355 { UINT16 l;
356
357   TRACE("\n");
358
359   l = strlen(entry);
360   for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
361   { if( strncasecmp(lpEnv, entry, l) )
362       continue;
363         if( !*(lpEnv+l) )
364             return (lpEnv + l);                 /* empty entry */
365         else if ( *(lpEnv+l)== '=' )
366             return (lpEnv + l + 1);
367     }
368     return NULL;
369 }
370
371 /**********************************************************************/
372
373 SEGPTR WINAPI FindEnvironmentString16(LPCSTR str)
374 { SEGPTR  spEnv;
375   LPSTR lpEnv,lpString;
376   TRACE("\n");
377
378   spEnv = GetDOSEnvironment16();
379
380   lpEnv = MapSL(spEnv);
381   lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
382
383     if( lpString )              /*  offset should be small enough */
384         return spEnv + (lpString - lpEnv);
385     return 0;
386 }
387
388 /*************************************************************************
389  *                              DoEnvironmentSubst      [SHELL.37]
390  *
391  * Replace %KEYWORD% in the str with the value of variable KEYWORD
392  * from "DOS" environment. If it is not found the %KEYWORD% is left
393  * intact. If the buffer is too small, str is not modified.
394  *
395  * PARAMS
396  *  str        [I] '\0' terminated string with %keyword%.
397  *             [O] '\0' terminated string with %keyword% substituted.
398  *  length     [I] size of str.
399  *
400  * RETURNS
401  *  str length in the LOWORD and 1 in HIWORD if subst was successful.
402  */
403 DWORD WINAPI DoEnvironmentSubst16(LPSTR str,WORD length)
404 {
405   LPSTR   lpEnv = MapSL(GetDOSEnvironment16());
406   LPSTR   lpstr = str;
407   LPSTR   lpend;
408   LPSTR   lpBuffer = HeapAlloc( GetProcessHeap(), 0, length);
409   WORD    bufCnt = 0;
410   WORD    envKeyLen;
411   LPSTR   lpKey;
412   WORD    retStatus = 0;
413   WORD    retLength = length;
414
415   CharToOemA(str,str);
416
417   TRACE("accept %s\n", str);
418
419   while( *lpstr && bufCnt <= length - 1 ) {
420      if ( *lpstr != '%' ) {
421         lpBuffer[bufCnt++] = *lpstr++;
422         continue;
423      }
424
425      for( lpend = lpstr + 1; *lpend && *lpend != '%'; lpend++) /**/;
426
427      envKeyLen = lpend - lpstr - 1;
428      if( *lpend != '%' || envKeyLen == 0)
429         goto err; /* "%\0" or "%%" found; back off and whine */
430
431      *lpend = '\0';
432      lpKey = SHELL_FindString(lpEnv, lpstr+1);
433      *lpend = '%';
434      if( lpKey ) {
435          int l = strlen(lpKey);
436
437          if( bufCnt + l > length - 1 )
438                 goto err;
439
440         memcpy(lpBuffer + bufCnt, lpKey, l);
441         bufCnt += l;
442      } else { /* Keyword not found; Leave the %KEYWORD% intact */
443         if( bufCnt + envKeyLen + 2 > length - 1 )
444             goto err;
445
446          memcpy(lpBuffer + bufCnt, lpstr, envKeyLen + 2);
447         bufCnt += envKeyLen + 2;
448      }
449
450      lpstr = lpend + 1;
451   }
452
453   if (!*lpstr && bufCnt <= length - 1) {
454       memcpy(str,lpBuffer, bufCnt);
455       str[bufCnt] = '\0';
456       retLength = bufCnt + 1;
457       retStatus = 1;
458   }
459
460   err:
461   if (!retStatus)
462       WARN("-- Env subst aborted - string too short or invalid input\n");
463   TRACE("-- return %s\n", str);
464
465   OemToCharA(str,str);
466   HeapFree( GetProcessHeap(), 0, lpBuffer);
467
468   return (DWORD)MAKELONG(retLength, retStatus);
469 }
470
471 /*************************************************************************
472  *                              SHELL_HookProc
473  *
474  * 32-bit version of the system-wide WH_SHELL hook.
475  */
476 static LRESULT WINAPI SHELL_HookProc(INT code, WPARAM wParam, LPARAM lParam)
477 {
478     TRACE("%i, %lx, %08lx\n", code, wParam, lParam );
479
480     if (SHELL_hWnd)
481     {
482         switch( code )
483         {
484         case HSHELL_WINDOWCREATED:
485             PostMessageA( SHELL_hWnd, uMsgWndCreated, wParam, 0 );
486             break;
487         case HSHELL_WINDOWDESTROYED:
488             PostMessageA( SHELL_hWnd, uMsgWndDestroyed, wParam, 0 );
489             break;
490         case HSHELL_ACTIVATESHELLWINDOW:
491             PostMessageA( SHELL_hWnd, uMsgShellActivate, wParam, 0 );
492             break;
493         }
494     }
495     return CallNextHookEx( SHELL_hHook, code, wParam, lParam );
496 }
497
498 /*************************************************************************
499  *                              ShellHookProc           [SHELL.103]
500  * System-wide WH_SHELL hook.
501  */
502 LRESULT WINAPI ShellHookProc16(INT16 code, WPARAM16 wParam, LPARAM lParam)
503 {
504     return SHELL_HookProc( code, wParam, lParam );
505 }
506
507 /*************************************************************************
508  *                              RegisterShellHook       [SHELL.102]
509  */
510 BOOL WINAPI RegisterShellHook16(HWND16 hWnd, UINT16 uAction)
511 {
512     TRACE("%04x [%u]\n", hWnd, uAction );
513
514     switch( uAction )
515     {
516     case 2:  /* register hWnd as a shell window */
517         if( !SHELL_hHook )
518         {
519             SHELL_hHook = SetWindowsHookExA( WH_SHELL, SHELL_HookProc,
520                                              GetModuleHandleA("shell32.dll"), 0 );
521             if ( SHELL_hHook )
522             {
523                 uMsgWndCreated = RegisterWindowMessageA( lpstrMsgWndCreated );
524                 uMsgWndDestroyed = RegisterWindowMessageA( lpstrMsgWndDestroyed );
525                 uMsgShellActivate = RegisterWindowMessageA( lpstrMsgShellActivate );
526             }
527             else
528                 WARN("-- unable to install ShellHookProc()!\n");
529         }
530
531         if ( SHELL_hHook )
532             return ((SHELL_hWnd = HWND_32(hWnd)) != 0);
533         break;
534
535     default:
536         WARN("-- unknown code %i\n", uAction );
537         SHELL_hWnd = 0; /* just in case */
538     }
539     return FALSE;
540 }
541
542
543 /***********************************************************************
544  *           DriveType   (SHELL.262)
545  */
546 UINT16 WINAPI DriveType16( UINT16 drive )
547 {
548     UINT ret;
549     char path[] = "A:\\";
550     path[0] += drive;
551     ret = GetDriveTypeA(path);
552     switch(ret)  /* some values are not supported in Win16 */
553     {
554     case DRIVE_CDROM:
555         ret = DRIVE_REMOTE;
556         break;
557     case DRIVE_NO_ROOT_DIR:
558         ret = DRIVE_UNKNOWN;
559         break;
560     }
561     return ret;
562 }
563
564
565 /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
566  * some programs. Do not remove those cases. -MM
567  */
568 static inline void fix_win16_hkey( HKEY *hkey )
569 {
570     if (*hkey == 0 || *hkey == (HKEY)1) *hkey = HKEY_CLASSES_ROOT;
571 }
572
573 /******************************************************************************
574  *           RegOpenKey   [SHELL.1]
575  */
576 DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR name, PHKEY retkey )
577 {
578     fix_win16_hkey( &hkey );
579     return RegOpenKeyA( hkey, name, retkey );
580 }
581
582 /******************************************************************************
583  *           RegCreateKey   [SHELL.2]
584  */
585 DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR name, PHKEY retkey )
586 {
587     fix_win16_hkey( &hkey );
588     return RegCreateKeyA( hkey, name, retkey );
589 }
590
591 /******************************************************************************
592  *           RegCloseKey   [SHELL.3]
593  */
594 DWORD WINAPI RegCloseKey16( HKEY hkey )
595 {
596     fix_win16_hkey( &hkey );
597     return RegCloseKey( hkey );
598 }
599
600 /******************************************************************************
601  *           RegDeleteKey   [SHELL.4]
602  */
603 DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR name )
604 {
605     fix_win16_hkey( &hkey );
606     return RegDeleteKeyA( hkey, name );
607 }
608
609 /******************************************************************************
610  *           RegSetValue   [SHELL.5]
611  */
612 DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
613 {
614     fix_win16_hkey( &hkey );
615     return RegSetValueA( hkey, name, type, data, count );
616 }
617
618 /******************************************************************************
619  *           RegQueryValue   [SHELL.6]
620  *
621  * NOTES
622  *    Is this HACK still applicable?
623  *
624  * HACK
625  *    The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
626  *    mask out the high 16 bit.  This (not so much incidentally) hopefully fixes
627  *    Aldus FH4)
628  */
629 DWORD WINAPI RegQueryValue16( HKEY hkey, LPCSTR name, LPSTR data, LPDWORD count
630 )
631 {
632     fix_win16_hkey( &hkey );
633     if (count) *count &= 0xffff;
634     return RegQueryValueA( hkey, name, data, (LONG*) count );
635 }
636
637 /******************************************************************************
638  *           RegEnumKey   [SHELL.7]
639  */
640 DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
641 {
642     fix_win16_hkey( &hkey );
643     return RegEnumKeyA( hkey, index, name, name_len );
644 }
645
646 /*************************************************************************
647  *           SHELL_Execute16 [Internal]
648  */
649 static UINT_PTR SHELL_Execute16(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
650                             const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
651 {
652     UINT ret;
653     char sCmd[MAX_PATH];
654     WideCharToMultiByte(CP_ACP, 0, lpCmd, -1, sCmd, MAX_PATH, NULL, NULL);
655     ret = WinExec16(sCmd, (UINT16)psei->nShow);
656     psei_out->hInstApp = HINSTANCE_32(ret);
657     return ret;
658 }
659
660 /*************************************************************************
661  *                              ShellExecute            [SHELL.20]
662  */
663 HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
664                                    LPCSTR lpFile, LPCSTR lpParameters,
665                                    LPCSTR lpDirectory, INT16 iShowCmd )
666 {
667     return HINSTANCE_16( WOWShellExecute( HWND_32(hWnd), lpOperation, lpFile, lpParameters,
668                                           lpDirectory, iShowCmd, SHELL_Execute16 ));
669 }
670
671
672 /*************************************************************************
673  * RunDLL_CallEntry16
674  *
675  * Only exported from shell32 on Windows, probably imported
676  * from shell through the 16/32 thunks.
677  */
678 void WINAPI RunDLL_CallEntry16( DWORD proc, HWND hwnd, HINSTANCE inst, LPCSTR cmdline, INT cmdshow )
679 {
680     WORD args[5];
681     SEGPTR cmdline_seg;
682
683     TRACE( "proc %x hwnd %p inst %p cmdline %s cmdshow %d\n",
684            proc, hwnd, inst, debugstr_a(cmdline), cmdshow );
685
686     cmdline_seg = MapLS( cmdline );
687     args[4] = HWND_16(hwnd);
688     args[3] = MapHModuleLS(inst);
689     args[2] = SELECTOROF(cmdline_seg);
690     args[1] = OFFSETOF(cmdline_seg);
691     args[0] = cmdshow;
692     WOWCallback16Ex( proc, WCB16_PASCAL, sizeof(args), args, NULL );
693     UnMapLS( cmdline_seg );
694 }