update all the functiosn now used in the msvc pack
This commit is contained in:
BIN
libexec/MsiX.exe
Executable file
BIN
libexec/MsiX.exe
Executable file
Binary file not shown.
534
libexec/MsiX/MsiX.cpp
Normal file
534
libexec/MsiX/MsiX.cpp
Normal file
@@ -0,0 +1,534 @@
|
||||
|
||||
#include "msix.h"
|
||||
#pragma comment(lib, "msi.lib")
|
||||
|
||||
// Entry point.
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
DWORD dwError = NOERROR;
|
||||
HRESULT hr = NOERROR;
|
||||
ARGS args = { 0 };
|
||||
IStorage* pRootStorage = NULL;
|
||||
IEnumSTATSTG* pEnum = NULL;
|
||||
LPCTSTR pszPersist = (LPTSTR)MSIDBOPEN_READONLY;
|
||||
STATSTG stg = { 0 };
|
||||
PMSIHANDLE hDatabase = NULL;
|
||||
PMSIHANDLE hView = NULL;
|
||||
PMSIHANDLE hRecord = NULL;
|
||||
|
||||
dwError = ParseArguments(argc, argv, &args);
|
||||
if (ERROR_SUCCESS != dwError)
|
||||
{
|
||||
return dwError;
|
||||
}
|
||||
|
||||
// Open the root storage file and extract storages first. Storages cannot
|
||||
// be extracted using MSI APIs so we must use the compound file implementation
|
||||
// for IStorage.
|
||||
hr = StgOpenStorage(
|
||||
CT2W(args.Path),
|
||||
NULL,
|
||||
STGM_READ | STGM_SHARE_EXCLUSIVE,
|
||||
NULL,
|
||||
0,
|
||||
&pRootStorage);
|
||||
if (SUCCEEDED(hr) && pRootStorage)
|
||||
{
|
||||
// Determine if the file path specifies an MSP file.
|
||||
// This will be used later to open the database with MSI APIs.
|
||||
if (IsPatch(pRootStorage))
|
||||
{
|
||||
pszPersist = MSIDBOPEN_READONLY + MSIDBOPEN_PATCHFILE;
|
||||
}
|
||||
|
||||
hr = pRootStorage->EnumElements(0, NULL, 0, &pEnum);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
while (S_OK == (hr = pEnum->Next(1, &stg, NULL)))
|
||||
{
|
||||
if (STGTY_STORAGE == stg.type)
|
||||
{
|
||||
hr = SaveStorage(pRootStorage, args.Directory, stg.pwcsName,
|
||||
args.IncludeExtension ? TEXT(".mst") : NULL);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_RELEASE(pEnum);
|
||||
}
|
||||
}
|
||||
SAFE_RELEASE(pRootStorage);
|
||||
|
||||
// Now open the database using MSI APIs. Patches cannot be opened simultaneously
|
||||
// since exclusive access is required and no MSI APIs are exported that accept
|
||||
// an IStorage pointer.
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
dwError = MsiOpenDatabase(args.Path, pszPersist, &hDatabase);
|
||||
if (ERROR_SUCCESS == dwError)
|
||||
{
|
||||
dwError = MsiDatabaseOpenView(hDatabase,
|
||||
TEXT("SELECT `Name`, `Data` FROM `_Streams`"), &hView);
|
||||
if (ERROR_SUCCESS == dwError)
|
||||
{
|
||||
dwError = MsiViewExecute(hView, NULL);
|
||||
if (ERROR_SUCCESS == dwError)
|
||||
{
|
||||
while (ERROR_SUCCESS == (dwError = MsiViewFetch(hView, &hRecord)))
|
||||
{
|
||||
dwError = SaveStream(hRecord, args.Directory, args.IncludeExtension);
|
||||
if (ERROR_SUCCESS != dwError)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no more records indicate success.
|
||||
if (ERROR_NO_MORE_ITEMS == dwError)
|
||||
{
|
||||
dwError = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If a Win32 error has occurred return only the win32 error portion.
|
||||
if (FACILITY_WIN32 == HRESULT_FACILITY(hr))
|
||||
{
|
||||
dwError = HRESULT_CODE(hr);
|
||||
}
|
||||
else if (FAILED(hr))
|
||||
{
|
||||
// Just set it to the HRESULT. Many common HRESULTs
|
||||
// will yield an error string from FormatMessage.
|
||||
dwError = hr;
|
||||
}
|
||||
|
||||
// Print the error to the console.
|
||||
if (ERROR_SUCCESS != dwError)
|
||||
{
|
||||
win32_error(dwError);
|
||||
}
|
||||
|
||||
return dwError;
|
||||
}
|
||||
|
||||
// Parse the file path, and optionally output directory and extension guessing switch.
|
||||
DWORD ParseArguments(int argc, [Pre(Null=No)] _TCHAR* argv[], [Pre(Null=No)] LPARGS args)
|
||||
{
|
||||
_ASSERTE(argv);
|
||||
_ASSERTE(args);
|
||||
|
||||
int iParamIndex = 1;
|
||||
|
||||
// Validate arguments.
|
||||
if (2 > argc)
|
||||
{
|
||||
error(TEXT("Error: you must specify a Windows Installer file from which to extract files.\n"));
|
||||
usage(argv[0], stderr);
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (0 == _tcsicmp(TEXT("/?"), argv[iParamIndex]) || 0 == _tcsicmp(TEXT("-?"), argv[iParamIndex]))
|
||||
{
|
||||
// Display the usage text.
|
||||
usage(argv[0], stdout);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
else if (TEXT('/') == argv[iParamIndex][0] || TEXT('-') == argv[iParamIndex][0])
|
||||
{
|
||||
// Filename should not begin with a command-switch character.
|
||||
error(TEXT("Error: invalid file name.\n"));
|
||||
usage(argv[0], stderr);
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the path argument.
|
||||
args->Path = const_cast<LPTSTR>(argv[iParamIndex]);
|
||||
}
|
||||
|
||||
// Get the output directory if requested.
|
||||
while (++iParamIndex < argc)
|
||||
{
|
||||
// The directory in which files are extracted.
|
||||
if (0 == _tcsicmp(TEXT("/out"), argv[iParamIndex]) || 0 == _tcsicmp(TEXT("-out"), argv[iParamIndex]))
|
||||
{
|
||||
if (++iParamIndex < argc && TEXT('/') != argv[iParamIndex][0] && TEXT('-') != argv[iParamIndex][0])
|
||||
{
|
||||
args->Directory = const_cast<LPTSTR>(argv[iParamIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
error(TEXT("Error: you must specify an output directory with /out.\n"));
|
||||
usage(argv[0], stderr);
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
// Whether or not to include or guess at extensions for output file names.
|
||||
else if (0 == _tcsicmp(TEXT("/ext"), argv[iParamIndex]) || 0 == _tcsicmp(TEXT("-ext"), argv[iParamIndex]))
|
||||
{
|
||||
args->IncludeExtension = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
error(TEXT("Error: unknown option: %s.\n"), argv[iParamIndex]);
|
||||
usage (argv[0], stderr);
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// Prints usage to the given output file stream.
|
||||
void usage(LPCTSTR pszPath, FILE* out)
|
||||
{
|
||||
_ASSERTE(pszPath);
|
||||
_ASSERTE(out);
|
||||
|
||||
LPTSTR pszName = NULL;
|
||||
pszName = (LPTSTR)_tcsrchr(pszPath, TEXT('\\'));
|
||||
if (pszName)
|
||||
{
|
||||
// Advance past the backslash.
|
||||
pszName++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the executable name.
|
||||
pszName = const_cast<LPTSTR>(pszPath);
|
||||
}
|
||||
|
||||
_ftprintf(out, TEXT("Usage: %s <file> [/out <output>] [/ext]\n\n"), pszName);
|
||||
_ftprintf(out, TEXT("\tfile - Path to an MSI, MSM, MSP, or PCP file.\n"));
|
||||
_ftprintf(out, TEXT("\tout - Extract streams and storages to the <output> directory.\n"));
|
||||
_ftprintf(out, TEXT("\text - Append appropriate extensions to output files.\n"));
|
||||
_ftprintf(out, TEXT("\nExtracts transforms and cabinets from a Windows Installer file.\n"));
|
||||
}
|
||||
|
||||
// Colors errors on the console red and prints the formatted error.
|
||||
// You can use positional format specifiers with CRT8.
|
||||
void error(LPCTSTR pszFormat, ...)
|
||||
{
|
||||
_ASSERTE(pszFormat);
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
HANDLE hStdErr = INVALID_HANDLE_VALUE;
|
||||
va_list args;
|
||||
|
||||
// Set console colors to error values.
|
||||
hStdErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (INVALID_HANDLE_VALUE != hStdErr)
|
||||
{
|
||||
if (GetConsoleScreenBufferInfo(hStdErr, &csbi))
|
||||
{
|
||||
// Set new console colors.
|
||||
SetConsoleTextAttribute(hStdErr, COLOR_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// Print error.
|
||||
va_start(args, pszFormat);
|
||||
_vftprintf_p(stderr, pszFormat, args);
|
||||
va_end(args);
|
||||
|
||||
// Reset the console colors to original values.
|
||||
if (INVALID_HANDLE_VALUE != hStdErr)
|
||||
{
|
||||
SetConsoleTextAttribute(hStdErr, csbi.wAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper around FormatMessage for getting error text.
|
||||
// Calls error() to print the error to the console.
|
||||
void win32_error(DWORD dwError)
|
||||
{
|
||||
LPTSTR pszError;
|
||||
|
||||
// Format the error. Error ends with new line.
|
||||
if (FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL,
|
||||
dwError,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &pszError,
|
||||
0,
|
||||
NULL))
|
||||
{
|
||||
error(TEXT("Error 0x%1$08x (%1$d): %2$s"), dwError, pszError);
|
||||
LocalFree(pszError);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a patch from components, using the current working
|
||||
// directory if pszDir is NULL.
|
||||
// pszExt should be either NULL or start with a ".".
|
||||
LPTSTR MakePath(LPTSTR pszDest, size_t cchDest, LPCTSTR pszDir, LPCTSTR pszName, LPCTSTR pszExt)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
_ASSERTE(pszDest);
|
||||
_ASSERTE(cchDest);
|
||||
_ASSERTE(pszName);
|
||||
|
||||
// Make sure pszDest is NULL-terminated.
|
||||
pszDest[0] = TEXT('\0');
|
||||
|
||||
if (pszDir)
|
||||
{
|
||||
// Get the length of pszDir.
|
||||
len = _tcslen(pszDir);
|
||||
|
||||
if (len && 0 != _tcsncpy_s(pszDest, cchDest, pszDir, len))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len && TEXT('\\') != pszDest[len - 1])
|
||||
{
|
||||
// Make sure the path ends with a "\".
|
||||
if (0 != _tcsncat_s(pszDest, cchDest, TEXT("\\"), _TRUNCATE))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append the file name.
|
||||
if (0 != _tcsncat_s(pszDest, cchDest, pszName, _TRUNCATE))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Append the extension.
|
||||
if (pszExt)
|
||||
{
|
||||
if (0 != _tcsncat_s(pszDest, cchDest, pszExt, _TRUNCATE))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return pszDest;
|
||||
}
|
||||
|
||||
// Wrapper around allocating and filling a buffer using MsiRecordGetString().
|
||||
UINT GetString(MSIHANDLE hRecord, UINT iField, LPTSTR* ppszProperty, DWORD* pcchProperty)
|
||||
{
|
||||
_ASSERTE(hRecord);
|
||||
_ASSERTE(iField > 0);
|
||||
_ASSERTE(ppszProperty);
|
||||
_ASSERTE(pcchProperty);
|
||||
|
||||
UINT iErr = NOERROR;
|
||||
DWORD cchProperty = 0;
|
||||
|
||||
iErr = MsiRecordGetString(hRecord, iField, TEXT(""), &cchProperty);
|
||||
if (ERROR_MORE_DATA == iErr)
|
||||
{
|
||||
*ppszProperty = new TCHAR[++cchProperty];
|
||||
*pcchProperty = cchProperty;
|
||||
|
||||
iErr = MsiRecordGetString(hRecord, iField, *ppszProperty, &cchProperty);
|
||||
if (ERROR_SUCCESS != iErr)
|
||||
{
|
||||
delete [] *ppszProperty;
|
||||
*ppszProperty = NULL;
|
||||
*pcchProperty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return iErr;
|
||||
}
|
||||
|
||||
// Determines if the given IStorage* is for a patch
|
||||
// using the STATSTG for the IStorage object.
|
||||
BOOL IsPatch(IStorage* pStorage)
|
||||
{
|
||||
_ASSERTE(pStorage);
|
||||
|
||||
HRESULT hr = NOERROR;
|
||||
STATSTG stg = { 0 };
|
||||
|
||||
hr = pStorage->Stat(&stg, STATFLAG_NONAME);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
return !memcmp(&stg.clsid, &CLSID_MsiPatch, sizeof(CLSID));
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Creates a new storage file and saves the named sub-storage of pRootStorage
|
||||
// to the new storage file.
|
||||
HRESULT SaveStorage(IStorage* pRootStorage, LPCTSTR pszDir, PCWSTR pszName, LPCTSTR pszExt)
|
||||
{
|
||||
HRESULT hr = NOERROR;
|
||||
TCHAR szPath[MAX_PATH] = { TEXT('\0') };
|
||||
IStorage* pStg = NULL;
|
||||
IStorage* pFileStg = NULL;
|
||||
|
||||
_ASSERTE(pRootStorage);
|
||||
_ASSERTE(pszName);
|
||||
|
||||
hr = pRootStorage->OpenStorage(
|
||||
pszName,
|
||||
NULL,
|
||||
STGM_READ | STGM_SHARE_EXCLUSIVE,
|
||||
NULL,
|
||||
0,
|
||||
&pStg);
|
||||
if (SUCCEEDED(hr) && pStg)
|
||||
{
|
||||
if (!MakePath(szPath, MAX_PATH, pszDir, CW2T(pszName), pszExt))
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
_tprintf(TEXT("%s\n"), szPath);
|
||||
|
||||
// Create the storage file.
|
||||
hr = StgCreateDocfile(
|
||||
CT2W(szPath),
|
||||
STGM_WRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
|
||||
0,
|
||||
&pFileStg);
|
||||
if (SUCCEEDED(hr) && pFileStg)
|
||||
{
|
||||
hr = pStg->CopyTo(0, NULL, NULL, pFileStg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SAFE_RELEASE(pFileStg);
|
||||
SAFE_RELEASE(pStg);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
error(TEXT("Error: failed to save storage '%s'.\n"), CW2T(pszName));
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Saves the stream from the given record to a file with or without
|
||||
// an extension based on whether or not fIncludeExt is set to TRUE.
|
||||
UINT SaveStream(MSIHANDLE hRecord, [Pre(Null=Maybe)] LPCTSTR pszDir, BOOL fIncludeExt)
|
||||
{
|
||||
UINT uiError = NOERROR;
|
||||
TCHAR szPath[MAX_PATH];
|
||||
LPTSTR pszName = NULL;
|
||||
DWORD cchName = 0;
|
||||
CHAR szBuffer[256];
|
||||
DWORD cbBuffer = sizeof(szBuffer);
|
||||
std::ofstream file;
|
||||
|
||||
try
|
||||
{
|
||||
// Get the name of the stream but skip if \005SummaryInformation stream.
|
||||
if (ERROR_SUCCESS == GetString(hRecord, 1, &pszName, &cchName) &&
|
||||
0 != _tcsncmp(pszName, TEXT("\005"), 1))
|
||||
{
|
||||
// Create the local file with the simple CFile write-only class.
|
||||
do
|
||||
{
|
||||
uiError = MsiRecordReadStream(hRecord, 2, szBuffer, &cbBuffer);
|
||||
if (ERROR_SUCCESS == uiError)
|
||||
{
|
||||
if (!file.is_open())
|
||||
{
|
||||
// Create the file path if the file is not created and assume the extension
|
||||
// if requested by fIncludeExt.
|
||||
if (!MakePathForData(szPath, MAX_PATH, pszDir, pszName, szBuffer, cbBuffer, fIncludeExt))
|
||||
{
|
||||
throw std::exception("Could not create the output path name");
|
||||
}
|
||||
|
||||
// Create the local file in which data is written.
|
||||
_tprintf(TEXT("%s\n"), szPath);
|
||||
file.open(CT2A(szPath), std::ios_base::binary);
|
||||
}
|
||||
|
||||
file.write(szBuffer, cbBuffer );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::exception("Could not read from stream.");
|
||||
}
|
||||
} while (cbBuffer);
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
error(TEXT("Error: %s\n"), CA2T(ex.what()));
|
||||
uiError = ERROR_CANNOT_MAKE;
|
||||
}
|
||||
|
||||
file.close();
|
||||
if (pszName)
|
||||
{
|
||||
delete [] pszName;
|
||||
pszName = NULL;
|
||||
}
|
||||
|
||||
return uiError;
|
||||
}
|
||||
|
||||
// Creates a patch for the given file using MakePath, but uses what of the
|
||||
// buffer it can to guess the file type and infer a common file extension.
|
||||
LPTSTR MakePathForData(LPTSTR pszDest, size_t cchDest, LPCTSTR pszDir, LPCTSTR pszName,
|
||||
LPCVOID pBuffer, size_t cbBuffer, BOOL fIncludeExt)
|
||||
{
|
||||
LPTSTR pszExt = NULL;
|
||||
if (fIncludeExt)
|
||||
{
|
||||
// Cabinet (*.cab) files.
|
||||
if (0 == memcmp(pBuffer, "MSCF", 4))
|
||||
{
|
||||
pszExt = TEXT(".cab");
|
||||
}
|
||||
|
||||
// Executable files. Assumed to be .dll (more common).
|
||||
else if (0 == memcmp(pBuffer, "MZ", 2))
|
||||
{
|
||||
pszExt = TEXT(".dll");
|
||||
}
|
||||
|
||||
// Icon (*.ico) files. Only assumed because they're common.
|
||||
else if (0 == memcmp(pBuffer, "\0\0\1\0", 4))
|
||||
{
|
||||
pszExt = TEXT(".ico");
|
||||
}
|
||||
|
||||
// Bitmap (*.bmp) files.
|
||||
else if (0 == memcmp(pBuffer, "BM", 2))
|
||||
{
|
||||
pszExt = TEXT(".bmp");
|
||||
}
|
||||
|
||||
// GIF (*.gif) files.
|
||||
else if (0 == memcmp(pBuffer, "GIF", 3))
|
||||
{
|
||||
pszExt = TEXT(".gif");
|
||||
}
|
||||
|
||||
// PING (*.png) files.
|
||||
else if (0 == memcmp(pBuffer, "\x89PNG", 4))
|
||||
{
|
||||
pszExt = TEXT(".png");
|
||||
}
|
||||
|
||||
// TIFF (*.tif) files.
|
||||
else if (0 == memcmp(pBuffer, "II", 2))
|
||||
{
|
||||
pszExt = TEXT(".tif");
|
||||
}
|
||||
}
|
||||
|
||||
return MakePath(pszDest, cchDest, pszDir, pszName, pszExt);
|
||||
}
|
||||
266
libexec/MsiX/MsiX.h
Normal file
266
libexec/MsiX/MsiX.h
Normal file
@@ -0,0 +1,266 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
#include <windows.h>
|
||||
#include <objbase.h>
|
||||
#include <msiquery.h>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
|
||||
#include <codeanalysis/sourceannotations.h>
|
||||
using namespace vc_attributes;
|
||||
|
||||
#define SAFE_RELEASE(ptr) if (ptr) { (ptr)->Release(); ptr = NULL; }
|
||||
#define COLOR_ERROR FOREGROUND_RED | FOREGROUND_INTENSITY
|
||||
|
||||
void usage([Pre(Null=No)] LPCTSTR pszPath, [Pre(Null=No)] FILE* out);
|
||||
void error([Pre(Null=No)] LPCTSTR pszFormat, ...);
|
||||
void win32_error(DWORD dwError);
|
||||
|
||||
typedef struct _ARGS
|
||||
{
|
||||
LPTSTR Path;
|
||||
LPTSTR Directory;
|
||||
BOOL IncludeExtension;
|
||||
} ARGS, *LPARGS;
|
||||
|
||||
DWORD ParseArguments(int argc, [Pre(Null=No)] _TCHAR* argv[], [Pre(Null=No)] LPARGS args);
|
||||
LPTSTR MakePath([Pre(Null=No)] LPTSTR pszDest, size_t cchDest, [Pre(Null=Maybe)] LPCTSTR pszDir,
|
||||
[Pre(Null=No)] LPCTSTR pszName, [Pre(Null=Maybe)] LPCTSTR pszExt);
|
||||
UINT GetString(MSIHANDLE hRecord, UINT iField,
|
||||
[Pre(Null=No)] LPTSTR* ppszProperty, [Pre(Null=No)] DWORD* pcchProperty);
|
||||
HRESULT SaveStorage([Pre(Null=No)] IStorage* pRootStorage, [Pre(Null=Maybe)] LPCTSTR pszDir,
|
||||
[Pre(Null=No)] PCWSTR pszName, [Pre(Null=Maybe)] LPCTSTR pszExt);
|
||||
UINT SaveStream(MSIHANDLE hRecord, [Pre(Null=Maybe)] LPCTSTR pszDir, BOOL fIncludeExt);
|
||||
LPTSTR MakePathForData([Pre(Null=No)] LPTSTR pszDest, size_t cchDest,
|
||||
[Pre(Null=Maybe)] LPCTSTR pszDir, [Pre(Null=No)] LPCTSTR pszName,
|
||||
[Pre(Null=No)] LPCVOID pBuffer, size_t cbBuffer, BOOL fIncludeExt);
|
||||
|
||||
BOOL IsPatch([Pre(Null=No)] IStorage* pStorage);
|
||||
EXTERN_C const CLSID CLSID_MsiPatch = {0xC1086, 0x0, 0x0, {0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x46}};
|
||||
|
||||
// Simple string conversion classes.
|
||||
class CW2W
|
||||
{
|
||||
public:
|
||||
|
||||
CW2W(LPCWSTR psz) throw(...) :
|
||||
m_psz(psz)
|
||||
{
|
||||
_ASSERTE(psz);
|
||||
}
|
||||
|
||||
CW2W(LPCWSTR psz, UINT nCodePage) throw(...) :
|
||||
m_psz(psz)
|
||||
{
|
||||
_ASSERTE(psz);
|
||||
(void)nCodePage;
|
||||
}
|
||||
|
||||
~CW2W() throw()
|
||||
{
|
||||
}
|
||||
|
||||
operator LPWSTR() const throw()
|
||||
{
|
||||
return const_cast<LPWSTR>(m_psz);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
LPCWSTR m_psz;
|
||||
|
||||
// Hide the copy constructor and assignment operator.
|
||||
CW2W( const CW2W& ) throw();
|
||||
CW2W& operator=( const CW2W& ) throw();
|
||||
};
|
||||
|
||||
class CW2A
|
||||
{
|
||||
public:
|
||||
|
||||
CW2A(LPCWSTR psz) throw(...) :
|
||||
m_psz(NULL)
|
||||
{
|
||||
_ASSERTE(psz);
|
||||
Init(psz, CP_ACP);
|
||||
}
|
||||
|
||||
CW2A(LPCWSTR psz, UINT nCodePage) throw(...) :
|
||||
m_psz(NULL)
|
||||
{
|
||||
_ASSERTE(psz);
|
||||
Init(psz, nCodePage);
|
||||
}
|
||||
|
||||
~CW2A() throw()
|
||||
{
|
||||
if (m_psz)
|
||||
{
|
||||
delete [] m_psz;
|
||||
m_psz = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
operator LPSTR() const throw()
|
||||
{
|
||||
return m_psz;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
LPSTR m_psz;
|
||||
|
||||
void Init(LPCWSTR psz, UINT nCodePage) throw(...)
|
||||
{
|
||||
int iErr = NOERROR;
|
||||
int cch = 0;
|
||||
|
||||
cch = WideCharToMultiByte(nCodePage, 0, psz, -1, NULL, 0, NULL, NULL);
|
||||
if (cch)
|
||||
{
|
||||
// cch includes the NULL terminator character.
|
||||
m_psz = new CHAR[cch]; // Throws if no memory.
|
||||
if (!WideCharToMultiByte(nCodePage, 0, psz, -1, m_psz, cch, NULL, NULL))
|
||||
{
|
||||
iErr = (int)GetLastError();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iErr = (int)GetLastError();
|
||||
}
|
||||
|
||||
if (ERROR_SUCCESS != iErr)
|
||||
{
|
||||
throw iErr;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the copy constructor and assignment operator.
|
||||
CW2A( const CW2A& ) throw();
|
||||
CW2A& operator=( const CW2A& ) throw();
|
||||
};
|
||||
|
||||
class CA2W
|
||||
{
|
||||
public:
|
||||
|
||||
CA2W(LPCSTR psz) throw(...) :
|
||||
m_psz(NULL)
|
||||
{
|
||||
_ASSERTE(psz);
|
||||
Init(psz, CP_ACP);
|
||||
}
|
||||
|
||||
CA2W(LPCSTR psz, UINT nCodePage) throw(...) :
|
||||
m_psz(NULL)
|
||||
{
|
||||
_ASSERTE(psz);
|
||||
Init(psz, nCodePage);
|
||||
}
|
||||
|
||||
~CA2W() throw()
|
||||
{
|
||||
if (m_psz)
|
||||
{
|
||||
delete [] m_psz;
|
||||
m_psz = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
operator LPWSTR() const throw()
|
||||
{
|
||||
return m_psz;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
LPWSTR m_psz;
|
||||
|
||||
void Init(LPCSTR psz, UINT nCodePage) throw(...)
|
||||
{
|
||||
int iErr = NOERROR;
|
||||
int cch = 0;
|
||||
|
||||
cch = MultiByteToWideChar(nCodePage, MB_PRECOMPOSED, psz, -1, NULL, 0);
|
||||
if (cch)
|
||||
{
|
||||
// cch includes the NULL terminator character.
|
||||
m_psz = new WCHAR[cch]; // Throws if no memory.
|
||||
if (!MultiByteToWideChar(nCodePage, MB_PRECOMPOSED, psz, -1, m_psz, cch))
|
||||
{
|
||||
iErr = (int)GetLastError();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iErr = (int)GetLastError();
|
||||
}
|
||||
|
||||
if (ERROR_SUCCESS != iErr)
|
||||
{
|
||||
throw iErr;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the copy constructor and assignment operator.
|
||||
CA2W( const CA2W& ) throw();
|
||||
CA2W& operator=( const CA2W& ) throw();
|
||||
};
|
||||
|
||||
class CA2A
|
||||
{
|
||||
public:
|
||||
|
||||
CA2A(LPCSTR psz) throw(...) :
|
||||
m_psz(psz)
|
||||
{
|
||||
_ASSERTE(psz);
|
||||
}
|
||||
|
||||
CA2A(LPCSTR psz, UINT nCodePage) throw(...) :
|
||||
m_psz(psz)
|
||||
{
|
||||
_ASSERTE(psz);
|
||||
(void)nCodePage;
|
||||
}
|
||||
|
||||
~CA2A() throw()
|
||||
{
|
||||
}
|
||||
|
||||
operator LPSTR() const throw()
|
||||
{
|
||||
return const_cast<LPSTR>(m_psz);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
LPCSTR m_psz;
|
||||
|
||||
// Hide the copy constructor and assignment operator.
|
||||
CA2A( const CA2A& ) throw();
|
||||
CA2A& operator=( const CA2A& ) throw();
|
||||
};
|
||||
|
||||
// Declare macros for proper conversion
|
||||
// based on whether UNICODE being defined.
|
||||
#ifdef UNICODE
|
||||
#define CT2W CW2W
|
||||
#define CT2A CW2A
|
||||
#define CW2T CW2W
|
||||
#define CA2T CA2W
|
||||
#else
|
||||
#define CT2W CA2W
|
||||
#define CT2A CA2A
|
||||
#define CW2T CW2A
|
||||
#define CA2T CA2A
|
||||
#endif // UNICODE
|
||||
BIN
libexec/MsiX/MsiX.pdb
Normal file
BIN
libexec/MsiX/MsiX.pdb
Normal file
Binary file not shown.
103
libexec/MsiX/MsiX.rc
Normal file
103
libexec/MsiX/MsiX.rc
Normal file
@@ -0,0 +1,103 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,0
|
||||
PRODUCTVERSION 1,0,0,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Extracts transforms and streams from Windows Installer files."
|
||||
VALUE "CompanyName", "Microsoft Corporation"
|
||||
VALUE "FileDescription", "MSI Extractor"
|
||||
VALUE "FileVersion", "1, 0, 0, 0"
|
||||
VALUE "InternalName", "MsiX"
|
||||
VALUE "LegalCopyright", "Copyright (C) Microsoft Corporation"
|
||||
VALUE "OriginalFilename", "MsiX.exe"
|
||||
VALUE "ProductName", "MSI Extractor"
|
||||
VALUE "ProductVersion", "1, 0, 0, 0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
211
libexec/MsiX/MsiX.vcproj
Normal file
211
libexec/MsiX/MsiX.vcproj
Normal file
@@ -0,0 +1,211 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="MsiX"
|
||||
ProjectGUID="{CC64C520-EFC5-4947-B7FC-B50C54D9D734}"
|
||||
RootNamespace="MsiX"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
EmbedManifest="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="1"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="1"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
EmbedManifest="false"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\MsiX.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\MsiX.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\MsiX.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
14
libexec/MsiX/resource.h
Normal file
14
libexec/MsiX/resource.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by MsiX.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
0
libexec/ShowVer.exe
Normal file → Executable file
0
libexec/ShowVer.exe
Normal file → Executable file
0
libexec/UnRAR.exe
Normal file → Executable file
0
libexec/UnRAR.exe
Normal file → Executable file
BIN
libexec/infozip/funzip.exe
Normal file
BIN
libexec/infozip/funzip.exe
Normal file
Binary file not shown.
BIN
libexec/infozip/unzip.exe
Normal file
BIN
libexec/infozip/unzip.exe
Normal file
Binary file not shown.
BIN
libexec/infozip/unzipsfx.exe
Normal file
BIN
libexec/infozip/unzipsfx.exe
Normal file
Binary file not shown.
BIN
libexec/infozip/zip.exe
Normal file
BIN
libexec/infozip/zip.exe
Normal file
Binary file not shown.
BIN
libexec/infozip/zipcloak.exe
Normal file
BIN
libexec/infozip/zipcloak.exe
Normal file
Binary file not shown.
BIN
libexec/infozip/zipnote.exe
Normal file
BIN
libexec/infozip/zipnote.exe
Normal file
Binary file not shown.
BIN
libexec/infozip/zipsplit.exe
Normal file
BIN
libexec/infozip/zipsplit.exe
Normal file
Binary file not shown.
0
libexec/inifile.exe
Normal file → Executable file
0
libexec/inifile.exe
Normal file → Executable file
0
libexec/innounp.exe
Normal file → Executable file
0
libexec/innounp.exe
Normal file → Executable file
Reference in New Issue
Block a user