ntdll: Align string data in RtlCreateProcessParametersEx().
[wine.git] / programs / regsvr32 / regsvr32.c
blobcfbb80d465ad0419996a4dd9e56bf7695612597a
1 /*
2 * PURPOSE: Register OLE components in the registry
4 * Copyright 2001 ReactOS project
5 * Copyright 2001 Jurgen Van Gael [jurgen.vangael@student.kuleuven.ac.be]
6 * Copyright 2002 Andriy Palamarchuk
7 * Copyright 2014, 2015 Hugh McMaster
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define WIN32_LEAN_AND_MEAN
26 #include "config.h"
27 #include "wine/port.h"
29 #include <windows.h>
30 #include <ole2.h>
31 #include "regsvr32.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(regsvr32);
37 typedef HRESULT (WINAPI *DLLREGISTER) (void);
38 typedef HRESULT (WINAPI *DLLUNREGISTER) (void);
39 typedef HRESULT (WINAPI *DLLINSTALL) (BOOL,LPCWSTR);
41 static BOOL Silent = FALSE;
43 static void WINAPIV output_write(UINT id, ...)
45 WCHAR fmt[1024];
46 __ms_va_list va_args;
47 WCHAR *str;
48 DWORD len, nOut, ret;
50 if (Silent) return;
52 if (!LoadStringW(GetModuleHandleW(NULL), id, fmt, ARRAY_SIZE(fmt)))
54 WINE_FIXME("LoadString failed with %d\n", GetLastError());
55 return;
58 __ms_va_start(va_args, id);
59 SetLastError(NO_ERROR);
60 len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
61 fmt, 0, 0, (LPWSTR)&str, 0, &va_args);
62 __ms_va_end(va_args);
63 if (len == 0 && GetLastError() != NO_ERROR)
65 WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt));
66 return;
69 ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, len, &nOut, NULL);
71 /* WriteConsole fails if its output is redirected to a file.
72 * If this occurs, we should use an OEM codepage and call WriteFile.
74 if (!ret)
76 DWORD lenA;
77 char *strA;
79 lenA = WideCharToMultiByte(GetConsoleOutputCP(), 0, str, len, NULL, 0, NULL, NULL);
80 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
81 if (strA)
83 WideCharToMultiByte(GetConsoleOutputCP(), 0, str, len, strA, lenA, NULL, NULL);
84 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), strA, lenA, &nOut, FALSE);
85 HeapFree(GetProcessHeap(), 0, strA);
88 LocalFree(str);
91 /**
92 * Loads procedure.
94 * Parameters:
95 * strDll - name of the dll.
96 * procName - name of the procedure to load from the dll.
97 * DllHandle - a variable that receives the handle of the loaded dll.
99 static VOID *LoadProc(const WCHAR* strDll, const char* procName, HMODULE* DllHandle)
101 VOID* (*proc)(void);
103 *DllHandle = LoadLibraryExW(strDll, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
104 if(!*DllHandle)
106 output_write(STRING_DLL_LOAD_FAILED, strDll);
107 ExitProcess(LOADLIBRARY_FAILED);
109 proc = (VOID *) GetProcAddress(*DllHandle, procName);
110 if(!proc)
112 output_write(STRING_PROC_NOT_IMPLEMENTED, procName, strDll);
113 FreeLibrary(*DllHandle);
114 return NULL;
116 return proc;
119 static int RegisterDll(const WCHAR* strDll)
121 HRESULT hr;
122 DLLREGISTER pfRegister;
123 HMODULE DllHandle = NULL;
125 pfRegister = LoadProc(strDll, "DllRegisterServer", &DllHandle);
126 if (!pfRegister)
127 return GETPROCADDRESS_FAILED;
129 hr = pfRegister();
130 if(FAILED(hr))
132 output_write(STRING_REGISTER_FAILED, strDll);
133 return DLLSERVER_FAILED;
135 output_write(STRING_REGISTER_SUCCESSFUL, strDll);
137 if(DllHandle)
138 FreeLibrary(DllHandle);
139 return 0;
142 static int UnregisterDll(const WCHAR* strDll)
144 HRESULT hr;
145 DLLUNREGISTER pfUnregister;
146 HMODULE DllHandle = NULL;
148 pfUnregister = LoadProc(strDll, "DllUnregisterServer", &DllHandle);
149 if (!pfUnregister)
150 return GETPROCADDRESS_FAILED;
152 hr = pfUnregister();
153 if(FAILED(hr))
155 output_write(STRING_UNREGISTER_FAILED, strDll);
156 return DLLSERVER_FAILED;
158 output_write(STRING_UNREGISTER_SUCCESSFUL, strDll);
160 if(DllHandle)
161 FreeLibrary(DllHandle);
162 return 0;
165 static int InstallDll(BOOL install, const WCHAR *strDll, const WCHAR *command_line)
167 HRESULT hr;
168 DLLINSTALL pfInstall;
169 HMODULE DllHandle = NULL;
171 pfInstall = LoadProc(strDll, "DllInstall", &DllHandle);
172 if (!pfInstall)
173 return GETPROCADDRESS_FAILED;
175 hr = pfInstall(install, command_line);
176 if(FAILED(hr))
178 if (install)
179 output_write(STRING_INSTALL_FAILED, strDll);
180 else
181 output_write(STRING_UNINSTALL_FAILED, strDll);
182 return DLLSERVER_FAILED;
184 if (install)
185 output_write(STRING_INSTALL_SUCCESSFUL, strDll);
186 else
187 output_write(STRING_UNINSTALL_SUCCESSFUL, strDll);
189 if(DllHandle)
190 FreeLibrary(DllHandle);
191 return 0;
194 static WCHAR *parse_command_line(WCHAR *command_line)
196 if (command_line[0] == ':' && command_line[1])
198 int len = strlenW(command_line);
200 command_line++;
201 len--;
202 /* remove double quotes */
203 if (command_line[0] == '"')
205 command_line++;
206 len--;
207 if (command_line[0])
209 len--;
210 command_line[len] = 0;
213 if (command_line[0])
214 return command_line;
216 return NULL;
219 int wmain(int argc, WCHAR* argv[])
221 int i, res, ret = 0;
222 BOOL CallRegister = TRUE;
223 BOOL CallInstall = FALSE;
224 BOOL Unregister = FALSE;
225 BOOL DllFound = FALSE;
226 WCHAR* wsCommandLine = NULL;
227 WCHAR EmptyLine[1] = {0};
229 OleInitialize(NULL);
231 /* We mirror the Microsoft version by processing all of the flags before
232 * the files (e.g. regsvr32 file1 /s file2 is silent even for file1).
234 * Note the complication that this version may be passed Unix format filenames
235 * which could be mistaken for flags. The Windows version conveniently
236 * requires each flag to be separate (e.g. no /su), so we will simply
237 * assume that anything longer than /. is a filename.
239 for(i = 1; i < argc; i++)
241 if (argv[i][0] == '/' || argv[i][0] == '-')
243 if (!argv[i][1])
244 return INVALID_ARG;
246 if (argv[i][2] && argv[i][2] != ':')
247 continue;
249 switch (tolowerW(argv[i][1]))
251 case 'u':
252 Unregister = TRUE;
253 break;
254 case 's':
255 Silent = TRUE;
256 break;
257 case 'i':
258 CallInstall = TRUE;
259 wsCommandLine = parse_command_line(argv[i] + 2); /* argv[i] + strlen("/i") */
260 if (!wsCommandLine)
261 wsCommandLine = EmptyLine;
262 break;
263 case 'n':
264 CallRegister = FALSE;
265 break;
266 case 'c':
267 /* console output */;
268 break;
269 default:
270 output_write(STRING_UNRECOGNIZED_SWITCH, argv[i]);
271 output_write(STRING_USAGE);
272 return INVALID_ARG;
274 argv[i] = NULL;
278 if (!CallInstall && !CallRegister) /* flags: /n or /u /n */
279 return INVALID_ARG;
281 for (i = 1; i < argc; i++)
283 if (argv[i])
285 WCHAR *DllName = argv[i];
286 res = 0;
288 DllFound = TRUE;
289 if (CallInstall && Unregister)
290 res = InstallDll(!Unregister, DllName, wsCommandLine);
292 /* The Windows version stops processing the current file on the first error. */
293 if (res)
295 ret = res;
296 continue;
299 if (!CallInstall || CallRegister)
301 if(Unregister)
302 res = UnregisterDll(DllName);
303 else
304 res = RegisterDll(DllName);
307 if (res)
309 ret = res;
310 continue;
313 if (CallInstall && !Unregister)
314 res = InstallDll(!Unregister, DllName, wsCommandLine);
316 if (res)
318 ret = res;
319 continue;
324 if (!DllFound)
326 output_write(STRING_HEADER);
327 output_write(STRING_USAGE);
328 return INVALID_ARG;
331 OleUninitialize();
333 /* return the most recent error code, even if later DLLs succeed */
334 return ret;