The 'w' component is used more than just for the vertex, so we cannot
[wine/testsucceed.git] / programs / rundll32 / rundll32.c
blob0d5ce9b1d282190d632281b37ff31948c778fc33
1 /*
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
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
36 /* Exclude rarely-used stuff from Windows headers */
37 #define WIN32_LEAN_AND_MEAN
38 #include <windows.h>
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)
59 WNDCLASSEX wcex;
61 wcex.cbSize = sizeof(WNDCLASSEX);
63 wcex.style = CS_HREDRAW | CS_VREDRAW;
64 wcex.lpfnWndProc = (WNDPROC)DefWindowProc;
65 wcex.cbClsExtra = 0;
66 wcex.cbWndExtra = 0;
67 wcex.hInstance = hInstance;
68 wcex.hIcon = NULL;
69 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
70 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
71 wcex.lpszMenuName = NULL;
72 wcex.lpszClassName = szWindowClass;
73 wcex.hIconSm = NULL;
75 return RegisterClassEx(&wcex);
78 static LPWSTR GetNextArg(LPCWSTR *cmdline)
80 LPCWSTR s;
81 LPWSTR arg,d;
82 int in_quotes,bcount,len=0;
84 /* count the chars */
85 bcount=0;
86 in_quotes=0;
87 s=*cmdline;
88 while (1) {
89 if (*s==0 || ((*s=='\t' || *s==' ') && !in_quotes)) {
90 /* end of this command line argument */
91 break;
92 } else if (*s=='\\') {
93 /* '\', count them */
94 bcount++;
95 } else if ((*s=='"') && ((bcount & 1)==0)) {
96 /* unescaped '"' */
97 in_quotes=!in_quotes;
98 bcount=0;
99 } else {
100 /* a regular character */
101 bcount=0;
103 s++;
104 len++;
106 arg=HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
107 if (!arg)
108 return NULL;
110 bcount=0;
111 in_quotes=0;
112 d=arg;
113 s=*cmdline;
114 while (*s) {
115 if ((*s=='\t' || *s==' ') && !in_quotes) {
116 /* end of this command line argument */
117 break;
118 } else if (*s=='\\') {
119 /* '\\' */
120 *d++=*s++;
121 bcount++;
122 } else if (*s=='"') {
123 /* '"' */
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.
128 d-=bcount/2;
129 in_quotes=!in_quotes;
130 s++;
131 } else {
132 /* Preceeded by an odd number of '\', this is half that
133 * number of '\' followed by a '"'
135 d=d-bcount/2-1;
136 *d++='"';
137 s++;
139 bcount=0;
140 } else {
141 /* a regular character */
142 *d++=*s++;
143 bcount=0;
146 *d=0;
147 *cmdline=s;
149 /* skip the remaining spaces */
150 while (**cmdline=='\t' || **cmdline==' ') {
151 (*cmdline)++;
154 return arg;
157 int main(int argc, char* argv[])
159 HWND hWnd;
160 LPCWSTR szCmdLine;
161 LPWSTR szDllName,szEntryPoint;
162 char* szProcName;
163 HMODULE hDll;
164 EntryPointW pEntryPointW;
165 EntryPointA pEntryPointA;
166 int len;
168 hWnd=NULL;
169 hDll=NULL;
170 szDllName=NULL;
171 szProcName=NULL;
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)
184 goto CLEANUP;
185 HeapFree(GetProcessHeap(),0,szDllName);
187 /* Get the dll name and API EntryPoint */
188 szDllName=GetNextArg(&szCmdLine);
189 if (!szDllName || *szDllName==0)
190 goto CLEANUP;
191 WINE_TRACE("DllName=%s\n",wine_dbgstr_w(szDllName));
192 szEntryPoint=szDllName;
193 while (*szEntryPoint!=0 && *szEntryPoint!=0x002c /* ',' */)
194 szEntryPoint++;
195 if (*szEntryPoint==0)
196 goto CLEANUP;
197 *szEntryPoint++=0;
198 WINE_TRACE("EntryPoint=%s\n",wine_dbgstr_w(szEntryPoint));
200 /* Load the library */
201 hDll=LoadLibraryW(szDllName);
202 if (!hDll)
204 /* Windows has a MessageBox here... */
205 WINE_WARN("Unable to load %s\n",wine_dbgstr_w(szDllName));
206 goto CLEANUP;
209 /* Try the Unicode entrypoint. Note that GetProcAddress only takes ascii
210 * names.
212 len=WideCharToMultiByte(CP_ACP,0,szEntryPoint,-1,NULL,0,NULL,NULL);
213 szProcName=HeapAlloc(GetProcessHeap(),0,len);
214 if (!szProcName)
215 goto CLEANUP;
216 WideCharToMultiByte(CP_ACP,0,szEntryPoint,-1,szProcName,len,NULL,NULL);
217 szProcName[len-1]=0x0057;
218 szProcName[len]=0;
219 pEntryPointW=(void*)GetProcAddress(hDll,szProcName);
220 if (pEntryPointW)
222 WCHAR* szArguments=NULL;
224 /* Make a copy of the arguments so they are writable */
225 len=lstrlenW(szCmdLine);
226 if (len>0)
228 szArguments=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
229 if (!szArguments)
230 goto CLEANUP;
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);
236 if (szArguments)
237 HeapFree(GetProcessHeap(),0,szArguments);
239 else
241 /* Then try to append 'A' and finally nothing */
242 szProcName[len-1]=0x0041;
243 pEntryPointA=(void*)GetProcAddress(hDll,szProcName);
244 if (!pEntryPointA)
246 szProcName[len-1]=0;
247 pEntryPointA=(void*)GetProcAddress(hDll,szProcName);
249 if (pEntryPointA)
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);
256 if (len>1)
258 szArguments=HeapAlloc(GetProcessHeap(),0,len);
259 if (!szArguments)
260 goto CLEANUP;
261 WideCharToMultiByte(CP_ACP,0,szCmdLine,-1,szArguments,len,NULL,NULL);
263 pEntryPointA(hWnd,hDll,szArguments,SW_SHOWDEFAULT);
264 if (szArguments)
265 HeapFree(GetProcessHeap(),0,szArguments);
267 else
269 /* Windows has a MessageBox here... */
270 WINE_WARN("Unable to find the entry point: %s\n",szProcName);
274 CLEANUP:
275 if (hWnd)
276 DestroyWindow(hWnd);
277 if (hDll)
278 FreeLibrary(hDll);
279 if (szDllName)
280 HeapFree(GetProcessHeap(),0,szDllName);
281 if (szProcName)
282 HeapFree(GetProcessHeap(),0,szProcName);
283 return 0; /* rundll32 always returns 0! */