/*++ 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 #include #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; }