files.c
来自「一个类似windows」· C语言 代码 · 共 888 行 · 第 1/2 页
C
888 行
static UINT ready_media_for_file( MSIPACKAGE *package, struct media_info *mi,
MSIFILE *file )
{
UINT rc = ERROR_SUCCESS;
MSIRECORD * row = 0;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
'`','M','e','d','i','a','`',' ','W','H','E','R','E',' ',
'`','L','a','s','t','S','e','q','u','e','n','c','e','`',' ','>','=',
' ','%', 'i',' ','O','R','D','E','R',' ','B','Y',' ',
'`','L','a','s','t','S','e','q','u','e','n','c','e','`',0};
LPCWSTR cab, volume;
DWORD sz;
INT seq;
UINT type;
LPCWSTR prompt;
MSICOMPONENT *comp = file->Component;
if (file->Sequence <= mi->last_sequence)
{
set_file_source(package,file,comp,mi->last_path);
TRACE("Media already ready (%u, %u)\n",file->Sequence,mi->last_sequence);
return ERROR_SUCCESS;
}
mi->count ++;
row = MSI_QueryGetRecord(package->db, ExecSeqQuery, file->Sequence);
if (!row)
{
TRACE("Unable to query row\n");
return ERROR_FUNCTION_FAILED;
}
seq = MSI_RecordGetInteger(row,2);
mi->last_sequence = seq;
volume = MSI_RecordGetString(row, 5);
prompt = MSI_RecordGetString(row, 3);
msi_free(mi->last_path);
mi->last_path = NULL;
if (file->Attributes & msidbFileAttributesNoncompressed)
{
mi->last_path = resolve_folder(package, comp->Directory, TRUE, FALSE, NULL);
set_file_source(package,file,comp,mi->last_path);
rc = ready_volume(package, file->SourcePath, mi->last_volume, row,&type);
MsiSourceListAddMediaDiskW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, mi->count, volume,
prompt);
if (type == DRIVE_REMOVABLE || type == DRIVE_CDROM ||
type == DRIVE_RAMDISK)
MsiSourceListSetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT|MSISOURCETYPE_MEDIA,
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->last_path);
else
MsiSourceListSetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->last_path);
msiobj_release(&row->hdr);
return rc;
}
cab = MSI_RecordGetString(row,4);
if (cab)
{
TRACE("Source is CAB %s\n",debugstr_w(cab));
/* the stream does not contain the # character */
if (cab[0]=='#')
{
LPWSTR path;
writeout_cabinet_stream(package,&cab[1],mi->source);
mi->last_path = strdupW(mi->source);
*(strrchrW(mi->last_path,'\\')+1)=0;
path = msi_dup_property( package, cszSourceDir );
MsiSourceListAddMediaDiskW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, mi->count,
volume, prompt);
MsiSourceListSetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
INSTALLPROPERTY_LASTUSEDSOURCEW, path);
msi_free(path);
}
else
{
sz = MAX_PATH;
mi->last_path = msi_alloc(MAX_PATH*sizeof(WCHAR));
if (MSI_GetPropertyW(package, cszSourceDir, mi->source, &sz))
{
ERR("No Source dir defined\n");
rc = ERROR_FUNCTION_FAILED;
}
else
{
strcpyW(mi->last_path,mi->source);
strcatW(mi->source,cab);
rc = ready_volume(package, mi->source, mi->last_volume, row, &type);
if (type == DRIVE_REMOVABLE || type == DRIVE_CDROM ||
type == DRIVE_RAMDISK)
MsiSourceListSetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT|MSISOURCETYPE_MEDIA,
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->last_path);
else
MsiSourceListSetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->last_path);
/* extract the cab file into a folder in the temp folder */
sz = MAX_PATH;
if (MSI_GetPropertyW(package, cszTempFolder,mi->last_path, &sz)
!= ERROR_SUCCESS)
GetTempPathW(MAX_PATH,mi->last_path);
}
}
rc = !extract_cabinet_file(package, mi->source, mi->last_path);
}
else
{
sz = MAX_PATH;
mi->last_path = msi_alloc(MAX_PATH*sizeof(WCHAR));
MSI_GetPropertyW(package,cszSourceDir,mi->source,&sz);
strcpyW(mi->last_path,mi->source);
rc = ready_volume(package, mi->last_path, mi->last_volume, row, &type);
if (type == DRIVE_REMOVABLE || type == DRIVE_CDROM ||
type == DRIVE_RAMDISK)
MsiSourceListSetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT|MSISOURCETYPE_MEDIA,
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->last_path);
else
MsiSourceListSetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT|MSISOURCETYPE_NETWORK,
INSTALLPROPERTY_LASTUSEDSOURCEW, mi->last_path);
}
set_file_source(package, file, comp, mi->last_path);
MsiSourceListAddMediaDiskW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED, MSICODE_PRODUCT, mi->count, volume,
prompt);
msiobj_release(&row->hdr);
return rc;
}
static UINT get_file_target(MSIPACKAGE *package, LPCWSTR file_key,
LPWSTR* file_source)
{
MSIFILE *file;
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{
if (lstrcmpW( file_key, file->File )==0)
{
if (file->state >= msifs_overwrite)
{
*file_source = strdupW( file->TargetPath );
return ERROR_SUCCESS;
}
else
return ERROR_FILE_NOT_FOUND;
}
}
return ERROR_FUNCTION_FAILED;
}
/*
* ACTION_InstallFiles()
*
* For efficiency, this is done in two passes:
* 1) Correct all the TargetPaths and determine what files are to be installed.
* 2) Extract Cabinets and copy files.
*/
UINT ACTION_InstallFiles(MSIPACKAGE *package)
{
struct media_info *mi;
UINT rc = ERROR_SUCCESS;
LPWSTR ptr;
MSIFILE *file;
/* increment progress bar each time action data is sent */
ui_progress(package,1,1,0,0);
/* handle the keys for the SourceList */
ptr = strrchrW(package->PackagePath,'\\');
if (ptr)
{
ptr ++;
MsiSourceListSetInfoW(package->ProductCode, NULL,
MSIINSTALLCONTEXT_USERMANAGED,
MSICODE_PRODUCT,
INSTALLPROPERTY_PACKAGENAMEW, ptr);
}
/* FIXME("Write DiskPrompt\n"); */
/* Pass 1 */
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{
if (!ACTION_VerifyComponentForAction( file->Component, INSTALLSTATE_LOCAL ))
{
ui_progress(package,2,file->FileSize,0,0);
TRACE("File %s is not scheduled for install\n",
debugstr_w(file->File));
file->state = msifs_skipped;
}
}
/*
* Despite MSDN specifying that the CreateFolders action
* should be called before InstallFiles, some installers don't
* do that, and they seem to work correctly. We need to create
* directories here to make sure that the files can be copied.
*/
msi_create_component_directories( package );
mi = create_media_info();
/* Pass 2 */
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{
if (file->state != msifs_missing && file->state != msifs_overwrite)
continue;
TRACE("Pass 2: %s\n",debugstr_w(file->File));
rc = ready_media_for_file( package, mi, file );
if (rc != ERROR_SUCCESS)
{
ERR("Unable to ready media\n");
rc = ERROR_FUNCTION_FAILED;
break;
}
TRACE("file paths %s to %s\n",debugstr_w(file->SourcePath),
debugstr_w(file->TargetPath));
if (file->state != msifs_missing && file->state != msifs_overwrite)
continue;
/* compressed files are extracted in ready_media_for_file */
if (~file->Attributes & msidbFileAttributesNoncompressed)
{
if (INVALID_FILE_ATTRIBUTES == GetFileAttributesW(file->TargetPath))
ERR("compressed file wasn't extracted (%s)\n",
debugstr_w(file->TargetPath));
continue;
}
rc = CopyFileW(file->SourcePath,file->TargetPath,FALSE);
if (!rc)
{
rc = GetLastError();
ERR("Unable to copy file (%s -> %s) (error %d)\n",
debugstr_w(file->SourcePath), debugstr_w(file->TargetPath), rc);
if (rc == ERROR_ALREADY_EXISTS && file->state == msifs_overwrite)
{
rc = 0;
}
else if (rc == ERROR_FILE_NOT_FOUND)
{
ERR("Source File Not Found! Continuing\n");
rc = 0;
}
else if (file->Attributes & msidbFileAttributesVital)
{
ERR("Ignoring Error and continuing (nonvital file)...\n");
rc = 0;
}
}
else
{
file->state = msifs_installed;
rc = ERROR_SUCCESS;
}
}
/* cleanup */
free_media_info( mi );
return rc;
}
static UINT ITERATE_DuplicateFiles(MSIRECORD *row, LPVOID param)
{
MSIPACKAGE *package = (MSIPACKAGE*)param;
WCHAR *file_source = NULL;
WCHAR dest_name[0x100];
LPWSTR dest_path, dest;
LPCWSTR file_key, component;
DWORD sz;
DWORD rc;
MSICOMPONENT *comp;
component = MSI_RecordGetString(row,2);
comp = get_loaded_component(package,component);
if (!ACTION_VerifyComponentForAction( comp, INSTALLSTATE_LOCAL ))
{
TRACE("Skipping copy due to disabled component %s\n",
debugstr_w(component));
/* the action taken was the same as the current install state */
comp->Action = comp->Installed;
return ERROR_SUCCESS;
}
comp->Action = INSTALLSTATE_LOCAL;
file_key = MSI_RecordGetString(row,3);
if (!file_key)
{
ERR("Unable to get file key\n");
return ERROR_FUNCTION_FAILED;
}
rc = get_file_target(package,file_key,&file_source);
if (rc != ERROR_SUCCESS)
{
ERR("Original file unknown %s\n",debugstr_w(file_key));
msi_free(file_source);
return ERROR_SUCCESS;
}
if (MSI_RecordIsNull(row,4))
strcpyW(dest_name,strrchrW(file_source,'\\')+1);
else
{
sz=0x100;
MSI_RecordGetStringW(row,4,dest_name,&sz);
reduce_to_longfilename(dest_name);
}
if (MSI_RecordIsNull(row,5))
{
LPWSTR p;
dest_path = strdupW(file_source);
p = strrchrW(dest_path,'\\');
if (p)
*p=0;
}
else
{
LPCWSTR destkey;
destkey = MSI_RecordGetString(row,5);
dest_path = resolve_folder(package, destkey, FALSE,FALSE,NULL);
if (!dest_path)
{
/* try a Property */
dest_path = msi_dup_property( package, destkey );
if (!dest_path)
{
FIXME("Unable to get destination folder, try AppSearch properties\n");
msi_free(file_source);
return ERROR_SUCCESS;
}
}
}
dest = build_directory_name(2, dest_path, dest_name);
TRACE("Duplicating file %s to %s\n",debugstr_w(file_source),
debugstr_w(dest));
if (strcmpW(file_source,dest))
rc = !CopyFileW(file_source,dest,TRUE);
else
rc = ERROR_SUCCESS;
if (rc != ERROR_SUCCESS)
ERR("Failed to copy file %s -> %s, last error %ld\n",
debugstr_w(file_source), debugstr_w(dest_path), GetLastError());
FIXME("We should track these duplicate files as well\n");
msi_free(dest_path);
msi_free(dest);
msi_free(file_source);
return ERROR_SUCCESS;
}
UINT ACTION_DuplicateFiles(MSIPACKAGE *package)
{
UINT rc;
MSIQUERY * view;
static const WCHAR ExecSeqQuery[] =
{'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
'`','D','u','p','l','i','c','a','t','e','F','i','l','e','`',0};
rc = MSI_DatabaseOpenViewW(package->db, ExecSeqQuery, &view);
if (rc != ERROR_SUCCESS)
return ERROR_SUCCESS;
rc = MSI_IterateRecords(view, NULL, ITERATE_DuplicateFiles, package);
msiobj_release(&view->hdr);
return rc;
}
UINT ACTION_RemoveFiles( MSIPACKAGE *package )
{
MSIFILE *file;
LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
{
if ( !file->Component )
continue;
if ( file->Component->Installed == INSTALLSTATE_LOCAL )
continue;
if ( file->state == msifs_installed )
ERR("removing installed file %s\n", debugstr_w(file->TargetPath));
if ( file->state != msifs_present )
continue;
TRACE("removing %s\n", debugstr_w(file->File) );
if ( !DeleteFileW( file->TargetPath ) )
ERR("failed to delete %s\n", debugstr_w(file->TargetPath) );
file->state = msifs_missing;
}
return ERROR_SUCCESS;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?