2 * PURPOSE: Load a DLL and run an entry point with the specified parameters
4 * Copyright 2002 Alberto Massari
5 * Copyright 2001-2003 Aric Stewart for CodeWeavers
6 * Copyright 2003 Mike McCormack for CodeWeavers
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.
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.
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
26 * rundll32 dllname,entrypoint [arguments]
28 * Documentation for this utility found on KB Q164787
36 /* Exclude rarely-used stuff from Windows headers */
37 #define WIN32_LEAN_AND_MEAN
39 #include "wine/winbase16.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(rundll32
);
47 /* wrapper for dlls that declare the entry point incorrectly */
48 extern void call_entry_point( void *func
, HWND hwnd
, HINSTANCE inst
, void *cmdline
, int show
);
49 __ASM_GLOBAL_FUNC( call_entry_point
,
51 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
52 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
54 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
56 __ASM_CFI(".cfi_rel_offset %edi,-4\n\t")
58 __ASM_CFI(".cfi_rel_offset %esi,-8\n\t")
60 __ASM_CFI(".cfi_rel_offset %ebx,-12\n\t")
67 "leal -12(%ebp),%esp\n\t"
69 __ASM_CFI(".cfi_same_value %ebx\n\t")
71 __ASM_CFI(".cfi_same_value %esi\n\t")
73 __ASM_CFI(".cfi_same_value %edi\n\t")
75 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
76 __ASM_CFI(".cfi_same_value %ebp\n\t")
79 static void call_entry_point( void *func
, HWND hwnd
, HINSTANCE inst
, void *cmdline
, int show
)
81 void (WINAPI
*entry_point
)( HWND hwnd
, HINSTANCE inst
, void *cmdline
, int show
) = func
;
82 entry_point( hwnd
, inst
, cmdline
, show
);
86 static HINSTANCE16 (WINAPI
*pLoadLibrary16
)(LPCSTR libname
);
87 static FARPROC16 (WINAPI
*pGetProcAddress16
)(HMODULE16 hModule
, LPCSTR name
);
88 static void (WINAPI
*pRunDLL_CallEntry16
)( FARPROC proc
, HWND hwnd
, HINSTANCE inst
,
89 LPCSTR cmdline
, INT cmdshow
);
92 * Control_RunDLL needs to have a window. So lets make us a very simple window class.
94 static ATOM
register_class(void)
98 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
100 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
101 wcex
.lpfnWndProc
= DefWindowProcW
;
104 wcex
.hInstance
= NULL
;
106 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_ARROW
);
107 wcex
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
108 wcex
.lpszMenuName
= NULL
;
109 wcex
.lpszClassName
= L
"class_rundll32";
112 return RegisterClassExW(&wcex
);
115 static HINSTANCE16
load_dll16( LPCWSTR dll
)
118 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, dll
, -1, NULL
, 0, NULL
, NULL
);
119 char *dllA
= HeapAlloc( GetProcessHeap(), 0, len
);
123 WideCharToMultiByte( CP_ACP
, 0, dll
, -1, dllA
, len
, NULL
, NULL
);
124 pLoadLibrary16
= (void *)GetProcAddress( GetModuleHandleW(L
"kernel32.dll"), (LPCSTR
)35 );
125 if (pLoadLibrary16
) ret
= pLoadLibrary16( dllA
);
126 HeapFree( GetProcessHeap(), 0, dllA
);
131 static FARPROC16
get_entry_point16( HINSTANCE16 inst
, LPCWSTR entry
)
134 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
135 char *entryA
= HeapAlloc( GetProcessHeap(), 0, len
);
139 WideCharToMultiByte( CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
140 pGetProcAddress16
= (void *)GetProcAddress( GetModuleHandleW(L
"kernel32.dll"), (LPCSTR
)37 );
141 if (pGetProcAddress16
) ret
= pGetProcAddress16( inst
, entryA
);
142 HeapFree( GetProcessHeap(), 0, entryA
);
147 static void *get_entry_point32( HMODULE module
, LPCWSTR entry
, BOOL
*unicode
)
151 /* determine if the entry point is an ordinal */
154 INT_PTR ordinal
= wcstol( entry
+ 1, NULL
, 10 );
159 ret
= GetProcAddress( module
, (LPCSTR
)ordinal
);
163 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
164 char *entryA
= HeapAlloc( GetProcessHeap(), 0, len
+ 1 );
169 WideCharToMultiByte( CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
171 /* first try the W version */
173 strcat( entryA
, "W" );
174 if (!(ret
= GetProcAddress( module
, entryA
)))
176 /* now the A version */
178 entryA
[strlen(entryA
)-1] = 'A';
179 if (!(ret
= GetProcAddress( module
, entryA
)))
181 /* now the version without suffix */
182 entryA
[strlen(entryA
)-1] = 0;
183 ret
= GetProcAddress( module
, entryA
);
186 HeapFree( GetProcessHeap(), 0, entryA
);
191 static LPWSTR
get_next_arg(LPWSTR
*cmdline
)
198 /* count the chars */
203 if (*s
==0 || ((*s
=='\t' || *s
==' ') && !in_quotes
)) {
204 /* end of this command line argument */
206 } else if (*s
=='\\') {
207 /* '\', count them */
209 } else if ((*s
=='"') && ((bcount
& 1)==0)) {
211 in_quotes
=!in_quotes
;
214 /* a regular character */
220 arg
=HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
229 if ((*s
=='\t' || *s
==' ') && !in_quotes
) {
230 /* end of this command line argument */
232 } else if (*s
=='\\') {
236 } else if (*s
=='"') {
238 if ((bcount
& 1)==0) {
239 /* Preceded by an even number of '\', this is half that
240 * number of '\', plus a quote which we erase.
243 in_quotes
=!in_quotes
;
246 /* Preceded by an odd number of '\', this is half that
247 * number of '\' followed by a '"'
255 /* a regular character */
263 /* skip the remaining spaces */
264 while (**cmdline
=='\t' || **cmdline
==' ') {
271 int WINAPI
wWinMain(HINSTANCE instance
, HINSTANCE hOldInstance
, LPWSTR szCmdLine
, int nCmdShow
)
274 LPWSTR szDllName
,szEntryPoint
;
276 BOOL unicode
= FALSE
, win16
;
284 /* Initialize the rundll32 class */
286 hWnd
= CreateWindowW(L
"class_rundll32", L
"rundll32", WS_OVERLAPPEDWINDOW
|WS_VISIBLE
,
287 CW_USEDEFAULT
, 0, CW_USEDEFAULT
, 0, NULL
, NULL
, NULL
, NULL
);
289 /* Get the dll name and API EntryPoint */
290 WINE_TRACE("CmdLine=%s\n",wine_dbgstr_w(szCmdLine
));
291 szDllName
= get_next_arg(&szCmdLine
);
292 if (!szDllName
|| *szDllName
==0)
294 WINE_TRACE("DllName=%s\n",wine_dbgstr_w(szDllName
));
295 if ((szEntryPoint
= wcschr(szDllName
, ',' )))
298 szEntryPoint
= get_next_arg(&szCmdLine
);
299 WINE_TRACE("EntryPoint=%s\n",wine_dbgstr_w(szEntryPoint
));
301 /* Load the library */
302 hDll
=LoadLibraryW(szDllName
);
306 entry_point
= get_entry_point32( hDll
, szEntryPoint
, &unicode
);
310 HINSTANCE16 dll
= load_dll16( szDllName
);
313 /* Windows has a MessageBox here... */
314 WINE_ERR("Unable to load %s\n",wine_dbgstr_w(szDllName
));
319 entry_point
= get_entry_point16( dll
, szEntryPoint
);
324 /* Windows has a MessageBox here... */
325 WINE_ERR( "Unable to find the entry point %s in %s\n",
326 wine_dbgstr_w(szEntryPoint
), wine_dbgstr_w(szDllName
) );
330 GetStartupInfoW( &info
);
331 if (!(info
.dwFlags
& STARTF_USESHOWWINDOW
)) info
.wShowWindow
= SW_SHOWDEFAULT
;
335 WINE_TRACE( "Calling %s (%p,%p,%s,%d)\n", wine_dbgstr_w(szEntryPoint
),
336 hWnd
, instance
, wine_dbgstr_w(szCmdLine
), info
.wShowWindow
);
338 call_entry_point( entry_point
, hWnd
, instance
, szCmdLine
, info
.wShowWindow
);
342 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, szCmdLine
, -1, NULL
, 0, NULL
, NULL
);
343 char *cmdline
= HeapAlloc( GetProcessHeap(), 0, len
);
348 WideCharToMultiByte( CP_ACP
, 0, szCmdLine
, -1, cmdline
, len
, NULL
, NULL
);
350 WINE_TRACE( "Calling %s (%p,%p,%s,%d)\n", wine_dbgstr_w(szEntryPoint
),
351 hWnd
, instance
, wine_dbgstr_a(cmdline
), info
.wShowWindow
);
355 HMODULE shell
= LoadLibraryW( L
"shell32.dll" );
356 if (shell
) pRunDLL_CallEntry16
= (void *)GetProcAddress( shell
, (LPCSTR
)122 );
357 if (pRunDLL_CallEntry16
)
358 pRunDLL_CallEntry16( entry_point
, hWnd
, instance
, cmdline
, info
.wShowWindow
);
360 else call_entry_point( entry_point
, hWnd
, instance
, cmdline
, info
.wShowWindow
);
362 HeapFree( GetProcessHeap(), 0, cmdline
);
370 HeapFree(GetProcessHeap(),0,szDllName
);
371 return 0; /* rundll32 always returns 0! */