Beispiel #1
0
/***********************************************************************
 * msidbExportStream
 *
 * Exports a stream to a file with an .idb extension.
 *
 * Examples (note wildcard escape for *nix/bash):
 * msidb -d <pathtomsi>.msi -f <workdir> -x <streamname>
 * msidb -d <pathtomsi>.msi -f <workdir> -x data.cab
 **********************************************************************/
static BOOL msidbExportStream(LPCWSTR dbfile, LPCWSTR wdir, LPCWSTR streamName)
{
    static const char ext[] = {'.', 'i', 'd', 'b', 0};
    UINT r, len;
    MSIHANDLE dbhandle, streamListView, rec;
    char queryBuffer[100];
    FILE *fp = 0;
    char *streamNameA = strdupWtoA(CP_ACP, streamName);
    char *wdirA = strdupWtoA(CP_ACP, wdir);
    char *streamFileA = 0;
    char streamPath[MAX_PATH];
    char *dataBuffer;
    DWORD dataLen = 0;

    r = MsiOpenDatabaseW(dbfile, (LPCWSTR) MSIDBOPEN_READONLY, &dbhandle);
    if (r != ERROR_SUCCESS) return FALSE;

    sprintf(queryBuffer, "SELECT * FROM _Streams WHERE Name = '%s'", streamNameA);
    MsiDatabaseOpenView(dbhandle, queryBuffer, &streamListView);
    MsiViewExecute(streamListView, 0);
    r = MsiViewFetch(streamListView, &rec);
    if (r != ERROR_SUCCESS) return FALSE;

    if (MsiRecordReadStream(rec, 2, 0, &dataLen) != ERROR_SUCCESS)
        return FALSE;
    dataBuffer = malloc(dataLen);
    if (!dataBuffer) return FALSE;
    if (MsiRecordReadStream(rec, 2, dataBuffer, &dataLen) != ERROR_SUCCESS)
        return FALSE;

    len = strlen(streamNameA) + 5;
    streamFileA = malloc(len);
    if (streamFileA == NULL) return FALSE;

    strcpy(streamFileA, streamNameA);
    strcat(streamFileA, ext);

    strcpy(streamPath, wdirA);
    strcat(streamPath, PATH_DELIMITER);
    strcat(streamPath, streamFileA);

    fp = fopen(streamPath , "wb");
    if (fp != NULL)
    {
        fwrite(dataBuffer, 1, dataLen, fp);
        fclose(fp);
    }

    free(streamFileA);
    MsiCloseHandle(rec);

    MsiViewClose(streamListView);
    MsiCloseHandle(streamListView);
    MsiCloseHandle(dbhandle);
    free(wdirA);
    free(streamNameA);
    return TRUE;
}
Beispiel #2
0
/***********************************************************************
 *            extract_cabinet_file
 *
 * Extract files from a cab file.
 */
static BOOL extract_cabinet_file(MSIPACKAGE* package, LPCWSTR source, 
                                 LPCWSTR path)
{
    HFDI hfdi;
    ERF erf;
    BOOL ret;
    char *cabinet;
    char *cab_path;
    CabData data;

    TRACE("Extracting %s to %s\n",debugstr_w(source), debugstr_w(path));

    hfdi = FDICreate(cabinet_alloc,
                     cabinet_free,
                     cabinet_open,
                     cabinet_read,
                     cabinet_write,
                     cabinet_close,
                     cabinet_seek,
                     0,
                     &erf);
    if (!hfdi)
    {
        ERR("FDICreate failed\n");
        return FALSE;
    }

    if (!(cabinet = strdupWtoA( source )))
    {
        FDIDestroy(hfdi);
        return FALSE;
    }
    if (!(cab_path = strdupWtoA( path )))
    {
        FDIDestroy(hfdi);
        msi_free(cabinet);
        return FALSE;
    }

    data.package = package;
    data.cab_path = cab_path;

    ret = FDICopy(hfdi, cabinet, "", 0, cabinet_notify, NULL, &data);

    if (!ret)
        ERR("FDICopy failed\n");

    FDIDestroy(hfdi);

    msi_free(cabinet);
    msi_free(cab_path);

    return ret;
}
Beispiel #3
0
static BOOL msidbExportStorage(LPCWSTR dbfile, LPCWSTR wdir, LPWSTR storageName)
{
    UINT r, len;
    MSIHANDLE dbhandle, view, rec;
    char queryBuffer[100];
    char *storageNameA = strdupWtoA(CP_ACP, storageName);
    char *wdirA = strdupWtoA(CP_ACP, wdir);
    char *storagePath = NULL;
    char *dataBuffer;
    DWORD dataLen = 0;
    FILE *fp = NULL;
    sprintf(queryBuffer, "SELECT * FROM _Storages WHERE Name = '%s'", storageNameA);

    r = MsiOpenDatabaseW(dbfile, (LPWSTR) MSIDBOPEN_READONLY, &dbhandle);
    if (r != ERROR_SUCCESS) return FALSE;

    MsiDatabaseOpenView(dbhandle, queryBuffer, &view);
    MsiViewExecute(view, 0);
    r = MsiViewFetch(view, &rec);
    if (r != ERROR_SUCCESS) return FALSE;

    if ((r = MsiRecordReadStream(rec, 2, 0, &dataLen)) != ERROR_SUCCESS)
    {
        return FALSE;
    }

    if ((dataBuffer = malloc(dataLen)) == NULL) return FALSE;
    if (MsiRecordReadStream(rec, 2, dataBuffer, &dataLen) != ERROR_SUCCESS) return FALSE;

    len = strlen(wdirA) + strlen(storageNameA) + 2;
    storagePath = malloc(len * sizeof(WCHAR));
    if (storagePath == NULL) return FALSE;

    strcpy(storagePath, wdirA);
    strcat(storagePath, "/");
    strcat(storagePath, storageNameA);

    fp = fopen(storagePath , "wb");
    if (fp != NULL)
    {
        fwrite(dataBuffer, 1, dataLen, fp);
        fclose(fp);
    }

    free(storagePath);
    MsiCloseHandle(rec);

    MsiViewClose(view);
    MsiCloseHandle(view);
    MsiCloseHandle(dbhandle);
    free(storageNameA);
    free(wdirA);
    return TRUE;
}
Beispiel #4
0
static INT_PTR CDECL list_notify( FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin )
{
    WCHAR *nameW;

    switch (fdint)
    {
    case fdintCABINET_INFO:
        return 0;
    case fdintCOPY_FILE:
        nameW = strdupAtoW( (pfdin->attribs & _A_NAME_IS_UTF) ? CP_UTF8 : CP_ACP, pfdin->psz1 );
        if (match_files( nameW ))
        {
            char *nameU = strdupWtoA( CP_UNIXCP, nameW );
            if (opt_verbose)
            {
                char attrs[] = "rxash";
                if (!(pfdin->attribs & _A_RDONLY)) attrs[0] = '-';
                if (!(pfdin->attribs & _A_EXEC))   attrs[1] = '-';
                if (!(pfdin->attribs & _A_ARCH))   attrs[2] = '-';
                if (!(pfdin->attribs & _A_SYSTEM)) attrs[3] = '-';
                if (!(pfdin->attribs & _A_HIDDEN)) attrs[4] = '-';
                printf( " %s %9u  %04u/%02u/%02u %02u:%02u:%02u  ", attrs, pfdin->cb,
                        (pfdin->date >> 9) + 1980, (pfdin->date >> 5) & 0x0f, pfdin->date & 0x1f,
                        pfdin->time >> 11, (pfdin->time >> 5) & 0x3f, (pfdin->time & 0x1f) * 2 );
            }
            printf( "%s\n", nameU );
            cab_free( nameU );
        }
        cab_free( nameW );
        return 0;
    default:
        WINE_FIXME( "Unexpected notification type %d.\n", fdint );
        return 0;
    }
}
Beispiel #5
0
/***********************************************************************
 *            extract_cabinet_file
 *
 * Extract files from a cab file.
 */
static BOOL extract_cabinet_file(MSIPACKAGE* package, struct media_info *mi)
{
    LPSTR cabinet, cab_path = NULL;
    LPWSTR ptr;
    HFDI hfdi;
    ERF erf;
    BOOL ret = FALSE;
    CabData data;

    TRACE("Extracting %s\n", debugstr_w(mi->source));

    hfdi = FDICreate(cabinet_alloc, cabinet_free, cabinet_open, cabinet_read,
                     cabinet_write, cabinet_close, cabinet_seek, 0, &erf);
    if (!hfdi)
    {
        ERR("FDICreate failed\n");
        return FALSE;
    }

    ptr = strrchrW(mi->source, '\\') + 1;
    cabinet = strdupWtoA(ptr);
    if (!cabinet)
        goto done;

    cab_path = strdupWtoA(mi->source);
    if (!cab_path)
        goto done;

    cab_path[ptr - mi->source] = '\0';

    data.package = package;
    data.mi = mi;

    ret = FDICopy(hfdi, cabinet, cab_path, 0, cabinet_notify, NULL, &data);
    if (!ret)
        ERR("FDICopy failed\n");

done:
    FDIDestroy(hfdi);
    msi_free(cabinet);
    msi_free(cab_path);

    if (ret)
        mi->is_extracted = TRUE;

    return ret;
}
Beispiel #6
0
/* downloads a remote cabinet and extracts it if it exists */
static UINT msi_extract_remote_cabinet( MSIPACKAGE *package, struct media_info *mi )
{
    FDICABINETINFO cabinfo;
    WCHAR temppath[MAX_PATH];
    WCHAR src[MAX_PATH];
    LPSTR cabpath;
    LPCWSTR file;
    LPWSTR ptr;
    HFDI hfdi;
    ERF erf;
    int hf;

    /* the URL is the path prefix of the package URL and the filename
     * of the file to download
     */
    ptr = strrchrW(package->PackagePath, '/');
    lstrcpynW(src, package->PackagePath, ptr - package->PackagePath + 2);
    ptr = strrchrW(mi->source, '\\');
    lstrcatW(src, ptr + 1);

    file = msi_download_file( src, temppath );
    lstrcpyW(mi->source, file);

    /* check if the remote cabinet still exists, ignore if it doesn't */
    hfdi = FDICreate(cabinet_alloc, cabinet_free, cabinet_open, cabinet_read,
                     cabinet_write, cabinet_close, cabinet_seek, 0, &erf);
    if (!hfdi)
    {
        ERR("FDICreate failed\n");
        return ERROR_FUNCTION_FAILED;
    }

    cabpath = strdupWtoA(mi->source);
    hf = cabinet_open(cabpath, _O_RDONLY, 0);
    if (!FDIIsCabinet(hfdi, hf, &cabinfo))
    {
        WARN("Remote cabinet %s does not exist.\n", debugstr_w(mi->source));
        msi_free(cabpath);
        return ERROR_SUCCESS;
    }

    msi_free(cabpath);
    return !extract_cabinet_file(package, mi->source, mi->last_path);
}
Beispiel #7
0
static BOOL add_file( HFCI fci, WCHAR *name )
{
    BOOL ret;
    char *filename, *path = strdupWtoA( CP_UTF8, name );

    if (!opt_preserve_paths)
    {
        if ((filename = strrchr( path, '\\' ))) filename++;
        else filename = path;
    }
    else
    {
        filename = path;
        while (*filename == '\\') filename++;  /* remove leading backslashes */
    }
    ret = FCIAddFile( fci, path, filename, FALSE,
                      fci_get_next_cab, fci_status, fci_get_open_info, opt_compression );
    cab_free( path );
    return ret;
}
Beispiel #8
0
static UINT msi_change_media( MSIPACKAGE *package, struct media_info *mi )
{
    LPSTR msg;
    LPWSTR error, error_dialog;
    LPWSTR source_dir;
    UINT r = ERROR_SUCCESS;

    static const WCHAR szUILevel[] = {'U','I','L','e','v','e','l',0};
    static const WCHAR error_prop[] = {'E','r','r','o','r','D','i','a','l','o','g',0};

    if ( (msi_get_property_int(package, szUILevel, 0) & INSTALLUILEVEL_MASK) == INSTALLUILEVEL_NONE && !gUIHandlerA )
        return ERROR_SUCCESS;

    error = generate_error_string( package, 1302, 1, mi->disk_prompt );
    error_dialog = msi_dup_property( package, error_prop );
    source_dir = msi_dup_property( package, cszSourceDir );
    PathStripToRootW(source_dir);

    while ( r == ERROR_SUCCESS &&
            !source_matches_volume(mi, source_dir) )
    {
        r = msi_spawn_error_dialog( package, error_dialog, error );

        if (gUIHandlerA)
        {
            msg = strdupWtoA( error );
            gUIHandlerA( gUIContext, MB_RETRYCANCEL | INSTALLMESSAGE_ERROR, msg );
            msi_free(msg);
        }
    }

    msi_free( error );
    msi_free( error_dialog );
    msi_free( source_dir );

    return r;
}
Beispiel #9
0
/***********************************************************************
 * msidbImportTables
 *
 * Takes a list of tables or '*' (for all) to import from text archive
 * files in specified folder
 *
 * For each table, a file called <tablename>.idt is imported containing
 * tab separated ASCII.
 *
 * Examples (note wildcard escape for *nix/bash):
 * msidb -d <pathtomsi>.msi -f <workdir> -i \*
 * msidb -d <pathtomsi>.msi -f <workdir> -i File Directory Binary
 **********************************************************************/
static BOOL msidbImportTables(LPCWSTR dbfile, LPCWSTR wdir, LPWSTR tables[], BOOL create)
{
    static const WCHAR ext[] = {'.', 'i', 'd', 't', 0};
    static const WCHAR all[] = {'*', 0};

    UINT r, len;
    char *dirNameA;
    char *fileName;
    DIR *dir;
    struct dirent *ent;

    int i = 0;
    MSIHANDLE dbhandle;

    LPWSTR tableFile = 0;
    LPCWSTR oFlag = (LPCWSTR) MSIDBOPEN_TRANSACT;

    if (create == TRUE) oFlag = (LPCWSTR) MSIDBOPEN_CREATE;
    r = MsiOpenDatabaseW(dbfile, oFlag, &dbhandle);

    if (r != ERROR_SUCCESS)
    {
        return FALSE;
    }

    if (strcmpW(tables[0], all) == 0)
    {
        dirNameA = strdupWtoA(CP_ACP, wdir);
        dir = opendir(dirNameA);

        if (dir)
        {
            while ((ent = readdir(dir)) != NULL)
            {
                if (ent->d_type != DT_REG) continue;
                fileName = ent->d_name;
                if (strcmp(fileName+strlen(fileName)-4*sizeof(fileName[0]), ".idt") != 0) continue;
                if (strcmp(fileName, ".") == 0 || strcmp(fileName, "..") == 0) continue;
                tableFile = strdupAtoW(CP_ACP, fileName);
                r = MsiDatabaseImportW(dbhandle, wdir, tableFile);
                free(tableFile);
            }
        }
        else
            return FALSE;
        closedir(dir);
        free(dirNameA);
    }
    else
    {
        for (i = 0; i < MAX_TABLES && tables[i] != 0; ++i)
        {
            len = lstrlenW(tables[i]) + 5;
            tableFile = malloc(len * sizeof (WCHAR));
            if (tableFile == NULL) return FALSE;

            lstrcpyW(tableFile, tables[i]);
            lstrcatW(tableFile, ext);
            r = MsiDatabaseImportW(dbhandle, wdir, tableFile);
            free(tableFile);

            if (r != ERROR_SUCCESS)
            {
                return FALSE;
            }
        }
    }

    MsiDatabaseCommit(dbhandle);
    MsiCloseHandle(dbhandle);
    return TRUE;
}
Beispiel #10
0
int wmain( int argc, WCHAR *argv[] )
{
    static const WCHAR noneW[] = {'n','o','n','e',0};
    static const WCHAR mszipW[] = {'m','s','z','i','p',0};

    WCHAR *p, *command;
    char buffer[MAX_PATH];
    char filename[MAX_PATH];
    char *cab_file, *file_part;
    int i;

    while (argv[1] && argv[1][0] == '-')
    {
        switch (argv[1][1])
        {
        case 'd':
            argv++; argc--;
            opt_cabinet_size = atoiW( argv[1] );
            if (opt_cabinet_size < 50000)
            {
                WINE_MESSAGE( "cabarc: Cabinet size must be at least 50000\n" );
                return 1;
            }
            break;
        case 'h':
            usage();
            return 0;
        case 'i':
            argv++; argc--;
            opt_cabinet_id = atoiW( argv[1] );
            break;
        case 'm':
            argv++; argc--;
            if (!strcmpiW( argv[1], noneW )) opt_compression = tcompTYPE_NONE;
            else if (!strcmpiW( argv[1], mszipW )) opt_compression = tcompTYPE_MSZIP;
            else
            {
                WINE_MESSAGE( "cabarc: Unknown compression type '%s'\n", optarg );
                return 1;
            }
            break;
        case 'p':
            opt_preserve_paths = 1;
            break;
        case 'r':
            opt_recurse = 1;
            break;
        case 's':
            argv++; argc--;
            opt_reserve_space = atoiW( argv[1] );
            break;
        case 'v':
            opt_verbose++;
            break;
        default:
            usage();
            return 1;
        }
        argv++; argc--;
    }

    command = argv[1];
    if (argc < 3 || !command[0] || command[1])
    {
        usage();
        return 1;
    }
    cab_file = strdupWtoA( CP_ACP, argv[2] );
    argv += 2;
    argc -= 2;

    if (!GetFullPathNameA( cab_file, MAX_PATH, buffer, &file_part ) || !file_part)
    {
        WINE_ERR( "cannot get full name for %s\n", wine_dbgstr_a( cab_file ));
        return 1;
    }
    strcpy(filename, file_part);
    file_part[0] = 0;

    /* map slash to backslash in all file arguments */
    for (i = 1; i < argc; i++)
        for (p = argv[i]; *p; p++)
            if (*p == '/') *p = '\\';
    opt_files = argv + 1;
    opt_cab_file = filename;

    switch (*command)
    {
    case 'l':
    case 'L':
        return list_cabinet( buffer );
    case 'n':
    case 'N':
        return new_cabinet( buffer );
    case 'x':
    case 'X':
        if (argc > 1)  /* check for destination dir as last argument */
        {
            WCHAR *last = argv[argc - 1];
            if (last[0] && last[strlenW(last) - 1] == '\\')
            {
                opt_dest_dir = last;
                argv[--argc] = NULL;
            }
        }
        WINE_TRACE("Extracting file(s) from cabinet %s\n", wine_dbgstr_a(cab_file));
        return extract_cabinet( buffer );
    default:
        usage();
        return 1;
    }
}
Beispiel #11
0
static INT_PTR CDECL extract_notify( FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin )
{
    WCHAR *file, *nameW, *path = NULL;
    INT_PTR ret;

    switch (fdint)
    {
    case fdintCABINET_INFO:
        return 0;

    case fdintCOPY_FILE:
        nameW = strdupAtoW( (pfdin->attribs & _A_NAME_IS_UTF) ? CP_UTF8 : CP_ACP, pfdin->psz1 );
        if (opt_preserve_paths)
        {
            file = nameW;
            while (*file == '\\') file++;  /* remove leading backslashes */
        }
        else
        {
            if ((file = strrchrW( nameW, '\\' ))) file++;
            else file = nameW;
        }

        if (opt_dest_dir)
        {
            path = cab_alloc( (strlenW(opt_dest_dir) + strlenW(file) + 1) * sizeof(WCHAR) );
            strcpyW( path, opt_dest_dir );
            strcatW( path, file );
        }
        else path = file;

        if (match_files( file ))
        {
            if (opt_verbose)
            {
                char *nameU = strdupWtoA( CP_UNIXCP, path );
                printf( "extracting %s\n", nameU );
                cab_free( nameU );
            }
            create_directories( path );
            /* FIXME: check for existing file and overwrite mode */
            ret = (INT_PTR)CreateFileW( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
                                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
        }
        else ret = 0;

        cab_free( nameW );
        if (path != file) cab_free( path );
        return ret;

    case fdintCLOSE_FILE_INFO:
        CloseHandle( (HANDLE)pfdin->hf );
        return 0;

    case fdintNEXT_CABINET:
        WINE_TRACE("Next cab: status %u, path '%s', file '%s'\n", pfdin->fdie, pfdin->psz3, pfdin->psz1);
        return pfdin->fdie == FDIERROR_NONE ? 0 : -1;

    case fdintENUMERATE:
        return 0;

    default:
        WINE_FIXME( "Unexpected notification type %d.\n", fdint );
        return 0;
    }
}