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"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(rundll32
);
47 * Control_RunDLL has these parameters
49 typedef void (WINAPI
*EntryPointW
)(HWND hWnd
, HINSTANCE hInst
, LPWSTR lpszCmdLine
, int nCmdShow
);
50 typedef void (WINAPI
*EntryPointA
)(HWND hWnd
, HINSTANCE hInst
, LPSTR lpszCmdLine
, int nCmdShow
);
53 * Control_RunDLL needs to have a window. So lets make us a very
54 * simple window class.
56 static const WCHAR szTitle
[] = {'r','u','n','d','l','l','3','2',0};
57 static const WCHAR szWindowClass
[] = {'c','l','a','s','s','_','r','u','n','d','l','l','3','2',0};
58 static const WCHAR kernel32
[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
59 static const WCHAR shell32
[] = {'s','h','e','l','l','3','2','.','d','l','l',0};
61 static HINSTANCE16 (WINAPI
*pLoadLibrary16
)(LPCSTR libname
);
62 static FARPROC16 (WINAPI
*pGetProcAddress16
)(HMODULE16 hModule
, LPCSTR name
);
63 static void (WINAPI
*pRunDLL_CallEntry16
)( FARPROC proc
, HWND hwnd
, HINSTANCE inst
,
64 LPCSTR cmdline
, INT cmdshow
);
66 static ATOM
register_class(void)
70 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
72 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
73 wcex
.lpfnWndProc
= DefWindowProcW
;
76 wcex
.hInstance
= NULL
;
78 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_ARROW
);
79 wcex
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
80 wcex
.lpszMenuName
= NULL
;
81 wcex
.lpszClassName
= szWindowClass
;
84 return RegisterClassExW(&wcex
);
87 static HINSTANCE16
load_dll16( LPCWSTR dll
)
90 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, dll
, -1, NULL
, 0, NULL
, NULL
);
91 char *dllA
= HeapAlloc( GetProcessHeap(), 0, len
);
95 WideCharToMultiByte( CP_ACP
, 0, dll
, -1, dllA
, len
, NULL
, NULL
);
96 pLoadLibrary16
= (void *)GetProcAddress( GetModuleHandleW(kernel32
), (LPCSTR
)35 );
97 if (pLoadLibrary16
) ret
= pLoadLibrary16( dllA
);
98 HeapFree( GetProcessHeap(), 0, dllA
);
103 static FARPROC16
get_entry_point16( HINSTANCE16 inst
, LPCWSTR entry
)
106 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
107 char *entryA
= HeapAlloc( GetProcessHeap(), 0, len
);
111 WideCharToMultiByte( CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
112 pGetProcAddress16
= (void *)GetProcAddress( GetModuleHandleW(kernel32
), (LPCSTR
)37 );
113 if (pGetProcAddress16
) ret
= pGetProcAddress16( inst
, entryA
);
114 HeapFree( GetProcessHeap(), 0, entryA
);
119 static void *get_entry_point32( HMODULE module
, LPCWSTR entry
, BOOL
*unicode
)
123 /* determine if the entry point is an ordinal */
126 INT_PTR ordinal
= atoiW( entry
+ 1 );
131 ret
= GetProcAddress( module
, (LPCSTR
)ordinal
);
135 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
136 char *entryA
= HeapAlloc( GetProcessHeap(), 0, len
+ 1 );
141 WideCharToMultiByte( CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
143 /* first try the W version */
145 strcat( entryA
, "W" );
146 if (!(ret
= GetProcAddress( module
, entryA
)))
148 /* now the A version */
150 entryA
[strlen(entryA
)-1] = 'A';
151 if (!(ret
= GetProcAddress( module
, entryA
)))
153 /* now the version without suffix */
154 entryA
[strlen(entryA
)-1] = 0;
155 ret
= GetProcAddress( module
, entryA
);
158 HeapFree( GetProcessHeap(), 0, entryA
);
163 static LPWSTR
get_next_arg(LPWSTR
*cmdline
)
167 int in_quotes
,bcount
,len
=0;
169 /* count the chars */
174 if (*s
==0 || ((*s
=='\t' || *s
==' ') && !in_quotes
)) {
175 /* end of this command line argument */
177 } else if (*s
=='\\') {
178 /* '\', count them */
180 } else if ((*s
=='"') && ((bcount
& 1)==0)) {
182 in_quotes
=!in_quotes
;
185 /* a regular character */
191 arg
=HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
200 if ((*s
=='\t' || *s
==' ') && !in_quotes
) {
201 /* end of this command line argument */
203 } else if (*s
=='\\') {
207 } else if (*s
=='"') {
209 if ((bcount
& 1)==0) {
210 /* Preceded by an even number of '\', this is half that
211 * number of '\', plus a quote which we erase.
214 in_quotes
=!in_quotes
;
217 /* Preceded by an odd number of '\', this is half that
218 * number of '\' followed by a '"'
226 /* a regular character */
234 /* skip the remaining spaces */
235 while (**cmdline
=='\t' || **cmdline
==' ') {
242 int WINAPI
wWinMain(HINSTANCE instance
, HINSTANCE hOldInstance
, LPWSTR szCmdLine
, int nCmdShow
)
245 LPWSTR szDllName
,szEntryPoint
;
247 BOOL unicode
= FALSE
, win16
;
255 /* Initialize the rundll32 class */
257 hWnd
= CreateWindowW(szWindowClass
, szTitle
,
258 WS_OVERLAPPEDWINDOW
|WS_VISIBLE
,
259 CW_USEDEFAULT
, 0, CW_USEDEFAULT
, 0, NULL
, NULL
, NULL
, NULL
);
261 /* Get the dll name and API EntryPoint */
262 WINE_TRACE("CmdLine=%s\n",wine_dbgstr_w(szCmdLine
));
263 szDllName
= get_next_arg(&szCmdLine
);
264 if (!szDllName
|| *szDllName
==0)
266 WINE_TRACE("DllName=%s\n",wine_dbgstr_w(szDllName
));
267 if ((szEntryPoint
= strchrW(szDllName
, ',' )))
270 szEntryPoint
= get_next_arg(&szCmdLine
);
271 WINE_TRACE("EntryPoint=%s\n",wine_dbgstr_w(szEntryPoint
));
273 /* Load the library */
274 hDll
=LoadLibraryW(szDllName
);
278 entry_point
= get_entry_point32( hDll
, szEntryPoint
, &unicode
);
282 HINSTANCE16 dll
= load_dll16( szDllName
);
285 /* Windows has a MessageBox here... */
286 WINE_ERR("Unable to load %s\n",wine_dbgstr_w(szDllName
));
291 entry_point
= get_entry_point16( dll
, szEntryPoint
);
296 /* Windows has a MessageBox here... */
297 WINE_ERR( "Unable to find the entry point %s in %s\n",
298 wine_dbgstr_w(szEntryPoint
), wine_dbgstr_w(szDllName
) );
302 GetStartupInfoW( &info
);
303 if (!(info
.dwFlags
& STARTF_USESHOWWINDOW
)) info
.wShowWindow
= SW_SHOWDEFAULT
;
307 EntryPointW pEntryPointW
= entry_point
;
309 WINE_TRACE( "Calling %s (%p,%p,%s,%d)\n", wine_dbgstr_w(szEntryPoint
),
310 hWnd
, instance
, wine_dbgstr_w(szCmdLine
), info
.wShowWindow
);
312 pEntryPointW( hWnd
, instance
, szCmdLine
, info
.wShowWindow
);
316 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, szCmdLine
, -1, NULL
, 0, NULL
, NULL
);
317 char *cmdline
= HeapAlloc( GetProcessHeap(), 0, len
);
322 WideCharToMultiByte( CP_ACP
, 0, szCmdLine
, -1, cmdline
, len
, NULL
, NULL
);
324 WINE_TRACE( "Calling %s (%p,%p,%s,%d)\n", wine_dbgstr_w(szEntryPoint
),
325 hWnd
, instance
, wine_dbgstr_a(cmdline
), info
.wShowWindow
);
329 HMODULE shell
= LoadLibraryW( shell32
);
330 if (shell
) pRunDLL_CallEntry16
= (void *)GetProcAddress( shell
, (LPCSTR
)122 );
331 if (pRunDLL_CallEntry16
)
332 pRunDLL_CallEntry16( entry_point
, hWnd
, instance
, cmdline
, info
.wShowWindow
);
336 EntryPointA pEntryPointA
= entry_point
;
337 pEntryPointA( hWnd
, instance
, cmdline
, info
.wShowWindow
);
339 HeapFree( GetProcessHeap(), 0, cmdline
);
347 HeapFree(GetProcessHeap(),0,szDllName
);
348 return 0; /* rundll32 always returns 0! */