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! */