extrac32.c 4.96 KB
Newer Older
1 2 3 4
/*
 * Extract - Wine-compatible program for extract *.cab files.
 *
 * Copyright 2007 Etersoft (Lyutin Anatoly)
5
 * Copyright 2009 Ilya Shpigor
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <windows.h>
23
#include <shellapi.h>
24
#include <setupapi.h>
25
#include <shlwapi.h>
26 27 28 29 30 31

#include "wine/unicode.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(extrac32);

32 33
static BOOL force_mode;

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
static UINT WINAPI ExtCabCallback(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2)
{
    FILE_IN_CABINET_INFO_W *pInfo;
    FILEPATHS_W *pFilePaths;

    switch(Notification)
    {
        case SPFILENOTIFY_FILEINCABINET:
            pInfo = (FILE_IN_CABINET_INFO_W*)Param1;
            lstrcpyW(pInfo->FullTargetName, (LPCWSTR)Context);
            lstrcatW(pInfo->FullTargetName, pInfo->NameInCabinet);
            return FILEOP_DOIT;
        case SPFILENOTIFY_FILEEXTRACTED:
            pFilePaths = (FILEPATHS_W*)Param1;
            WINE_TRACE("Extracted %s\n", wine_dbgstr_w(pFilePaths->Target));
            return NO_ERROR;
    }
    return NO_ERROR;
}

static void extract(LPCWSTR cabfile, LPWSTR destdir)
{
    if (!SetupIterateCabinetW(cabfile, 0, ExtCabCallback, destdir))
        WINE_ERR("Could not extract cab file %s\n", wine_dbgstr_w(cabfile));
}

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
static void copy_file(LPCWSTR source, LPCWSTR destination)
{
    WCHAR destfile[MAX_PATH];

    /* append source filename if destination is a directory */
    if (PathIsDirectoryW(destination))
    {
        PathCombineW(destfile, destination, PathFindFileNameW(source));
        destination = destfile;
    }

    if (PathFileExistsW(destination) && !force_mode)
    {
        static const WCHAR overwriteMsg[] = {'O','v','e','r','w','r','i','t','e',' ','"','%','s','"','?',0};
        static const WCHAR titleMsg[] = {'E','x','t','r','a','c','t',0};
        WCHAR msg[MAX_PATH+100];
        snprintfW(msg, sizeof(msg)/sizeof(msg[0]), overwriteMsg, destination);
        if (MessageBoxW(NULL, msg, titleMsg, MB_YESNO | MB_ICONWARNING) != IDYES)
            return;
    }

    WINE_TRACE("copying %s to %s\n", wine_dbgstr_w(source), wine_dbgstr_w(destination));
    CopyFileW(source, destination, FALSE);
}

85 86
int PASCAL wWinMain(HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmdline, int show)
{
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
    LPWSTR *argv;
    int argc;
    int i;
    WCHAR check, cmd = 0;
    WCHAR path[MAX_PATH];
    WCHAR backslash[] = {'\\',0};
    LPCWSTR cabfile = NULL;

    path[0] = 0;
    argv = CommandLineToArgvW(cmdline, &argc);

    if(!argv)
    {
        WINE_ERR("Bad command line arguments\n");
        return 0;
    }

    /* Parse arguments */
    for(i = 0; i < argc; i++)
    {
        /* Get cabfile */
108
        if (argv[i][0] != '/')
109
        {
110 111 112 113 114 115
            if (!cabfile)
            {
                cabfile = argv[i];
                continue;
            } else
                break;
116 117 118 119 120 121 122 123 124
        }
        /* Get parameters for commands */
        check = toupperW( argv[i][1] );
        switch(check)
        {
            case 'A':
                WINE_FIXME("/A not implemented\n");
                break;
            case 'Y':
125
                force_mode = TRUE;
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
                break;
            case 'L':
                if ((i + 1) >= argc) return 0;
                if (!GetFullPathNameW(argv[++i], MAX_PATH, path, NULL))
                    return 0;
                break;
            case 'C':
                if (cmd) return 0;
                cmd = check;
                break;
            case 'E':
            case 'D':
                if (cmd) return 0;
                cmd = check;
                break;
            default:
                return 0;
        }
    }

    if (!cabfile)
        return 0;

149 150 151 152 153 154 155
    if (cmd == 'C')
    {
        if ((i + 1) != argc) return 0;
        if (!GetFullPathNameW(argv[i], MAX_PATH, path, NULL))
            return 0;
    }

156 157 158 159 160 161 162 163 164 165
    if (!path[0])
        GetCurrentDirectoryW(MAX_PATH, path);

    lstrcatW(path, backslash);

    /* Execute the specified command */
    switch(cmd)
    {
        case 'C':
            /* Copy file */
166
            copy_file(cabfile, path);
167 168 169
            break;
        case 'E':
            /* Extract CAB archive */
170
            extract(cabfile, path);
171 172 173 174 175 176 177
            break;
        case 0:
        case 'D':
            /* Display CAB archive */
            WINE_FIXME("/D not implemented\n");
            break;
    }
178 179
    return 0;
}