update all the functiosn now used in the msvc pack
This commit is contained in:
parent
df3c29f0d9
commit
8ad86744fc
@ -44,6 +44,10 @@ PRG=$(readlink -f $0)
|
|||||||
BASEDIR=`dirname "$PRG"`
|
BASEDIR=`dirname "$PRG"`
|
||||||
BASEDIR=`cd "$BASEDIR" && pwd`/..
|
BASEDIR=`cd "$BASEDIR" && pwd`/..
|
||||||
|
|
||||||
|
OLDPATH=$PATH
|
||||||
|
export PATH=$BASEDIR/libexec:$PATH
|
||||||
|
echo $PATH
|
||||||
|
|
||||||
# Parameters
|
# Parameters
|
||||||
PRODUCT_DIR=$1
|
PRODUCT_DIR=$1
|
||||||
TARGET=$2
|
TARGET=$2
|
||||||
@ -64,6 +68,8 @@ fi
|
|||||||
# call main
|
# call main
|
||||||
builder_controller
|
builder_controller
|
||||||
|
|
||||||
|
export PATH=$OLDPATH
|
||||||
|
|
||||||
# exit
|
# exit
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
160
doc/beautify_bash.py
Normal file
160
doc/beautify_bash.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
#**************************************************************************
|
||||||
|
# Copyright (C) 2011, Paul Lutus *
|
||||||
|
# *
|
||||||
|
# This program is free software; you can redistribute it and/or modify *
|
||||||
|
# it under the terms of the GNU General Public License as published by *
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
# (at your option) any later version. *
|
||||||
|
# *
|
||||||
|
# This program is distributed in the hope that it will be useful, *
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
# GNU General Public License for more details. *
|
||||||
|
# *
|
||||||
|
# You should have received a copy of the GNU General Public License *
|
||||||
|
# along with this program; if not, write to the *
|
||||||
|
# Free Software Foundation, Inc., *
|
||||||
|
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||||
|
#**************************************************************************
|
||||||
|
|
||||||
|
import re, sys
|
||||||
|
|
||||||
|
PVERSION = '1.0'
|
||||||
|
|
||||||
|
class BeautifyBash:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.tab_str = ' '
|
||||||
|
self.tab_size = 2
|
||||||
|
|
||||||
|
def read_file(self,fp):
|
||||||
|
with open(fp) as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
def write_file(self,fp,data):
|
||||||
|
with open(fp,'w') as f:
|
||||||
|
f.write(data)
|
||||||
|
|
||||||
|
def beautify_string(self,data,path = ''):
|
||||||
|
tab = 0
|
||||||
|
case_stack = []
|
||||||
|
in_here_doc = False
|
||||||
|
defer_ext_quote = False
|
||||||
|
in_ext_quote = False
|
||||||
|
ext_quote_string = ''
|
||||||
|
here_string = ''
|
||||||
|
output = []
|
||||||
|
line = 1
|
||||||
|
for record in re.split('\n',data):
|
||||||
|
record = record.rstrip()
|
||||||
|
stripped_record = record.strip()
|
||||||
|
|
||||||
|
# collapse multiple quotes between ' ... '
|
||||||
|
test_record = re.sub(r'\'.*?\'','',stripped_record)
|
||||||
|
# collapse multiple quotes between " ... "
|
||||||
|
test_record = re.sub(r'".*?"','',test_record)
|
||||||
|
# collapse multiple quotes between ` ... `
|
||||||
|
test_record = re.sub(r'`.*?`','',test_record)
|
||||||
|
# collapse multiple quotes between \` ... ' (weird case)
|
||||||
|
test_record = re.sub(r'\\`.*?\'','',test_record)
|
||||||
|
# strip out any escaped single characters
|
||||||
|
test_record = re.sub(r'\\.','',test_record)
|
||||||
|
# remove '#' comments
|
||||||
|
test_record = re.sub(r'(\A|\s)(#.*)','',test_record,1)
|
||||||
|
if(not in_here_doc):
|
||||||
|
if(re.search('<<-?',test_record)):
|
||||||
|
here_string = re.sub('.*<<-?\s*[\'|"]?([_|\w]+)[\'|"]?.*','\\1',stripped_record,1)
|
||||||
|
in_here_doc = (len(here_string) > 0)
|
||||||
|
if(in_here_doc): # pass on with no changes
|
||||||
|
output.append(record)
|
||||||
|
# now test for here-doc termination string
|
||||||
|
if(re.search(here_string,test_record) and not re.search('<<',test_record)):
|
||||||
|
in_here_doc = False
|
||||||
|
else: # not in here doc
|
||||||
|
if(in_ext_quote):
|
||||||
|
if(re.search(ext_quote_string,test_record)):
|
||||||
|
# provide line after quotes
|
||||||
|
test_record = re.sub('.*%s(.*)' % ext_quote_string,'\\1',test_record,1)
|
||||||
|
in_ext_quote = False
|
||||||
|
else: # not in ext quote
|
||||||
|
if(re.search(r'(\A|\s)(\'|")',test_record)):
|
||||||
|
# apply only after this line has been processed
|
||||||
|
defer_ext_quote = True
|
||||||
|
ext_quote_string = re.sub('.*([\'"]).*','\\1',test_record,1)
|
||||||
|
# provide line before quote
|
||||||
|
test_record = re.sub('(.*)%s.*' % ext_quote_string,'\\1',test_record,1)
|
||||||
|
if(in_ext_quote):
|
||||||
|
# pass on unchanged
|
||||||
|
output.append(record)
|
||||||
|
else: # not in ext quote
|
||||||
|
inc = len(re.findall('(\s|\A|;)(case|then|do)(;|\Z|\s)',test_record))
|
||||||
|
inc += len(re.findall('(\{|\(|\[)',test_record))
|
||||||
|
outc = len(re.findall('(\s|\A|;)(esac|fi|done|elif)(;|\)|\||\Z|\s)',test_record))
|
||||||
|
outc += len(re.findall('(\}|\)|\])',test_record))
|
||||||
|
if(re.search(r'\besac\b',test_record)):
|
||||||
|
if(len(case_stack) == 0):
|
||||||
|
sys.stderr.write(
|
||||||
|
'File %s: error: "esac" before "case" in line %d.\n' % (path,line)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
outc += case_stack.pop()
|
||||||
|
# sepcial handling for bad syntax within case ... esac
|
||||||
|
if(len(case_stack) > 0):
|
||||||
|
if(re.search('\A[^(]*\)',test_record)):
|
||||||
|
# avoid overcount
|
||||||
|
outc -= 2
|
||||||
|
case_stack[-1] += 1
|
||||||
|
if(re.search(';;',test_record)):
|
||||||
|
outc += 1
|
||||||
|
case_stack[-1] -= 1
|
||||||
|
# an ad-hoc solution for the "else" keyword
|
||||||
|
else_case = (0,-1)[re.search('^(else)',test_record) != None]
|
||||||
|
net = inc - outc
|
||||||
|
tab += min(net,0)
|
||||||
|
extab = tab + else_case
|
||||||
|
extab = max(0,extab)
|
||||||
|
output.append((self.tab_str * self.tab_size * extab) + stripped_record)
|
||||||
|
tab += max(net,0)
|
||||||
|
if(defer_ext_quote):
|
||||||
|
in_ext_quote = True
|
||||||
|
defer_ext_quote = False
|
||||||
|
if(re.search(r'\bcase\b',test_record)):
|
||||||
|
case_stack.append(0)
|
||||||
|
line += 1
|
||||||
|
error = (tab != 0)
|
||||||
|
if(error):
|
||||||
|
sys.stderr.write('File %s: error: indent/outdent mismatch: %d.\n' % (path,tab))
|
||||||
|
return '\n'.join(output), error
|
||||||
|
|
||||||
|
def beautify_file(self,path):
|
||||||
|
error = False
|
||||||
|
if(path == '-'):
|
||||||
|
data = sys.stdin.read()
|
||||||
|
result,error = self.beautify_string(data,'(stdin)')
|
||||||
|
sys.stdout.write(result)
|
||||||
|
else: # named file
|
||||||
|
data = self.read_file(path)
|
||||||
|
result,error = self.beautify_string(data,path)
|
||||||
|
if(data != result):
|
||||||
|
# make a backup copy
|
||||||
|
self.write_file(path + '~',data)
|
||||||
|
self.write_file(path,result)
|
||||||
|
return error
|
||||||
|
|
||||||
|
def main(self):
|
||||||
|
error = False
|
||||||
|
sys.argv.pop(0)
|
||||||
|
if(len(sys.argv) < 1):
|
||||||
|
sys.stderr.write('usage: shell script filenames or \"-\" for stdin.\n')
|
||||||
|
else:
|
||||||
|
for path in sys.argv:
|
||||||
|
error |= self.beautify_file(path)
|
||||||
|
sys.exit((0,1)[error])
|
||||||
|
|
||||||
|
# if not called as a module
|
||||||
|
if(__name__ == '__main__'):
|
||||||
|
BeautifyBash().main()
|
||||||
|
|
@ -11,11 +11,10 @@
|
|||||||
builder_config() {
|
builder_config() {
|
||||||
|
|
||||||
# Define commands
|
# Define commands
|
||||||
CMD_7z="`which 7z.exe`" ; builder_check_error "Command '7z' not installed"
|
CMD_7z="`which 7z`" ; builder_check_error "Command '7z' not installed"
|
||||||
CMD_unzip="`which unzip.exe`" ; builder_check_error "Command 'unzip' not installed"
|
CMD_unzip="`which unzip.exe`" ; builder_check_error "Command 'unzip' not installed"
|
||||||
CMD_unrar="`which UnRAR.exe`" ; builder_check_error "Command 'UnRAR' not installed"
|
CMD_unrar="`which UnRAR.exe`" ; builder_check_error "Command 'UnRAR' not installed"
|
||||||
CMD_zip="`which zip.exe`" ; builder_check_error "Command 'zip' not installed"
|
CMD_zip="`which zip.exe`" ; builder_check_error "Command 'zip' not installed"
|
||||||
CMD_lha="`which lha.exe`" ; builder_check_error "Command 'lha' not installed"
|
|
||||||
CMD_tar="`which tar.exe`" ; builder_check_error "Command 'tar' not installed"
|
CMD_tar="`which tar.exe`" ; builder_check_error "Command 'tar' not installed"
|
||||||
CMD_cabextract="`which cabextract.exe`" ; builder_check_error "Command 'cabextract' not installed"
|
CMD_cabextract="`which cabextract.exe`" ; builder_check_error "Command 'cabextract' not installed"
|
||||||
CMD_unix2dos="`which unix2dos.exe`" ; builder_check_error "Command 'unix2dos' not installed"
|
CMD_unix2dos="`which unix2dos.exe`" ; builder_check_error "Command 'unix2dos' not installed"
|
||||||
@ -23,6 +22,9 @@ builder_config() {
|
|||||||
CMD_inifile="`which inifile.exe`" ; builder_check_error "Command 'inifile' not installed (http://www.horstmuc.de/wbat32d.htm#inifile)"
|
CMD_inifile="`which inifile.exe`" ; builder_check_error "Command 'inifile' not installed (http://www.horstmuc.de/wbat32d.htm#inifile)"
|
||||||
CMD_showver="`which ShowVer.exe`" ; builder_check_error "Command 'ShowVer' not installed (http://www.codeproject.com/Articles/2457/ShowVer-exe-command-line-VERSIONINFO-display-progr)"
|
CMD_showver="`which ShowVer.exe`" ; builder_check_error "Command 'ShowVer' not installed (http://www.codeproject.com/Articles/2457/ShowVer-exe-command-line-VERSIONINFO-display-progr)"
|
||||||
CMD_tidy="`which tidy.exe`" ; builder_check_error "Command 'tidy' not installed"
|
CMD_tidy="`which tidy.exe`" ; builder_check_error "Command 'tidy' not installed"
|
||||||
|
CMD_msiexec="`which msiexec.exe`" ; builder_check_error "Command 'msiexec' not installed"
|
||||||
|
CMD_innounp="`which innounp.exe`" ; builder_check_error "Command 'innounp' not installed"
|
||||||
|
CMD_xmlstarlet="`which xmlstarlet.exe`" ; builder_check_error "Command 'xmlstarlat' not installed"
|
||||||
|
|
||||||
# Check temp dir
|
# Check temp dir
|
||||||
test -d ${TMP_DIR}
|
test -d ${TMP_DIR}
|
||||||
@ -188,14 +190,14 @@ builder_create() {
|
|||||||
|
|
||||||
# Copy files and convert text files to dos format
|
# Copy files and convert text files to dos format
|
||||||
# cp -Rv ${PRODUCT_DIR}/AIO $INST_DIR
|
# cp -Rv ${PRODUCT_DIR}/AIO $INST_DIR
|
||||||
# cp -Rv ${PRODUCT_DIR}/CLIENT_DATA $INST_DIR
|
# cp -Rv ${PRODUCT_DIR}/Temp $INST_DIR
|
||||||
# if [ -d "${PRODUCT_DIR}/SERVER_DATA" ] ; then
|
# if [ -d "${PRODUCT_DIR}/SERVER_DATA" ] ; then
|
||||||
# cp -Rv ${PRODUCT_DIR}/SERVER_DATA $INST_DIR
|
# cp -Rv ${PRODUCT_DIR}/SERVER_DATA $INST_DIR
|
||||||
# fi
|
# fi
|
||||||
|
|
||||||
# copy binaries
|
# copy binaries
|
||||||
for (( i = 0 ; i < ${#DL_SOURCE[@]} ; i++ )) ; do
|
for (( i = 0 ; i < ${#DL_SOURCE[@]} ; i++ )) ; do
|
||||||
DL_EXTRACT_PATH[$i]=${INST_DIR}/CLIENT_DATA/${DL_ARCH[$i]}/${DL_EXTRACT_TO[$i]}
|
DL_EXTRACT_PATH[$i]=${INST_DIR}/Temp/${DL_ARCH[$i]}/${DL_EXTRACT_TO[$i]}
|
||||||
local format=${DL_EXTRACT_FORMAT[$i]}
|
local format=${DL_EXTRACT_FORMAT[$i]}
|
||||||
if [ -z "$format" ] ; then format="cp"; fi
|
if [ -z "$format" ] ; then format="cp"; fi
|
||||||
local option=${DL_EXTRACT_OPTION[$i]}
|
local option=${DL_EXTRACT_OPTION[$i]}
|
||||||
@ -240,9 +242,10 @@ builder_package() {
|
|||||||
local release_new=${CREATOR_TAG}${RELEASE}
|
local release_new=${CREATOR_TAG}${RELEASE}
|
||||||
local aio_file=${PN}_${VERSION}-${release_new}.7z
|
local aio_file=${PN}_${VERSION}-${release_new}.7z
|
||||||
|
|
||||||
|
rm -rf $INST_DIR/Temp
|
||||||
pushd ${OUTPUT_DIR}
|
pushd ${OUTPUT_DIR}
|
||||||
rm -f ${aio_file} ${AIO_REPOS_FILE_PATTERN}.7z
|
rm -f ${aio_file} ${AIO_REPOS_FILE_PATTERN}.7z
|
||||||
7z a ${AIO_REPOS_FILE_PATTERN}.7z -v $INST_DIR/*
|
$CMD_7z a ${AIO_REPOS_FILE_PATTERN}.7z $INST_DIR/*
|
||||||
builder_check_error "Building AIO-package"
|
builder_check_error "Building AIO-package"
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
#############################################
|
#############################################
|
||||||
# void retrieve_file (src, dst)
|
# void retrieve_file (src, dst)
|
||||||
#
|
#
|
||||||
@ -67,8 +68,6 @@ function process_file() {
|
|||||||
$CMD_unzip $option -o $src -d $dst
|
$CMD_unzip $option -o $src -d $dst
|
||||||
elif [ "$format" = "unrar" ]; then
|
elif [ "$format" = "unrar" ]; then
|
||||||
$CMD_unrar x -y $option $src $dst
|
$CMD_unrar x -y $option $src $dst
|
||||||
elif [ "$format" = "lha" ]; then
|
|
||||||
$CMD_lha x $option -w=$dst $src
|
|
||||||
elif [ "$format" = "targz" ]; then
|
elif [ "$format" = "targz" ]; then
|
||||||
$CMD_tar xzvf $option $src -C $dst
|
$CMD_tar xzvf $option $src -C $dst
|
||||||
elif [ "$format" = "tarbz2" ]; then
|
elif [ "$format" = "tarbz2" ]; then
|
||||||
@ -201,16 +200,28 @@ write_ini_file() {
|
|||||||
# Var:
|
# Var:
|
||||||
#
|
#
|
||||||
###################
|
###################
|
||||||
get_file_version() {
|
vercomp() {
|
||||||
local getver_file=$1
|
[ ! $(echo -e "$1\n$2" | sort --version-sort | head -1) = "$1" ]
|
||||||
local getver_var=$2
|
}
|
||||||
|
|
||||||
if [ -f "$getver_file" ] ; then
|
###################
|
||||||
$CMD_showver $getver_file | grep FileVersion: | rev | cut -d: -f1 | rev | tr -d ' ' > $getver_ver
|
# Get Verison of File
|
||||||
echo "file $getver_file has version $getver_ver"
|
#
|
||||||
else
|
# Copy file only if it is newer
|
||||||
echo "$getver_file not found"
|
#
|
||||||
fi
|
# Parameter
|
||||||
|
# File: to process
|
||||||
|
# Var:
|
||||||
|
#
|
||||||
|
###################
|
||||||
|
|
||||||
|
|
||||||
|
get_file_ver() {
|
||||||
|
local getver_file=$2
|
||||||
|
local __resultvar=$1
|
||||||
|
local myresult=`$CMD_showver $(cygpath -pw "$getver_file") | grep FileVersion: | rev | cut -d: -f1 | rev | tr -d ' '`
|
||||||
|
echo "$getver_file -> $myresult"
|
||||||
|
eval $__resultvar="'$myresult'"
|
||||||
}
|
}
|
||||||
|
|
||||||
###################
|
###################
|
||||||
@ -226,10 +237,29 @@ get_file_version() {
|
|||||||
copyver() {
|
copyver() {
|
||||||
local source_file=$1
|
local source_file=$1
|
||||||
local target_file=$2
|
local target_file=$2
|
||||||
local source_ver
|
local source_ver=""
|
||||||
local target_ver
|
local target_ver=""
|
||||||
|
|
||||||
get_file_version $source_file $source_ver
|
echo "Source File: $source_file Target Version: $target_file"
|
||||||
|
if [ -f "$source_file" ] && [ -f "$target_file" ] ; then
|
||||||
|
get_file_ver source_ver $source_file
|
||||||
|
get_file_ver target_ver $target_file
|
||||||
|
if [ vercomp $source_ver $target_ver ] ; then
|
||||||
|
echo "Source Verssion: $source_ver > Target Version: $target_ver"
|
||||||
|
echo "Copying File"
|
||||||
|
cp $source_file $target_file
|
||||||
|
else
|
||||||
|
echo "Source Verssion: $source_ver =< Target Version: $target_ver"
|
||||||
|
echo "Not Copying File"
|
||||||
|
fi
|
||||||
|
elif [ -f "$source_file" ] && [ ! -f "$target_file" ] ; then
|
||||||
|
source_ver=$(get_file_version $source_file)
|
||||||
|
echo "Source Verssion: $source_ver"
|
||||||
|
echo "Copying File"
|
||||||
|
cp $source_file $target_file
|
||||||
|
else
|
||||||
|
echo "Nothing to copy"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
###################
|
###################
|
||||||
@ -249,3 +279,68 @@ tidy_xml() {
|
|||||||
cat $source_file | $CMD_tidy -utf8 -xml -w 255 -i -c -q -asxml | sed -e 's!>!>!g' -e 's!<!<!g' > $target_file
|
cat $source_file | $CMD_tidy -utf8 -xml -w 255 -i -c -q -asxml | sed -e 's!>!>!g' -e 's!<!<!g' > $target_file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# void extract_file (format, src, dst)
|
||||||
|
#
|
||||||
|
# Description: Extract a file
|
||||||
|
#
|
||||||
|
# Parameter
|
||||||
|
# format: compression format
|
||||||
|
# src: source file to be used
|
||||||
|
# dst: path to extract the file
|
||||||
|
#
|
||||||
|
#############################################
|
||||||
|
function extract_file() {
|
||||||
|
|
||||||
|
local format=$1
|
||||||
|
local src=$2
|
||||||
|
local dst=$3
|
||||||
|
local option=$4
|
||||||
|
local src_dir=`dirname "$src"`
|
||||||
|
local src_file=`basename "$src"`
|
||||||
|
local dst_dir=`dirname "$dst"`
|
||||||
|
local dst_file=`basename "$dst"`
|
||||||
|
|
||||||
|
log_debug "Compression format: $format"
|
||||||
|
|
||||||
|
mkdir -p $dst
|
||||||
|
if [ "$format" = "msi-a" ]; then
|
||||||
|
mkdir /cygdrive/c/msi-adm
|
||||||
|
pushd $src_dir
|
||||||
|
echo $src_file
|
||||||
|
$CMD_msiexec /a "$src_file" $option TARGETDIR="c:\msi-adm"
|
||||||
|
popd
|
||||||
|
cp -r /cygdrive/c/msi-adm/* $dst
|
||||||
|
rm -rf /cygdrive/c/msi-adm
|
||||||
|
elif [ "$format" = "msp-a" ]; then
|
||||||
|
pushd $dst_dir
|
||||||
|
cp $src $dst_dir
|
||||||
|
$CMD_msiexec /p "$src_file" /a "$dst_file" SHORTFILENAMES=TRUE /qb
|
||||||
|
popd
|
||||||
|
elif [ "$format" = "7zip" ]; then
|
||||||
|
$CMD_7z x -y $option -o$dst $src
|
||||||
|
elif [ "$format" = "unzip" ]; then
|
||||||
|
$CMD_unzip $option -o $src -d $dst
|
||||||
|
elif [ "$format" = "unrar" ]; then
|
||||||
|
$CMD_unrar x -y $option $(cygpath -pw "$src") $(cygpath -pw "$dst")
|
||||||
|
elif [ "$format" = "cab" ]; then
|
||||||
|
$CMD_cabextract $option -d $dst $src
|
||||||
|
elif [ "$format" = "cab-sfx" ]; then
|
||||||
|
$CMD_cabextract $option -d $dst $src
|
||||||
|
$CMD_xmlstarlet sel -N X="http://schemas.microsoft.com/wix/2008/Burn" -t -m "//X:Payload" -v "concat(@SourcePath,'-',@FilePath)" -n $dst/0 | tr '\\' '/' > $dst/rename.list
|
||||||
|
for i in `cat $dst/rename.list`
|
||||||
|
do
|
||||||
|
pushd $dst
|
||||||
|
local src_var=$(echo $i | cut -f1 -d-)
|
||||||
|
local dst_var=$(echo $i | cut -f2 -d-)
|
||||||
|
mkdir -p $(dirname $dst_var)
|
||||||
|
mv -v $src_var $dst_var
|
||||||
|
popd
|
||||||
|
done
|
||||||
|
elif [ "$format" = "inno" ]; then
|
||||||
|
$CMD_innounp $option -d $dst $src
|
||||||
|
else
|
||||||
|
fatal_error "Unknown compression format: $format"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
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
Loading…
Reference in New Issue
Block a user