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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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/debug.h>
41 WINE_DEFAULT_DEBUG_CHANNEL(rundll32
);
45 * Control_RunDLL has these parameters
47 typedef void (WINAPI
*EntryPointW
)(HWND hWnd
, HINSTANCE hInst
, LPWSTR lpszCmdLine
, int nCmdShow
);
48 typedef void (WINAPI
*EntryPointA
)(HWND hWnd
, HINSTANCE hInst
, LPSTR lpszCmdLine
, int nCmdShow
);
51 * Control_RunDLL needs to have a window. So lets make us a very
52 * simple window class.
54 static TCHAR
*szTitle
= "rundll32";
55 static TCHAR
*szWindowClass
= "class_rundll32";
57 static ATOM
MyRegisterClass(HINSTANCE hInstance
)
61 wcex
.cbSize
= sizeof(WNDCLASSEX
);
63 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
64 wcex
.lpfnWndProc
= (WNDPROC
)DefWindowProc
;
67 wcex
.hInstance
= hInstance
;
69 wcex
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
70 wcex
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+1);
71 wcex
.lpszMenuName
= NULL
;
72 wcex
.lpszClassName
= szWindowClass
;
75 return RegisterClassEx(&wcex
);
78 static LPWSTR
GetNextArg(LPCWSTR
*cmdline
)
82 int in_quotes
,bcount
,len
=0;
89 if (*s
==0 || ((*s
=='\t' || *s
==' ') && !in_quotes
)) {
90 /* end of this command line argument */
92 } else if (*s
=='\\') {
95 } else if ((*s
=='"') && ((bcount
& 1)==0)) {
100 /* a regular character */
106 arg
=HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
));
115 if ((*s
=='\t' || *s
==' ') && !in_quotes
) {
116 /* end of this command line argument */
118 } else if (*s
=='\\') {
122 } else if (*s
=='"') {
124 if ((bcount
& 1)==0) {
125 /* Preceeded by an even number of '\', this is half that
126 * number of '\', plus a quote which we erase.
129 in_quotes
=!in_quotes
;
132 /* Preceeded by an odd number of '\', this is half that
133 * number of '\' followed by a '"'
141 /* a regular character */
149 /* skip the remaining spaces */
150 while (**cmdline
=='\t' || **cmdline
==' ') {
157 int main(int argc
, char* argv
[])
161 LPWSTR szDllName
,szEntryPoint
;
164 EntryPointW pEntryPointW
;
165 EntryPointA pEntryPointA
;
173 /* Initialize the rundll32 class */
174 MyRegisterClass( NULL
);
175 hWnd
= CreateWindow(szWindowClass
, szTitle
,
176 WS_OVERLAPPEDWINDOW
|WS_VISIBLE
,
177 CW_USEDEFAULT
, 0, CW_USEDEFAULT
, 0, NULL
, NULL
, NULL
, NULL
);
179 /* Skip the rundll32.exe path */
180 szCmdLine
=GetCommandLineW();
181 WINE_TRACE("CmdLine=%s\n",wine_dbgstr_w(szCmdLine
));
182 szDllName
=GetNextArg(&szCmdLine
);
183 if (!szDllName
|| *szDllName
==0)
185 HeapFree(GetProcessHeap(),0,szDllName
);
187 /* Get the dll name and API EntryPoint */
188 szDllName
=GetNextArg(&szCmdLine
);
189 if (!szDllName
|| *szDllName
==0)
191 WINE_TRACE("DllName=%s\n",wine_dbgstr_w(szDllName
));
192 szEntryPoint
=szDllName
;
193 while (*szEntryPoint
!=0 && *szEntryPoint
!=0x002c /* ',' */)
195 if (*szEntryPoint
==0)
198 WINE_TRACE("EntryPoint=%s\n",wine_dbgstr_w(szEntryPoint
));
200 /* Load the library */
201 hDll
=LoadLibraryW(szDllName
);
204 /* Windows has a MessageBox here... */
205 WINE_WARN("Unable to load %s\n",wine_dbgstr_w(szDllName
));
209 /* Try the Unicode entrypoint. Note that GetProcAddress only takes ascii
212 len
=WideCharToMultiByte(CP_ACP
,0,szEntryPoint
,-1,NULL
,0,NULL
,NULL
);
213 szProcName
=HeapAlloc(GetProcessHeap(),0,len
);
216 WideCharToMultiByte(CP_ACP
,0,szEntryPoint
,-1,szProcName
,len
,NULL
,NULL
);
217 szProcName
[len
-1]=0x0057;
219 pEntryPointW
=(void*)GetProcAddress(hDll
,szProcName
);
222 WCHAR
* szArguments
=NULL
;
224 /* Make a copy of the arguments so they are writable */
225 len
=lstrlenW(szCmdLine
);
228 szArguments
=HeapAlloc(GetProcessHeap(),0,(len
+1)*sizeof(WCHAR
));
231 lstrcpyW(szArguments
,szCmdLine
);
233 WINE_TRACE("Calling %s, arguments=%s\n",
234 szProcName
,wine_dbgstr_w(szArguments
));
235 pEntryPointW(hWnd
,hDll
,szArguments
,SW_SHOWDEFAULT
);
237 HeapFree(GetProcessHeap(),0,szArguments
);
241 /* Then try to append 'A' and finally nothing */
242 szProcName
[len
-1]=0x0041;
243 pEntryPointA
=(void*)GetProcAddress(hDll
,szProcName
);
247 pEntryPointA
=(void*)GetProcAddress(hDll
,szProcName
);
251 char* szArguments
=NULL
;
252 /* Convert the command line to ascii */
253 WINE_TRACE("Calling %s, arguments=%s\n",
254 szProcName
,wine_dbgstr_a(szArguments
));
255 len
=WideCharToMultiByte(CP_ACP
,0,szCmdLine
,-1,NULL
,0,NULL
,NULL
);
258 szArguments
=HeapAlloc(GetProcessHeap(),0,len
);
261 WideCharToMultiByte(CP_ACP
,0,szCmdLine
,-1,szArguments
,len
,NULL
,NULL
);
263 pEntryPointA(hWnd
,hDll
,szArguments
,SW_SHOWDEFAULT
);
265 HeapFree(GetProcessHeap(),0,szArguments
);
269 /* Windows has a MessageBox here... */
270 WINE_WARN("Unable to find the entry point: %s\n",szProcName
);
280 HeapFree(GetProcessHeap(),0,szDllName
);
282 HeapFree(GetProcessHeap(),0,szProcName
);
283 return 0; /* rundll32 always returns 0! */