You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
322 lines
6.9 KiB
322 lines
6.9 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cabinet.cpp
|
|
|
|
Abstract:
|
|
|
|
cabinet management Function calls for msm generation
|
|
|
|
Author:
|
|
|
|
Xiaoyu Wu(xiaoyuw) 01-Aug-2001
|
|
|
|
--*/
|
|
|
|
#include "msmgen.h"
|
|
#include "util.h"
|
|
|
|
extern BOOL __stdcall SxspDeleteDirectory(const CBaseStringBuffer &rdir);
|
|
|
|
|
|
#include <fci.h>
|
|
#include <fdi.h>
|
|
|
|
#include "msmfci.h"
|
|
#include "msmfdi.h"
|
|
|
|
ERF erf;
|
|
//
|
|
// FCI
|
|
//
|
|
HRESULT InitializeCabinetForWrite()
|
|
{
|
|
HFCI hfci;
|
|
|
|
CCAB cab_parameters;
|
|
client_state cs;
|
|
HRESULT hr = S_OK;
|
|
|
|
// Initialise our internal state
|
|
cs.total_compressed_size = 0;
|
|
cs.total_uncompressed_size = 0;
|
|
|
|
set_cab_parameters(&cab_parameters);
|
|
|
|
hfci = FCICreate(
|
|
&erf,
|
|
file_placed,
|
|
fci_mem_alloc,
|
|
fci_mem_free,
|
|
fci_open,
|
|
fci_read,
|
|
fci_write,
|
|
fci_close,
|
|
fci_seek,
|
|
fci_delete,
|
|
get_temp_file,
|
|
&cab_parameters,
|
|
&cs
|
|
);
|
|
|
|
if (hfci == NULL)
|
|
{
|
|
printf("CAB: FCICreate() failed: code %d [%s]\n",
|
|
erf.erfOper, return_fci_error_string(erf.erfOper));
|
|
|
|
SETFAIL_AND_EXIT;
|
|
}else
|
|
{
|
|
g_MsmInfo.m_hfci = hfci;
|
|
hfci= NULL;
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT AddFileToCabinetW(PCWSTR full_filename, SIZE_T CchFullFileName, PCWSTR relative_filename, SIZE_T CchRelativePath)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CHAR pszpath[MAX_PATH];
|
|
CHAR pszfilename[MAX_PATH];
|
|
|
|
WideCharToMultiByte(
|
|
CP_ACP, 0, full_filename, (int)CchFullFileName,
|
|
pszpath, MAX_PATH, NULL, NULL);
|
|
pszpath[CchFullFileName] = '\0';
|
|
|
|
WideCharToMultiByte(
|
|
CP_ACP, 0, relative_filename, (int)CchRelativePath,
|
|
pszfilename, MAX_PATH, NULL, NULL);
|
|
pszfilename[CchRelativePath] = '\0';
|
|
|
|
if (FALSE == FCIAddFile(
|
|
g_MsmInfo.m_hfci,
|
|
pszpath, /* filename to add : fully qualified filename */
|
|
pszfilename, /* file name in cabinet file : relative filepath */
|
|
FALSE, /* file is not executable */
|
|
get_next_cabinet,
|
|
progress,
|
|
get_open_info,
|
|
COMPRESSION_TYPE))
|
|
{
|
|
fprintf(stderr, "adding file %s to the cabinet failed\n", pszpath);
|
|
SETFAIL_AND_EXIT;
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT AddFileToCabinetA(PCSTR full_filename, SIZE_T CchFullFileName, PCSTR relative_filename, SIZE_T CchRelativePath)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR szFullFilename[MAX_PATH];
|
|
WCHAR szRelativeFilename[MAX_PATH];
|
|
|
|
swprintf(szFullFilename, L"%S", full_filename);
|
|
swprintf(szRelativeFilename, L"%S", relative_filename);
|
|
|
|
IFFAILED_EXIT(AddFileToCabinetW(szFullFilename, CchFullFileName, szRelativeFilename, CchRelativePath));
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
HRESULT CloseCabinet()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CurrentAssemblyRealign;
|
|
|
|
if (FALSE == FCIFlushCabinet(
|
|
g_MsmInfo.m_hfci,
|
|
FALSE,
|
|
get_next_cabinet,
|
|
progress))
|
|
{
|
|
fprintf(stderr, "Flush Cabinet failed\n");
|
|
hr = HRESULT_FROM_WIN32(::GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
if (FCIDestroy(g_MsmInfo.m_hfci) != TRUE)
|
|
{
|
|
SETFAIL_AND_EXIT;
|
|
}
|
|
else
|
|
g_MsmInfo.m_hfci = NULL;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// FDI
|
|
//
|
|
HRESULT MoveFilesInCabinetA(char * sourceCabinet)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HFDI hfdi = NULL;
|
|
ERF erf;
|
|
FDICABINETINFO fdici;
|
|
INT_PTR hf = -1;
|
|
DWORD num;
|
|
extern char dest_dir[MAX_PATH];
|
|
|
|
hfdi = FDICreate(
|
|
fdi_mem_alloc,
|
|
fdi_mem_free,
|
|
fdi_file_open,
|
|
fdi_file_read,
|
|
fdi_file_write,
|
|
fdi_file_close,
|
|
fdi_file_seek,
|
|
cpu80386,
|
|
&erf
|
|
);
|
|
|
|
if (hfdi == NULL)
|
|
{
|
|
printf("FDICreate() failed: code %d [%s]\n",
|
|
erf.erfOper, return_fdi_error_string(erf.erfOper)
|
|
);
|
|
|
|
SETFAIL_AND_EXIT;
|
|
}
|
|
|
|
|
|
hf = fdi_file_open(
|
|
sourceCabinet,
|
|
_O_BINARY | _O_RDONLY | _O_SEQUENTIAL,
|
|
0
|
|
);
|
|
|
|
if (hf == -1)
|
|
{
|
|
printf("Unable to open '%s' for input\n", sourceCabinet);
|
|
SETFAIL_AND_EXIT;
|
|
}
|
|
|
|
if (FALSE == FDIIsCabinet(
|
|
hfdi,
|
|
hf,
|
|
&fdici))
|
|
{
|
|
/*
|
|
* It is not a cabinet!, BUT it must be since it is named as MergeModule.cab in a msm
|
|
*/
|
|
|
|
printf(
|
|
"FDIIsCabinet() failed: '%s' is not a cabinet\n",
|
|
sourceCabinet
|
|
);
|
|
|
|
SETFAIL_AND_EXIT;
|
|
}
|
|
else
|
|
{
|
|
_close((int)hf);
|
|
#ifdef MSMGEN_TEST
|
|
printf(
|
|
"Information on cabinet file '%s'\n"
|
|
" Total length of cabinet file : %d\n"
|
|
" Number of folders in cabinet : %d\n"
|
|
" Number of files in cabinet : %d\n"
|
|
" Cabinet set ID : %d\n"
|
|
" Cabinet number in set : %d\n"
|
|
" RESERVE area in cabinet? : %s\n"
|
|
" Chained to prev cabinet? : %s\n"
|
|
" Chained to next cabinet? : %s\n"
|
|
"\n",
|
|
sourceCabinet,
|
|
fdici.cbCabinet,
|
|
fdici.cFolders,
|
|
fdici.cFiles,
|
|
fdici.setID,
|
|
fdici.iCabinet,
|
|
fdici.fReserve == TRUE ? "yes" : "no",
|
|
fdici.hasprev == TRUE ? "yes" : "no",
|
|
fdici.hasnext == TRUE ? "yes" : "no"
|
|
);
|
|
#endif
|
|
if ((fdici.fReserve == TRUE)|| (fdici.hasprev == TRUE) || (fdici.hasnext == TRUE))
|
|
{
|
|
printf("ERROR file format : MSI 1.5 support one and only one cabinet in MergeModule.cab!\n");
|
|
SETFAIL_AND_EXIT;
|
|
}
|
|
}
|
|
|
|
//
|
|
// create a temporary directory for use
|
|
//
|
|
num = ExpandEnvironmentStringsA(MSM_TEMP_CABIN_DIRECTORY_A, dest_dir, NUMBER_OF(dest_dir));
|
|
if ( (num == 0) || (num > NUMBER_OF(dest_dir)))
|
|
SETFAIL_AND_EXIT;
|
|
|
|
DWORD dwAttribs = GetFileAttributesA(dest_dir);
|
|
if (dwAttribs != (DWORD)(-1))
|
|
{
|
|
if ((dwAttribs & FILE_ATTRIBUTE_DIRECTORY) == 0 )
|
|
SETFAIL_AND_EXIT;
|
|
|
|
CStringBuffer sb;
|
|
WCHAR wdir[MAX_PATH];
|
|
|
|
num = ExpandEnvironmentStringsW(MSM_TEMP_CABIN_DIRECTORY_W, wdir, NUMBER_OF(wdir));
|
|
if ( (num == 0) || (num > NUMBER_OF(wdir)))
|
|
SETFAIL_AND_EXIT;
|
|
|
|
IFFALSE_EXIT(sb.Win32Assign(wdir, wcslen(wdir)));
|
|
IFFALSE_EXIT(SxspDeleteDirectory(sb));
|
|
}
|
|
|
|
IFFALSE_EXIT(CreateDirectoryA(dest_dir, NULL));
|
|
char * p = NULL;
|
|
char sourceDir[MAX_PATH];
|
|
|
|
p = strrchr(sourceCabinet, '\\');
|
|
ASSERT_NTC(p != NULL);
|
|
p ++; // skip "\"
|
|
strncpy(sourceDir, sourceCabinet, p - sourceCabinet);
|
|
sourceDir[p - sourceCabinet] = '\0';
|
|
|
|
if (TRUE != FDICopy(
|
|
hfdi,
|
|
p,
|
|
sourceDir,
|
|
0,
|
|
fdi_notification_function,
|
|
NULL,
|
|
NULL))
|
|
{
|
|
printf(
|
|
"FDICopy() failed: code %d [%s]\n",
|
|
erf.erfOper, return_fdi_error_string(erf.erfOper)
|
|
);
|
|
|
|
(void) FDIDestroy(hfdi);
|
|
return FALSE;
|
|
}
|
|
|
|
if (FDIDestroy(hfdi) != TRUE)
|
|
{
|
|
printf(
|
|
"FDIDestroy() failed: code %d [%s]\n",
|
|
erf.erfOper, return_fdi_error_string(erf.erfOper)
|
|
);
|
|
|
|
return FALSE;
|
|
}
|
|
hfdi = NULL;
|
|
|
|
Exit:
|
|
if (hfdi != NULL)
|
|
(void) FDIDestroy(hfdi);
|
|
if ( hf != -1)
|
|
_close((int)hf);
|
|
|
|
return hr;
|
|
}
|