regsvr32.c 8.35 KB
Newer Older
1
/*
2
 * PURPOSE: Register OLE components in the registry
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * Copyright 2001 ReactOS project
 * Copyright 2001 Jurgen Van Gael [jurgen.vangael@student.kuleuven.ac.be]
 * Copyright 2002 Andriy Palamarchuk
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
21
 *
22
 * This version deliberately differs in error handling compared to the
23
 * windows version.
24 25 26 27
 */

/*
 *
28
 *  regsvr32 [/u] [/s] [/n] [/i[:cmdline]] dllname ...
29 30 31 32 33
 *  [/u]    unregister server
 *  [/s]    silent (no message boxes)
 *  [/i]    Call DllInstall passing it an optional [cmdline];
 *          when used with /u calls dll uninstall.
 *  [/n]    Do not call DllRegisterServer; this option must be used with [/i]
34
 *  [/c]    Console output (seems to be deprecated and ignored)
35 36 37
 *
 *  Note the complication that this version may be passed unix format file names
 *  which might be mistaken for flags.  Conveniently the Windows version
38
 *  requires each flag to be separate (e.g. no /su ) and so we will simply
39
 *  assume that anything longer than /. is a filename.
40 41 42 43
 */

/**
 * FIXME - currently receives command-line parameters in ASCII only and later
44
 * converts to Unicode. Ideally the function should have wWinMain entry point
45 46 47 48
 * and then work in Unicode only, but it seems Wine does not have necessary
 * support.
 */

49 50
#define WIN32_LEAN_AND_MEAN

51 52 53
#include "config.h"
#include "wine/port.h"

54
#include <stdio.h>
55
#include <string.h>
56
#include <windows.h>
57
#include <ole2.h>
58 59 60 61 62 63 64

typedef HRESULT (*DLLREGISTER)          (void);
typedef HRESULT (*DLLUNREGISTER)        (void);
typedef HRESULT (*DLLINSTALL)           (BOOL,LPCWSTR);

int Silent = 0;

65
static int Usage(void)
66
{
67
    printf("regsvr32 [/u] [/s] [/n] [/i[:cmdline]] dllname ...\n");
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    printf("\t[/u]  unregister server\n");
    printf("\t[/s]  silent (no message boxes)\n");
    printf("\t[/i]  Call DllInstall passing it an optional [cmdline];\n");
    printf("\t      when used with /u calls dll uninstall\n");
    printf("\t[/n]  Do not call DllRegisterServer; this option "
           "must be used with [/i]\n");
    return 0;
}

/**
 * Loads procedure.
 *
 * Parameters:
 * strDll - name of the dll.
 * procName - name of the procedure to load from dll
 * pDllHanlde - output variable receives handle of the loaded dll.
 */
85
static VOID *LoadProc(const char* strDll, const char* procName, HMODULE* DllHandle)
86 87 88
{
    VOID* (*proc)(void);

89
    *DllHandle = LoadLibraryExA(strDll, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
90 91 92
    if(!*DllHandle)
    {
        if(!Silent)
Andreas Mohr's avatar
Andreas Mohr committed
93
            printf("Failed to load DLL %s\n", strDll);
94

95
        ExitProcess(1);
96 97 98 99 100
    }
    proc = (VOID *) GetProcAddress(*DllHandle, procName);
    if(!proc)
    {
        if(!Silent)
Andreas Mohr's avatar
Andreas Mohr committed
101
            printf("%s not implemented in DLL %s\n", procName, strDll);
102
        FreeLibrary(*DllHandle);
103
        ExitProcess(1);
104 105 106 107
    }
    return proc;
}

108
static int RegisterDll(const char* strDll)
109 110 111 112 113 114 115 116 117 118 119
{
    HRESULT hr;
    DLLREGISTER pfRegister;
    HMODULE DllHandle = NULL;

    pfRegister = LoadProc(strDll, "DllRegisterServer", &DllHandle);

    hr = pfRegister();
    if(FAILED(hr))
    {
        if(!Silent)
Andreas Mohr's avatar
Andreas Mohr committed
120
            printf("Failed to register DLL %s\n", strDll);
121 122 123 124

        return -1;
    }
    if(!Silent)
Andreas Mohr's avatar
Andreas Mohr committed
125
        printf("Successfully registered DLL %s\n", strDll);
126 127 128 129 130 131

    if(DllHandle)
        FreeLibrary(DllHandle);
    return 0;
}

132
static int UnregisterDll(char* strDll)
133 134 135 136 137 138 139 140 141 142
{
    HRESULT hr;
    DLLUNREGISTER pfUnregister;
    HMODULE DllHandle = NULL;

    pfUnregister = LoadProc(strDll, "DllUnregisterServer", &DllHandle);
    hr = pfUnregister();
    if(FAILED(hr))
    {
        if(!Silent)
Andreas Mohr's avatar
Andreas Mohr committed
143
            printf("Failed to unregister DLL %s\n", strDll);
144 145 146 147

        return -1;
    }
    if(!Silent)
Andreas Mohr's avatar
Andreas Mohr committed
148
        printf("Successfully unregistered DLL %s\n", strDll);
149 150 151 152 153 154

    if(DllHandle)
        FreeLibrary(DllHandle);
    return 0;
}

155
static int InstallDll(BOOL install, char *strDll, WCHAR *command_line)
156 157 158 159 160 161 162 163 164 165
{
    HRESULT hr;
    DLLINSTALL pfInstall;
    HMODULE DllHandle = NULL;

    pfInstall = LoadProc(strDll, "DllInstall", &DllHandle);
    hr = pfInstall(install, command_line);
    if(FAILED(hr))
    {
        if(!Silent)
Andreas Mohr's avatar
Andreas Mohr committed
166
            printf("Failed to %s DLL %s\n", install ? "install" : "uninstall",
167 168 169 170
                   strDll);
        return -1;
    }
    if(!Silent)
Andreas Mohr's avatar
Andreas Mohr committed
171
        printf("Successfully %s DLL %s\n",  install ? "installed" : "uninstalled",
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
               strDll);

    if(DllHandle)
        FreeLibrary(DllHandle);
    return 0;
}

int main(int argc, char* argv[])
{
    int             i;
    BOOL            CallRegister = TRUE;
    BOOL            CallInstall = FALSE;
    BOOL            Unregister = FALSE;
    BOOL            DllFound = FALSE;
    WCHAR*          wsCommandLine = NULL;
    WCHAR           EmptyLine[1] = {0};
188

189
    OleInitialize(NULL);
190

191 192 193 194 195
    /* Strictly, the Microsoft version processes all the flags before
     * the files (e.g. regsvr32 file1 /s file2 is silent even for file1.
     * For ease, we will not replicate that and will process the arguments
     * in order.
     */
196 197
    for(i = 1; i < argc; i++)
    {
198
        if ((!strcasecmp(argv[i], "/u")) ||(!strcasecmp(argv[i], "-u")))
199
                Unregister = TRUE;
200
        else if ((!strcasecmp(argv[i], "/s"))||(!strcasecmp(argv[i], "-s")))
201
                Silent = 1;
202
        else if ((!strncasecmp(argv[i], "/i", strlen("/i")))||(!strncasecmp(argv[i], "-i", strlen("-i"))))
203 204
        {
            CHAR* command_line = argv[i] + strlen("/i");
205

206
            CallInstall = TRUE;
207
            if (command_line[0] == ':' && command_line[1])
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
            {
                int len = strlen(command_line);

                command_line++;
                len--;
                /* remove double quotes */
                if (command_line[0] == '"')
                {
                    command_line++;
                    len--;
                    if (command_line[0])
                    {
                        len--;
                        command_line[len] = 0;
                    }
                }
                if (command_line[0])
                {
                    len = MultiByteToWideChar(CP_ACP, 0, command_line, -1,
                                              NULL, 0);
                    wsCommandLine = HeapAlloc(GetProcessHeap(), 0,
                                              len * sizeof(WCHAR));
                    if (wsCommandLine)
                        MultiByteToWideChar(CP_ACP, 0, command_line, -1,
                                            wsCommandLine, len);
                }
                else
                {
                    wsCommandLine = EmptyLine;
                }
            }
239
            else
240 241 242 243
            {
                wsCommandLine = EmptyLine;
            }
        }
244
        else if((!strcasecmp(argv[i], "/n"))||(!strcasecmp(argv[i], "-n")))
245
            CallRegister = FALSE;
246 247
        else if((!strcasecmp(argv[i], "/c"))||(!strcasecmp(argv[i], "-c")))
            /* console output */;
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
        else if (argv[i][0] == '/' && (!argv[i][2] || argv[i][2] == ':'))
            printf("Unrecognized switch %s\n", argv[i]);
        else
        {
            char *DllName = argv[i];
            int res = 0;

            DllFound = TRUE;
            if (!CallInstall || (CallInstall && CallRegister))
            {
                if(Unregister)
                    res = UnregisterDll(DllName);
                else
                    res = RegisterDll(DllName);
            }
263

264 265
            if (res)
                return res;
266
	    /* Confirmed.  The windows version does stop on the first error.*/
267 268 269 270 271

            if (CallInstall)
            {
                res = InstallDll(!Unregister, DllName, wsCommandLine);
            }
272

273 274
            if (res)
		return res;
275 276 277 278 279 280 281 282 283 284 285
        }
    }

    if (!DllFound)
    {
        if(!Silent)
            return Usage();
        else
            return -1;
    }

286 287
    OleUninitialize();

288 289
    return 0;
}