msi: Add initial implementation of MsiPublishAssemblies.
This commit is contained in:
parent
e487b1e213
commit
bfe07d1d07
|
@ -33,6 +33,10 @@
|
||||||
#include "msipriv.h"
|
#include "msipriv.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "shlobj.h"
|
#include "shlobj.h"
|
||||||
|
#include "objbase.h"
|
||||||
|
#include "mscoree.h"
|
||||||
|
#include "fusion.h"
|
||||||
|
#include "shlwapi.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "winver.h"
|
#include "winver.h"
|
||||||
|
|
||||||
|
@ -1246,6 +1250,9 @@ static MSIFEATURE *find_feature_by_name( MSIPACKAGE *package, LPCWSTR name )
|
||||||
{
|
{
|
||||||
MSIFEATURE *feature;
|
MSIFEATURE *feature;
|
||||||
|
|
||||||
|
if ( !name )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
LIST_FOR_EACH_ENTRY( feature, &package->features, MSIFEATURE, entry )
|
||||||
{
|
{
|
||||||
if ( !lstrcmpW( feature->Feature, name ) )
|
if ( !lstrcmpW( feature->Feature, name ) )
|
||||||
|
@ -5542,6 +5549,154 @@ static UINT ACTION_MoveFiles( MSIPACKAGE *package )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT (WINAPI *pCreateAssemblyCache)(IAssemblyCache **ppAsmCache,
|
||||||
|
DWORD dwReserved);
|
||||||
|
static HRESULT (WINAPI *pLoadLibraryShim)(LPCWSTR szDllName, LPCWSTR szVersion,
|
||||||
|
LPVOID pvReserved, HMODULE *phModDll);
|
||||||
|
|
||||||
|
static BOOL init_functionpointers(void)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
HMODULE hfusion;
|
||||||
|
HMODULE hmscoree;
|
||||||
|
|
||||||
|
static const WCHAR szFusion[] = {'f','u','s','i','o','n','.','d','l','l',0};
|
||||||
|
|
||||||
|
hmscoree = LoadLibraryA("mscoree.dll");
|
||||||
|
if (!hmscoree)
|
||||||
|
{
|
||||||
|
WARN("mscoree.dll not available\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pLoadLibraryShim = (void *)GetProcAddress(hmscoree, "LoadLibraryShim");
|
||||||
|
if (!pLoadLibraryShim)
|
||||||
|
{
|
||||||
|
WARN("LoadLibraryShim not available\n");
|
||||||
|
FreeLibrary(hmscoree);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = pLoadLibraryShim(szFusion, NULL, NULL, &hfusion);
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
WARN("fusion.dll not available\n");
|
||||||
|
FreeLibrary(hmscoree);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCreateAssemblyCache = (void *)GetProcAddress(hfusion, "CreateAssemblyCache");
|
||||||
|
|
||||||
|
FreeLibrary(hmscoree);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT install_assembly(LPWSTR path)
|
||||||
|
{
|
||||||
|
IAssemblyCache *cache;
|
||||||
|
HRESULT hr;
|
||||||
|
UINT r = ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
if (!init_functionpointers() || !pCreateAssemblyCache)
|
||||||
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
|
hr = pCreateAssemblyCache(&cache, 0);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
hr = IAssemblyCache_InstallAssembly(cache, 0, path, NULL);
|
||||||
|
if (FAILED(hr))
|
||||||
|
ERR("Failed to install assembly: %s %08x\n", debugstr_w(path), hr);
|
||||||
|
|
||||||
|
r = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
done:
|
||||||
|
IAssemblyCache_Release(cache);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT ITERATE_PublishAssembly( MSIRECORD *rec, LPVOID param )
|
||||||
|
{
|
||||||
|
MSIPACKAGE *package = param;
|
||||||
|
MSICOMPONENT *comp;
|
||||||
|
MSIFEATURE *feature;
|
||||||
|
MSIFILE *file;
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
LPCWSTR app;
|
||||||
|
DWORD attr;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
|
comp = get_loaded_component(package, MSI_RecordGetString(rec, 1));
|
||||||
|
if (!comp || !comp->Enabled ||
|
||||||
|
!(comp->Action & (INSTALLSTATE_LOCAL | INSTALLSTATE_SOURCE)))
|
||||||
|
{
|
||||||
|
ERR("Component not set for install, not publishing assembly\n");
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
feature = find_feature_by_name(package, MSI_RecordGetString(rec, 2));
|
||||||
|
if (feature)
|
||||||
|
msi_feature_set_state(feature, INSTALLSTATE_LOCAL);
|
||||||
|
|
||||||
|
if (MSI_RecordGetString(rec, 3))
|
||||||
|
FIXME("Manifest unhandled\n");
|
||||||
|
|
||||||
|
app = MSI_RecordGetString(rec, 4);
|
||||||
|
if (app)
|
||||||
|
{
|
||||||
|
FIXME("Assembly should be privately installed\n");
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr = MSI_RecordGetInteger(rec, 5);
|
||||||
|
if (attr == msidbAssemblyAttributesWin32)
|
||||||
|
{
|
||||||
|
FIXME("Win32 assemblies not handled\n");
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: extract all files belonging to this component */
|
||||||
|
file = msi_find_file(package, comp->KeyPath);
|
||||||
|
|
||||||
|
GetTempPathW(MAX_PATH, path);
|
||||||
|
r = msi_extract_file(package, file, path);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Failed to extract temporary assembly\n");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
PathAddBackslashW(path);
|
||||||
|
lstrcatW(path, file->FileName);
|
||||||
|
|
||||||
|
r = install_assembly(path);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
ERR("Failed to install assembly\n");
|
||||||
|
|
||||||
|
/* FIXME: write Installer assembly reg values */
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
|
||||||
|
{
|
||||||
|
UINT rc;
|
||||||
|
MSIQUERY *view;
|
||||||
|
|
||||||
|
static const WCHAR ExecSeqQuery[] =
|
||||||
|
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
|
||||||
|
'`','M','s','i','A','s','s','e','m','b','l','y','`',0};
|
||||||
|
|
||||||
|
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
rc = MSI_IterateRecords(view, NULL, ITERATE_PublishAssembly, package);
|
||||||
|
msiobj_release(&view->hdr);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
|
static UINT msi_unimplemented_action_stub( MSIPACKAGE *package,
|
||||||
LPCSTR action, LPCWSTR table )
|
LPCSTR action, LPCWSTR table )
|
||||||
{
|
{
|
||||||
|
@ -5630,13 +5785,6 @@ static UINT ACTION_RemoveEnvironmentStrings( MSIPACKAGE *package )
|
||||||
return msi_unimplemented_action_stub( package, "RemoveEnvironmentStrings", table );
|
return msi_unimplemented_action_stub( package, "RemoveEnvironmentStrings", table );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT ACTION_MsiPublishAssemblies( MSIPACKAGE *package )
|
|
||||||
{
|
|
||||||
static const WCHAR table[] = {
|
|
||||||
'M','s','i','A','s','s','e','m','b','l','y',0 };
|
|
||||||
return msi_unimplemented_action_stub( package, "MsiPublishAssemblies", table );
|
|
||||||
}
|
|
||||||
|
|
||||||
static UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
|
static UINT ACTION_MsiUnpublishAssemblies( MSIPACKAGE *package )
|
||||||
{
|
{
|
||||||
static const WCHAR table[] = {
|
static const WCHAR table[] = {
|
||||||
|
|
|
@ -57,20 +57,7 @@ extern const WCHAR szRemoveFiles[];
|
||||||
|
|
||||||
static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
|
static const WCHAR cszTempFolder[]= {'T','e','m','p','F','o','l','d','e','r',0};
|
||||||
|
|
||||||
struct media_info {
|
static BOOL source_matches_volume(MSIMEDIAINFO *mi, LPWSTR source_root)
|
||||||
UINT disk_id;
|
|
||||||
UINT type;
|
|
||||||
UINT last_sequence;
|
|
||||||
LPWSTR disk_prompt;
|
|
||||||
LPWSTR cabinet;
|
|
||||||
LPWSTR first_volume;
|
|
||||||
LPWSTR volume_label;
|
|
||||||
BOOL is_continuous;
|
|
||||||
BOOL is_extracted;
|
|
||||||
WCHAR source[MAX_PATH];
|
|
||||||
};
|
|
||||||
|
|
||||||
static BOOL source_matches_volume(struct media_info *mi, LPWSTR source_root)
|
|
||||||
{
|
{
|
||||||
WCHAR volume_name[MAX_PATH + 1];
|
WCHAR volume_name[MAX_PATH + 1];
|
||||||
|
|
||||||
|
@ -84,7 +71,7 @@ static BOOL source_matches_volume(struct media_info *mi, LPWSTR source_root)
|
||||||
return !lstrcmpW(mi->volume_label, volume_name);
|
return !lstrcmpW(mi->volume_label, volume_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT msi_change_media( MSIPACKAGE *package, struct media_info *mi )
|
static UINT msi_change_media( MSIPACKAGE *package, MSIMEDIAINFO *mi )
|
||||||
{
|
{
|
||||||
LPSTR msg;
|
LPSTR msg;
|
||||||
LPWSTR error, error_dialog;
|
LPWSTR error, error_dialog;
|
||||||
|
@ -169,7 +156,7 @@ end:
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
MSIPACKAGE* package;
|
MSIPACKAGE* package;
|
||||||
struct media_info *mi;
|
MSIMEDIAINFO *mi;
|
||||||
} CabData;
|
} CabData;
|
||||||
|
|
||||||
static void * cabinet_alloc(ULONG cb)
|
static void * cabinet_alloc(ULONG cb)
|
||||||
|
@ -265,7 +252,7 @@ static void msi_file_update_ui( MSIPACKAGE *package, MSIFILE *f, const WCHAR *ac
|
||||||
ui_progress( package, 2, f->FileSize, 0, 0);
|
ui_progress( package, 2, f->FileSize, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT msi_media_get_disk_info( MSIPACKAGE *package, struct media_info *mi )
|
static UINT msi_media_get_disk_info( MSIPACKAGE *package, MSIMEDIAINFO *mi )
|
||||||
{
|
{
|
||||||
MSIRECORD *row;
|
MSIRECORD *row;
|
||||||
LPWSTR ptr;
|
LPWSTR ptr;
|
||||||
|
@ -311,7 +298,7 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
||||||
case fdintNEXT_CABINET:
|
case fdintNEXT_CABINET:
|
||||||
{
|
{
|
||||||
CabData *data = (CabData *)pfdin->pv;
|
CabData *data = (CabData *)pfdin->pv;
|
||||||
struct media_info *mi = data->mi;
|
MSIMEDIAINFO *mi = data->mi;
|
||||||
LPWSTR cab = strdupAtoW(pfdin->psz1);
|
LPWSTR cab = strdupAtoW(pfdin->psz1);
|
||||||
UINT rc;
|
UINT rc;
|
||||||
|
|
||||||
|
@ -423,18 +410,18 @@ static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* extract_cabinet_file
|
* msi_cabextract
|
||||||
*
|
*
|
||||||
* Extract files from a cab file.
|
* Extract files from a cab file.
|
||||||
*/
|
*/
|
||||||
static BOOL extract_cabinet_file(MSIPACKAGE* package, struct media_info *mi)
|
BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi,
|
||||||
|
PFNFDINOTIFY notify, LPVOID data)
|
||||||
{
|
{
|
||||||
LPSTR cabinet, cab_path = NULL;
|
LPSTR cabinet, cab_path = NULL;
|
||||||
LPWSTR ptr;
|
LPWSTR ptr;
|
||||||
HFDI hfdi;
|
HFDI hfdi;
|
||||||
ERF erf;
|
ERF erf;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
CabData data;
|
|
||||||
|
|
||||||
TRACE("Extracting %s\n", debugstr_w(mi->source));
|
TRACE("Extracting %s\n", debugstr_w(mi->source));
|
||||||
|
|
||||||
|
@ -457,10 +444,7 @@ static BOOL extract_cabinet_file(MSIPACKAGE* package, struct media_info *mi)
|
||||||
|
|
||||||
cab_path[ptr - mi->source] = '\0';
|
cab_path[ptr - mi->source] = '\0';
|
||||||
|
|
||||||
data.package = package;
|
ret = FDICopy(hfdi, cabinet, cab_path, 0, notify, NULL, data);
|
||||||
data.mi = mi;
|
|
||||||
|
|
||||||
ret = FDICopy(hfdi, cabinet, cab_path, 0, cabinet_notify, NULL, &data);
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ERR("FDICopy failed\n");
|
ERR("FDICopy failed\n");
|
||||||
|
|
||||||
|
@ -495,7 +479,7 @@ static VOID set_file_source(MSIPACKAGE* package, MSIFILE* file, LPCWSTR path)
|
||||||
file->SourcePath = build_directory_name(2, path, file->File);
|
file->SourcePath = build_directory_name(2, path, file->File);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_media_info( struct media_info *mi )
|
void msi_free_media_info( MSIMEDIAINFO *mi )
|
||||||
{
|
{
|
||||||
msi_free( mi->disk_prompt );
|
msi_free( mi->disk_prompt );
|
||||||
msi_free( mi->cabinet );
|
msi_free( mi->cabinet );
|
||||||
|
@ -504,7 +488,7 @@ static void free_media_info( struct media_info *mi )
|
||||||
msi_free( mi );
|
msi_free( mi );
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_info *mi)
|
UINT msi_load_media_info(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
|
||||||
{
|
{
|
||||||
MSIRECORD *row;
|
MSIRECORD *row;
|
||||||
LPWSTR source_dir;
|
LPWSTR source_dir;
|
||||||
|
@ -593,7 +577,7 @@ static UINT load_media_info(MSIPACKAGE *package, MSIFILE *file, struct media_inf
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: search NETWORK and URL sources as well */
|
/* FIXME: search NETWORK and URL sources as well */
|
||||||
static UINT find_published_source(MSIPACKAGE *package, struct media_info *mi)
|
static UINT find_published_source(MSIPACKAGE *package, MSIMEDIAINFO *mi)
|
||||||
{
|
{
|
||||||
WCHAR source[MAX_PATH];
|
WCHAR source[MAX_PATH];
|
||||||
WCHAR volume[MAX_PATH];
|
WCHAR volume[MAX_PATH];
|
||||||
|
@ -634,7 +618,7 @@ static UINT find_published_source(MSIPACKAGE *package, struct media_info *mi)
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *mi)
|
static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi)
|
||||||
{
|
{
|
||||||
UINT rc = ERROR_SUCCESS;
|
UINT rc = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
@ -642,7 +626,7 @@ static UINT ready_media(MSIPACKAGE *package, MSIFILE *file, struct media_info *m
|
||||||
if (mi->is_continuous)
|
if (mi->is_continuous)
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
rc = load_media_info(package, file, mi);
|
rc = msi_load_media_info(package, file, mi);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("Unable to load media info\n");
|
ERR("Unable to load media info\n");
|
||||||
|
@ -808,7 +792,7 @@ static BOOL check_dest_hash_matches(MSIFILE *file)
|
||||||
*/
|
*/
|
||||||
UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
{
|
{
|
||||||
struct media_info *mi;
|
MSIMEDIAINFO *mi;
|
||||||
UINT rc = ERROR_SUCCESS;
|
UINT rc = ERROR_SUCCESS;
|
||||||
MSIFILE *file;
|
MSIFILE *file;
|
||||||
|
|
||||||
|
@ -825,7 +809,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
*/
|
*/
|
||||||
msi_create_component_directories( package );
|
msi_create_component_directories( package );
|
||||||
|
|
||||||
mi = msi_alloc_zero( sizeof(struct media_info) );
|
mi = msi_alloc_zero( sizeof(MSIMEDIAINFO) );
|
||||||
|
|
||||||
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
|
||||||
{
|
{
|
||||||
|
@ -841,6 +825,8 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
if (file->Sequence > mi->last_sequence || mi->is_continuous ||
|
if (file->Sequence > mi->last_sequence || mi->is_continuous ||
|
||||||
(file->IsCompressed && !mi->is_extracted))
|
(file->IsCompressed && !mi->is_extracted))
|
||||||
{
|
{
|
||||||
|
CabData data;
|
||||||
|
|
||||||
rc = ready_media(package, file, mi);
|
rc = ready_media(package, file, mi);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -848,7 +834,11 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->IsCompressed && !extract_cabinet_file(package, mi))
|
data.mi = mi;
|
||||||
|
data.package = package;
|
||||||
|
|
||||||
|
if (file->IsCompressed &&
|
||||||
|
!msi_cabextract(package, mi, cabinet_notify, &data))
|
||||||
{
|
{
|
||||||
ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
|
ERR("Failed to extract cabinet: %s\n", debugstr_w(mi->cabinet));
|
||||||
rc = ERROR_FUNCTION_FAILED;
|
rc = ERROR_FUNCTION_FAILED;
|
||||||
|
@ -881,7 +871,7 @@ UINT ACTION_InstallFiles(MSIPACKAGE *package)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_media_info( mi );
|
msi_free_media_info( mi );
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "msipriv.h"
|
#include "msipriv.h"
|
||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "shlwapi.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "msidefs.h"
|
#include "msidefs.h"
|
||||||
|
|
||||||
|
@ -1054,3 +1056,122 @@ void msi_ui_error( DWORD msg_id, DWORD type )
|
||||||
|
|
||||||
MessageBoxW( NULL, text, title, type );
|
MessageBoxW( NULL, text, title, type );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MSIPACKAGE *package;
|
||||||
|
MSIMEDIAINFO *mi;
|
||||||
|
MSIFILE *file;
|
||||||
|
LPWSTR destination;
|
||||||
|
} CabData;
|
||||||
|
|
||||||
|
static INT_PTR cabinet_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
||||||
|
{
|
||||||
|
TRACE("(%d)\n", fdint);
|
||||||
|
|
||||||
|
switch (fdint)
|
||||||
|
{
|
||||||
|
case fdintNEXT_CABINET:
|
||||||
|
{
|
||||||
|
ERR("continuous cabinets not handled\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case fdintCOPY_FILE:
|
||||||
|
{
|
||||||
|
CabData *data = (CabData*) pfdin->pv;
|
||||||
|
LPWSTR file, path;
|
||||||
|
DWORD attrs, size;
|
||||||
|
HANDLE handle;
|
||||||
|
MSIFILE *f;
|
||||||
|
|
||||||
|
file = strdupAtoW(pfdin->psz1);
|
||||||
|
f = get_loaded_file(data->package, file);
|
||||||
|
msi_free(file);
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
WARN("unknown file in cabinet (%s)\n",debugstr_a(pfdin->psz1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lstrcmpW(f->File, data->file->File))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size = lstrlenW(data->destination) + lstrlenW(file) + 2;
|
||||||
|
path = msi_alloc(size * sizeof(WCHAR));
|
||||||
|
lstrcpyW(path, data->destination);
|
||||||
|
PathAddBackslashW(path);
|
||||||
|
lstrcatW(path, data->file->FileName);
|
||||||
|
|
||||||
|
TRACE("extracting %s\n", debugstr_w(path));
|
||||||
|
|
||||||
|
attrs = f->Attributes & (FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
|
||||||
|
if (!attrs) attrs = FILE_ATTRIBUTE_NORMAL;
|
||||||
|
|
||||||
|
handle = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0,
|
||||||
|
NULL, CREATE_ALWAYS, attrs, NULL);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
|
||||||
|
ERR("failed to create %s (error %d)\n",
|
||||||
|
debugstr_w(path), GetLastError());
|
||||||
|
|
||||||
|
msi_free(path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
msi_free(path);
|
||||||
|
return (INT_PTR)handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
case fdintCLOSE_FILE_INFO:
|
||||||
|
{
|
||||||
|
FILETIME ft;
|
||||||
|
FILETIME ftLocal;
|
||||||
|
HANDLE handle = (HANDLE)pfdin->hf;
|
||||||
|
|
||||||
|
if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
|
||||||
|
return -1;
|
||||||
|
if (!LocalFileTimeToFileTime(&ft, &ftLocal))
|
||||||
|
return -1;
|
||||||
|
if (!SetFileTime(handle, &ftLocal, 0, &ftLocal))
|
||||||
|
return -1;
|
||||||
|
CloseHandle(handle);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT msi_extract_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR destdir)
|
||||||
|
{
|
||||||
|
MSIMEDIAINFO *mi;
|
||||||
|
CabData data;
|
||||||
|
UINT r;
|
||||||
|
|
||||||
|
mi = msi_alloc_zero(sizeof(MSIMEDIAINFO));
|
||||||
|
if (!mi)
|
||||||
|
return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
|
r = msi_load_media_info(package, file, mi);
|
||||||
|
if (r != ERROR_SUCCESS)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
data.package = package;
|
||||||
|
data.mi = mi;
|
||||||
|
data.file = file;
|
||||||
|
data.destination = destdir;
|
||||||
|
|
||||||
|
if (!msi_cabextract(package, mi, cabinet_notify, &data))
|
||||||
|
{
|
||||||
|
ERR("Failed to extract cabinet file\n");
|
||||||
|
r = ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
msi_free_media_info(mi);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
|
#include "fdi.h"
|
||||||
#include "msi.h"
|
#include "msi.h"
|
||||||
#include "msiquery.h"
|
#include "msiquery.h"
|
||||||
#include "objbase.h"
|
#include "objbase.h"
|
||||||
|
@ -133,6 +134,20 @@ typedef struct tagMSIMEDIADISK
|
||||||
LPWSTR disk_prompt;
|
LPWSTR disk_prompt;
|
||||||
} MSIMEDIADISK;
|
} MSIMEDIADISK;
|
||||||
|
|
||||||
|
typedef struct tagMSIMEDIAINFO
|
||||||
|
{
|
||||||
|
UINT disk_id;
|
||||||
|
UINT type;
|
||||||
|
UINT last_sequence;
|
||||||
|
LPWSTR disk_prompt;
|
||||||
|
LPWSTR cabinet;
|
||||||
|
LPWSTR first_volume;
|
||||||
|
LPWSTR volume_label;
|
||||||
|
BOOL is_continuous;
|
||||||
|
BOOL is_extracted;
|
||||||
|
WCHAR source[MAX_PATH];
|
||||||
|
} MSIMEDIAINFO;
|
||||||
|
|
||||||
typedef struct _column_info
|
typedef struct _column_info
|
||||||
{
|
{
|
||||||
LPCWSTR table;
|
LPCWSTR table;
|
||||||
|
@ -889,6 +904,10 @@ extern UINT msi_create_component_directories( MSIPACKAGE *package );
|
||||||
extern void msi_ui_error( DWORD msg_id, DWORD type );
|
extern void msi_ui_error( DWORD msg_id, DWORD type );
|
||||||
extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
|
extern UINT msi_set_last_used_source(LPCWSTR product, LPCWSTR usersid,
|
||||||
MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value);
|
MSIINSTALLCONTEXT context, DWORD options, LPCWSTR value);
|
||||||
|
extern UINT msi_load_media_info(MSIPACKAGE *package, MSIFILE *file, MSIMEDIAINFO *mi);
|
||||||
|
extern void msi_free_media_info(MSIMEDIAINFO *mi);
|
||||||
|
extern BOOL msi_cabextract(MSIPACKAGE* package, MSIMEDIAINFO *mi, PFNFDINOTIFY notify, LPVOID data);
|
||||||
|
extern UINT msi_extract_file(MSIPACKAGE *package, MSIFILE *file, LPWSTR destdir);
|
||||||
|
|
||||||
/* control event stuff */
|
/* control event stuff */
|
||||||
extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
|
extern VOID ControlEvent_FireSubscribedEvent(MSIPACKAGE *package, LPCWSTR event,
|
||||||
|
|
|
@ -201,6 +201,12 @@ enum msidbMoveFileOptions
|
||||||
msidbMoveFileOptionsMove = 0x00000001,
|
msidbMoveFileOptionsMove = 0x00000001,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum msidbAssemblyAttributes
|
||||||
|
{
|
||||||
|
msidbAssemblyAttributesURT = 0x00000000,
|
||||||
|
msidbAssemblyAttributesWin32 = 0x00000001,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Windows SDK braindamage alert
|
* Windows SDK braindamage alert
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue