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 TCHAR
*szTitle
= "rundll32";
57 static const TCHAR
*szWindowClass
= "class_rundll32";
59 static HINSTANCE16 (WINAPI
*pLoadLibrary16
)(LPCSTR libname
);
60 static FARPROC16 (WINAPI
*pGetProcAddress16
)(HMODULE16 hModule
, LPCSTR name
);
61 static void (WINAPI
*pRunDLL_CallEntry16
)( FARPROC proc
, HWND hwnd
, HINSTANCE inst
,
62 LPCSTR cmdline
, INT cmdshow
);
64 static ATOM
MyRegisterClass(HINSTANCE hInstance
)
68 wcex
.cbSize
= sizeof(WNDCLASSEX
);
70 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
71 wcex
.lpfnWndProc
= DefWindowProc
;
74 wcex
.hInstance
= hInstance
;
76 wcex
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
77 wcex
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
78 wcex
.lpszMenuName
= NULL
;
79 wcex
.lpszClassName
= szWindowClass
;
82 return RegisterClassEx(&wcex
);
85 static HINSTANCE16
load_dll16( LPCWSTR dll
)
88 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, dll
, -1, NULL
, 0, NULL
, NULL
);
89 char *dllA
= HeapAlloc( GetProcessHeap(), 0, len
);
90 WideCharToMultiByte( CP_ACP
, 0, dll
, -1, dllA
, len
, NULL
, NULL
);
91 pLoadLibrary16
= (void *)GetProcAddress( GetModuleHandleA("kernel32.dll"), (LPCSTR
)35 );
92 if (pLoadLibrary16
) ret
= pLoadLibrary16( dllA
);
93 HeapFree( GetProcessHeap(), 0, dllA
);
97 static FARPROC16
get_entry_point16( HINSTANCE16 inst
, LPCWSTR entry
)
100 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
101 char *entryA
= HeapAlloc( GetProcessHeap(), 0, len
);
102 WideCharToMultiByte( CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
103 pGetProcAddress16
= (void *)GetProcAddress( GetModuleHandleA("kernel32.dll"), (LPCSTR
)37 );
104 if (pGetProcAddress16
) ret
= pGetProcAddress16( inst
, entryA
);
105 HeapFree( GetProcessHeap(), 0, entryA
);
109 static void *get_entry_point32( HMODULE module
, LPCWSTR entry
, BOOL
*unicode
)
112 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
113 char *entryA
= HeapAlloc( GetProcessHeap(), 0, len
+ 1 );
114 WideCharToMultiByte( CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
116 /* first try the W version */
118 strcat( entryA
, "W" );
119 if (!(ret
= GetProcAddress( module
, entryA
)))
121 /* now the A version */
123 entryA
[strlen(entryA
)-1] = 'A';
124 if (!(ret
= GetProcAddress( module
, entryA
)))
126 /* now the version without suffix */
127 entryA
[strlen(entryA
)-1] = 0;
128 ret
= GetProcAddress( module
, entryA
);
131 HeapFree( GetProcessHeap(), 0, entryA
);
135 static LPWSTR
GetNextArg(LPWSTR
*cmdline
)
139 int in_quotes
,bcount
,len
=0;
141 /* count the chars */
146 if (*s
==0 || ((*s
=='\t' || *s
==' ') && !in_quotes
)) {
147 /* end of this command line argument */
149 } else if (*s
=='\\') {
150 /* '\', count them */
152 } else if ((*s
=='"') && ((bcount
& 1)==0)) {
154 in_quotes
=!in_quotes
;
157 /* a regular character */
163 arg
=HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
172 if ((*s
=='\t' || *s
==' ') && !in_quotes
) {
173 /* end of this command line argument */
175 } else if (*s
=='\\') {
179 } else if (*s
=='"') {
181 if ((bcount
& 1)==0) {
182 /* Preceded by an even number of '\', this is half that
183 * number of '\', plus a quote which we erase.
186 in_quotes
=!in_quotes
;
189 /* Preceded by an odd number of '\', this is half that
190 * number of '\' followed by a '"'
198 /* a regular character */
206 /* skip the remaining spaces */
207 while (**cmdline
=='\t' || **cmdline
==' ') {
214 int WINAPI
WinMain(HINSTANCE instance
, HINSTANCE hOldInstance
, LPSTR szCmdArgs
, int nCmdShow
)
218 LPWSTR szDllName
,szEntryPoint
;
228 /* Initialize the rundll32 class */
229 MyRegisterClass( NULL
);
230 hWnd
= CreateWindow(szWindowClass
, szTitle
,
231 WS_OVERLAPPEDWINDOW
|WS_VISIBLE
,
232 CW_USEDEFAULT
, 0, CW_USEDEFAULT
, 0, NULL
, NULL
, NULL
, NULL
);
234 /* Skip the rundll32.exe path */
235 szCmdLine
=GetCommandLineW();
236 WINE_TRACE("CmdLine=%s\n",wine_dbgstr_w(szCmdLine
));
237 szDllName
=GetNextArg(&szCmdLine
);
238 if (!szDllName
|| *szDllName
==0)
240 HeapFree(GetProcessHeap(),0,szDllName
);
242 /* Get the dll name and API EntryPoint */
243 szDllName
=GetNextArg(&szCmdLine
);
244 if (!szDllName
|| *szDllName
==0)
246 WINE_TRACE("DllName=%s\n",wine_dbgstr_w(szDllName
));
247 if ((szEntryPoint
= strchrW(szDllName
, ',' )))
250 szEntryPoint
= GetNextArg(&szCmdLine
);
251 WINE_TRACE("EntryPoint=%s\n",wine_dbgstr_w(szEntryPoint
));
253 /* Load the library */
254 hDll
=LoadLibraryW(szDllName
);
258 entry_point
= get_entry_point32( hDll
, szEntryPoint
, &unicode
);
262 HINSTANCE16 dll
= load_dll16( szDllName
);
265 /* Windows has a MessageBox here... */
266 WINE_ERR("Unable to load %s\n",wine_dbgstr_w(szDllName
));
271 entry_point
= get_entry_point16( dll
, szEntryPoint
);
276 /* Windows has a MessageBox here... */
277 WINE_ERR( "Unable to find the entry point %s in %s\n",
278 wine_dbgstr_w(szEntryPoint
), wine_dbgstr_w(szDllName
) );
282 GetStartupInfoW( &info
);
283 if (!(info
.dwFlags
& STARTF_USESHOWWINDOW
)) info
.wShowWindow
= SW_SHOWDEFAULT
;
287 EntryPointW pEntryPointW
= entry_point
;
289 WINE_TRACE( "Calling %s (%p,%p,%s,%d)\n", wine_dbgstr_w(szEntryPoint
),
290 hWnd
, instance
, wine_dbgstr_w(szCmdLine
), info
.wShowWindow
);
292 pEntryPointW( hWnd
, instance
, szCmdLine
, info
.wShowWindow
);
296 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, szCmdLine
, -1, NULL
, 0, NULL
, NULL
);
297 char *cmdline
= HeapAlloc( GetProcessHeap(), 0, len
);
298 WideCharToMultiByte( CP_ACP
, 0, szCmdLine
, -1, cmdline
, len
, NULL
, NULL
);
300 WINE_TRACE( "Calling %s (%p,%p,%s,%d)\n", wine_dbgstr_w(szEntryPoint
),
301 hWnd
, instance
, wine_dbgstr_a(cmdline
), info
.wShowWindow
);
305 HMODULE shell
= LoadLibraryA( "shell32.dll" );
306 if (shell
) pRunDLL_CallEntry16
= (void *)GetProcAddress( shell
, (LPCSTR
)122 );
307 if (pRunDLL_CallEntry16
)
308 pRunDLL_CallEntry16( entry_point
, hWnd
, instance
, cmdline
, info
.wShowWindow
);
312 EntryPointA pEntryPointA
= entry_point
;
313 pEntryPointA( hWnd
, instance
, cmdline
, info
.wShowWindow
);
315 HeapFree( GetProcessHeap(), 0, cmdline
);
323 HeapFree(GetProcessHeap(),0,szDllName
);
324 return 0; /* rundll32 always returns 0! */