
Ящик для предложений: sales@blogslov.ru
Send Wix-commits mailing list submissions to
wix-commits@lists.sourceforge.net
To subscribe or unsubscribe via the World Wide Web, visit
https://lists.sourceforge.net/lists/listinfo/wix-commits
or, via email, send a message with subject or body 'help' to
wix-commits-request@lists.sourceforge.net
You can reach the person managing the list at
wix-commits-owner@lists.sourceforge.net
When replying, please edit your Subject line so it is more specific
than "Re: Contents of Wix-commits digest..."
Today's Topics:
1. wix/src/dutil cabcutil.cpp, 1.8, 1.9 dirutil.cpp, 1.5, 1.6
dirutil.h, 1.6, 1.7 fileutil.cpp, 1.12, 1.13 fileutil.h, 1.8, 1.9
pathutil.cpp, 1.2, 1.3 pathutil.h, 1.3, 1.4 proc2utl.cpp, 1.1,
1.2 procutil.cpp, 1.1, 1.2 procutil.h, 1.1, 1.2 sqlutil.h, 1.7,
1.8 xmlutil.cpp, 1.8, 1.9 xmlutil.h, 1.7, 1.8 (Rob Mensching)
----------------------------------------------------------------------
Message: 1
Date: Wed, 27 Jun 2007 05:36:21 +0000
From: Rob Mensching
Subject: [WiX-commits] wix/src/dutil cabcutil.cpp, 1.8, 1.9
dirutil.cpp, 1.5, 1.6 dirutil.h, 1.6, 1.7 fileutil.cpp, 1.12, 1.13
fileutil.h, 1.8, 1.9 pathutil.cpp, 1.2, 1.3 pathutil.h, 1.3, 1.4
proc2utl.cpp, 1.1, 1.2 procutil.cpp, 1.1, 1.2 procutil.h, 1.1, 1.2
sqlutil.h, 1.7, 1.8 xmlutil.cpp, 1.8, 1.9 xmlutil.h, 1.7, 1.8
To: wix-commits@lists.sourceforge.net
Message-ID:
Update of /cvsroot/wix/wix/src/dutil
In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv1332/src/dutil
Modified Files:
cabcutil.cpp dirutil.cpp dirutil.h fileutil.cpp fileutil.h
pathutil.cpp pathutil.h proc2utl.cpp procutil.cpp procutil.h
sqlutil.h xmlutil.cpp xmlutil.h
Log Message:
Benxing: Number of patch related bug fix
*Update FeatureComponent table when ComponentRef in the selected PatchFamily
*File Sequence problem
PMarcu: Allowing extension attributes on DirectoryRef and PropertyRef
Adding extension attributes to the VSExtension Refs
PMarcu: Adding UIRef and DirectoryRef to possible PatchFamily Children
Allowing extension attributes on CustomAction elements.
JRock: Added support for setting pre- and post-build event command lines via a
property page in Votive. This gets me one step closer to restoring the
inter-project variables that we had in V2 but had to pull in V3 to get
it out the door (e.g. $(var.MyProject.TargetPath)).
JRock: Added support for SolutionX variables in the wix.targets file. So, you
can now use $(var.SolutionDir) in your .wxs files and have the variables
automatically added to the preprocessor definitions when building with
wix.targets and MSBuild.
Benxing: Regardless of differences in the MST, we will compare underlying files before
copying data into the patch. Extensions can override CompareFiles to provide
custom file diffing behavior.
AaronSte: Updating Heat to use HKCU instead of HKLM when harvesting registry
information on Windows Vista to avoid UAC issues
PMarcu: Making XsdStitch only output a single prefix for each extension namespace.
Benxing: Fixing null reference exception in the binder when the file table is empty.
RobMen: Default File/@Name to File/@Id.
MikeHo: Fix bug with Setup.exe when trying to install and TEMP and AppData
folders are not on same drive, setup fails
MikeHo: Add fallback to Caching the MSI.
RobMen: SFBUG:1680666 - Correctly modularize RemoveIniFile.DirProperites.
PMarcu: Removing FragmentRef's
AaronSte: SFBUG:1675664 - Marking ComboBox value attribute as localizable.
PMarcu: Adding BinaryRef as a child of PatchFamily.
Benxing: Give warning when removing component from feature during the patch build.
PMarcu: Changing namespace keys in the VSExtension help tables to not be modularized.
PMarcu: Adding some targeted checks to patch transforms to catch possible error
conditions as early as possible.
AaronSte: Adding Visual Studio Codename Orcas detection properties.
AaronSte: SFBUG:1687207 - Update Heat so DllRegisterServer captures will work
on Windows Vista from an elevated cmd prompt.
PMarcu: Fix for DocCompiler to handle ref attributes in attribute definitions under
elements.
BobArnso: Resize and combine some controls to better fit localized strings
(affects all UI sets, dialogs UserExit, OutOfRbDiskDlg, OutOfDiskDlg)
Benxing: Skipping unreal tables when binding transforms to improve patch build
perfomance.
Adding active substorage into binder extension to give the ability to
access corresponding transform information.
JRock: SFBUG:1673425 - Cannot access the VS menu using the alt key
SFBUG:1576283 - Unable to enter 'c' or 'm' in proj properties screen fields
SFBUG:1570392 - Project Designer - Index was outside the bounds of the array
SFBUG:1566296 - Setting 'Cultures' field in project properties has no effect
SFBUG:1576287 - Modifying project properties does not force rebuild
Benxing: Ignore rows without section id in ReduceTransform.
MikeHo: Allow for multiple files to be extracted from chainer.
AaronSte: Adding Visual Studio Team Test project system detection properties.
FGrohn: Support for PubCA in WiX v3.
HeathS: Added extension support to the Validator.
Exposed extension support for the Validator through light.exe.
Exposed extension support for the Validator through smoke.exe.
Exposed multiple .cub file support through smoke.exe.
HeathS: Exposed multiple .cub file support through light.exe.
Added a test for the Validator and multiple .cub support in light.exe.
MikeHo: Add error messages for Windows Installer service can't start or Install
blocked by system policy
BobArnso: Add WixQueryOsInfo CA to detect system suite info and "special
folders" as properties over and above the MSI set
BobArnso: Default to removing library rows from decompiled output in
WixUtilExtension
PMarcu: Refactoring patch buld system to use Pyro instead of Light for filtering
and binding. Other target patch specific bug fixes are in the mix as well.
PMarcu: Adding more command line options to Pyro, specifically the ones that
provide settings for the binder.
PMarcu: Adding error and warning preprocessor instructions.
PMarcu: Fixing an exception thrown when Dark is run and no extensions are defined
in the config file or the config file is absent.
Also, bug where Customtable columns that are not foreign keys have the
keytable attribute defined on the column as keytable="". This results in
an invalid table reference to "".
PMarcu: Switching order on Pyro commandline.
Jordanf: Adding support to WixUnit for Pyro. Fixing the qtest patch.minorupgrade
to use Pyro.
BrianRe: Added code to detect a namespace prefix that is already in use and if
so it will append it with its' position within the "duplicates" for
that specific prefix; eg. sql, sql2, sql3, and so on.
RobMen: Add support for PerformanceCounters (including managed code).
FGrohn: Added COM+ and MSMQ extensions to the zip file.
FGrohn: Move to Windows Vista SDK.
JRock: SFBUG:1566807 - Display full version in about dialog.
SFBUG:1697089 - MSBuild WiX taskscannot resolve WiX tool paths automatically
SFBUG:1689830 - Error when using Wix3 when not installed on C drive
Benxing: Handle Sequence tables when building the patch.
Don't allow empty patch.
HeathS: Added an extension for installing PowerShell snap-ins.
PMarcu: Adding Melt as a tool to decompile MSM's to ComponentGroups.
PMarcu: Adding warning for when a non keypath file is updated and the keypath file
of that component is not.
Benxing: Adding information into _SummaryInformation table for patch build.
PMarcu: Adding a check to assure no duplicate fragment Id's exist.
JKuhne: Fixing a GC issue with the Validator. (Locals are rooted until last reference, not
end of scope.)
BobArnso: Add DiskId attribute to Directory and DirectoryRef to provide default
DiskId for contained components and files.
MikeHo: Fix language matching in Setup.exe
PMarcu: Making sdut and tsa defaults when passing xo to light.exe
AaronSte: Adding more CSIDL values to WixQueryOsDirs custom action
RobMen: Reverse integrate WiX v2 CustomAction fixes.
BobArnso: Add element-extensibility points to Directory and DirectoryRef.
Jordanf: Add a new test for preprocessor .
Mikeho: Add NewFolder UIText element.
AaronSte: Adding custom actions to run devenv.exe /InstallVSTemplates to the
WixVSExtension
BobArnso: Pass directory ID to Directory and DirectoryRef extension elements.
RobMen: Introducing smart-cabbing.
RobMen: SFBUG:1707259 - fix nasty memory violation
HeathS: Added patch-specific property to identify client patches and
if they can be removed.
Mikeho: Fix manifests for setupbld.exe/setup.exe
JordanF: Add the -update option to automatically update a test. Make MSI/MSI
validation explicit in the tests.
JRock: Adding back project references to Votive V3! Actually, I'm adding them
to the wix.targets MSBuild file to be exact. Votive uses it, but you get
the goodness without using Votive also. Basically, this is the feature
where if you reference other projects in your Visual Studio solution,
you can reference the output of those projects from within your wixproj
project. For example, $(var.MyCSharpApp.TargetPath). This will work for
any managed project in Visual Studio (at least it does for VC#, VB, and
VC++ managed). You have to build from within Visual Studio or from the
command line. If you build just the .wixproj, then you won't get the
project variables defined.
SFBUG:1585281 - Add solution and project variables back to Votive v3
MikeHo: Fix support for more than 10 MSIs/MSTs
JRock: SFBUG:1588291 - Support response files for MSBuild candle/light/lit
tasks
BobArnso: Have heat generate a default ComponentGroup when harvesting
directories in a fragment.
JRock: SFBUG:1717966 - Solution Build Issues (build 2911)
When a wixproj is the only thing in the solution, the SolutionX
variables aren't defined when building within Visual Studio. This
is because normally C#/VB define these variables for us. The fix
is to define them ourself.
HeathS: SFBUG:1716160 - ICE03 string overflow error, xmlFile
RobMen: SFBUG:1716160 - fix string overflow error for XmlConfig
BrianRe: Fixing wix.xsd to use W3C recognized regular expressions.
PMarcu: Defaulting Media\@Source to a form of the patchId if not specified
when Media is a child of a patch.
RobMen: SFBUG:1724535 - correctly integrate a few more fixes from WiX v2 to
WiX v3.
JordanF: WixUnit now compares the transforms inside a patch when it is diffing
two patches. Previously, only the tables in the patch were compared.
AaronSte: Added documentation for properties and custom actions in the
WixVSExtension.
PMarcu: Fix for ServiceConfig CA's to call correct rollback entrypoint.
BMurri: Add support for bound wixouts/wixmsts to torch and pyro.
PMarcu: Fix for ServiceConfig CA's to call correct rollback entrypoint.
RobMen: Schema tweaks to enable simple references on FeatureRef and
FeatureGroupRef plus tweaks to enable floating Components.
AaronSte: Added documentation for Votive functionality.
AaronSte: Fixing variable resolution problem in WiX Product item template
in Votive.
PMarcu: Updating flags in XmlConfig to match with CA after the 2.0 to
3.0 integration.
JRock: Integrated the VS SDK 4.0 into Votive.
AaronSte: Merged WiX 2.0 documentation changes into 3.0. Updated instances
of deprecated src attributes in examples in the docs.
MikeHo: Add reinstall support & logging to Chainer + fix bug when using
transforms other than Chinese.
HeathS: SFBUG:1739868 - Pyro does not find .AllowRemoval property
PMarcu: Removing primary key from EnsureTable to support patching.
Fixing documentation for XmlConfig.
RobMen: SFBUG:1739194 - Preserve whitespace when using XmlFile or XmlConfig
JKuhne: Fix a GC related bug in the cab enumeration callback. (Cab.WixEnumerateCab.Enumerate)
Index: xmlutil.h
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/xmlutil.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** xmlutil.h 4 Oct 2006 08:07:33 -0000 1.7
--- xmlutil.h 27 Jun 2007 05:36:19 -0000 1.8
***************
*** 30,33 ****
--- 30,39 ----
extern __declspec(selectany) const IID XmlUtil_IID_IXMLDOMSchemaCollection = {0x373984C8, 0xB845, 0x449B, {0x91, 0xE7, 0x45, 0xAC, 0x83, 0x03, 0x6A, 0xDE}};
+ enum XML_LOAD_ATTRIBUTE
+ {
+ XML_LOAD_PRESERVE_WHITESPACE = 1,
+ };
+
+
#ifdef __cplusplus
extern "C" {
***************
*** 51,58 ****
--- 57,74 ----
__out IXMLDOMDocument** ppixdDocument
);
+ HRESULT DAPI XmlLoadDocumentEx(
+ __in LPCWSTR wzDocument,
+ __in DWORD dwAttributes,
+ __out IXMLDOMDocument** ppixdDocument
+ );
HRESULT DAPI XmlLoadDocumentFromFile(
__in LPCWSTR wzPath,
__out IXMLDOMDocument** ppixdDocument
);
+ HRESULT DAPI XmlLoadDocumentFromFileEx(
+ __in LPCWSTR wzPath,
+ __in DWORD dwAttributes,
+ __out IXMLDOMDocument** ppixdDocument
+ );
HRESULT DAPI XmlSelectSingleNode(
__in IXMLDOMNode* pixnParent,
Index: fileutil.h
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/fileutil.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** fileutil.h 13 Dec 2006 07:44:20 -0000 1.8
--- fileutil.h 27 Jun 2007 05:36:19 -0000 1.9
***************
*** 18,21 ****
--- 18,23 ----
//-------------------------------------------------------------------------------------------------
+ #include
+
#ifdef __cplusplus
extern "C" {
***************
*** 31,34 ****
--- 33,40 ----
__out LPWSTR *ppwzFullPath
);
+ HRESULT DAPI FileStripExtension(
+ __in LPCWSTR wzFileName,
+ __out LPWSTR *ppwzFileNameNoExtension
+ );
HRESULT DAPI FileVersionFromString(
__in LPCWSTR wzVersion,
***************
*** 61,65 ****
__in BOOL fAllowCopy
);
!
#ifdef __cplusplus
}
--- 67,83 ----
__in BOOL fAllowCopy
);
! HRESULT FileCreateTemp(
! IN LPCWSTR wzPrefix,
! IN LPCWSTR wzExtension,
! OUT LPWSTR* ppwzLog,
! OUT HANDLE* phLog
! );
! HRESULT FileCreateTempW(
! IN LPCWSTR wzPrefix,
! IN LPCWSTR wzExtension,
! OUT LPWSTR* ppwzTempFile,
! OUT HANDLE* phTempFile
! );
!
#ifdef __cplusplus
}
Index: cabcutil.cpp
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/cabcutil.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** cabcutil.cpp 19 Apr 2006 08:54:28 -0000 1.8
--- cabcutil.cpp 27 Jun 2007 05:36:19 -0000 1.9
***************
*** 26,31 ****
--- 26,75 ----
static HRESULT vhrLastError = S_OK;
+ static const DWORD ONEHUNDRED_TWENTYEIGHT_MB = 128 * 1024 * 1024;
+
// structs
+ struct MS_CABINET_HEADER
+ {
+ DWORD sig;
+ DWORD csumHeader;
+ DWORD cbCabinet;
+ DWORD csumFolders;
+ DWORD coffFiles;
+ DWORD csumFiles;
+ WORD version;
+ WORD cFolders;
+ WORD cFiles;
+ WORD flags;
+ WORD setID;
+ WORD iCabinet;
+ };
+
+
+ struct MS_CABINET_ITEM
+ {
+ DWORD cbFile;
+ DWORD uoffFolderStart;
+ WORD iFolder;
+ WORD date;
+ WORD time;
+ WORD attribs;
+ };
+
+
+ struct CABC_DUPLICATEFILE
+ {
+ DWORD dwFileIndex;
+ DWORD dwDuplicateFileIndex;
+ };
+
+
+ struct CABC_FILE
+ {
+ DWORD dwIndex;
+ LPWSTR pwzSourcePath;
+ };
+
+
struct CABC_DATA
{
***************
*** 34,37 ****
--- 78,93 ----
CCAB ccab;
TCOMP tc;
+
+ WCHAR wzCabinetPath[MAX_PATH];
+ CHAR szEmptyFile[MAX_PATH];
+ DWORD dwLastFileIndex;
+
+ DWORD cFilePaths;
+ DWORD cMaxFilePaths;
+ CABC_FILE *prgFiles;
+
+ DWORD cDuplicates;
+ DWORD cMaxDuplicates;
+ CABC_DUPLICATEFILE *prgDuplicates;
};
***************
*** 39,42 ****
--- 95,119 ----
// prototypes
//
+ static CABC_FILE* CheckForDuplicateFile(
+ __in CABC_DATA *pcd,
+ __in LPCWSTR wzFileName
+ );
+ static HRESULT AddDuplicateFile(
+ __in CABC_DATA *pcd,
+ __in CABC_FILE *pcf,
+ __in DWORD dwDuplicateFileIndex
+ );
+ static HRESULT AddNonDuplicateFile(
+ __in CABC_DATA *pcd,
+ __in LPCWSTR wzFile,
+ __in DWORD dwFileIndex
+ );
+ static HRESULT UpdateDuplicateFiles(
+ __in CABC_DATA *pcd
+ );
+ static HRESULT DuplicateFile(
+ __in MS_CABINET_HEADER *pHeader,
+ __in CABC_DUPLICATEFILE *pDuplicate
+ );
static int DIAMONDAPI CabCFilePlaced(__in PCCAB pccab, __in char *szFile, __in long cbFile, __in BOOL fContinuation, __out void *pv);
static void * DIAMONDAPI CabCAlloc(__in ULONG cb);
***************
*** 58,64 ****
NOTE: phContext must be the same handle used in AddFile and Finish.
! wzCabDir can be L"", but not NULL. dwMaxSize and dwMaxThresh can
! be NULL. A large default value will be used in that case. tc can be NULL.
! LZX with Lowest Memory will be used as a default.
********************************************************************/
extern "C" HRESULT DAPI CabCBegin(
--- 135,141 ----
NOTE: phContext must be the same handle used in AddFile and Finish.
! wzCabDir can be L"", but not NULL.
! dwMaxSize and dwMaxThresh can be 0. A large default value will be used in that case.
!
********************************************************************/
extern "C" HRESULT DAPI CabCBegin(
***************
*** 75,78 ****
--- 152,156 ----
HRESULT hr = S_OK;
CABC_DATA *pcd = NULL;
+ CHAR szTempPath[MAX_PATH] = { 0 };
WCHAR wzPathBuffer [MAX_PATH] = L"";
***************
*** 84,88 ****
// Need room to terminate with L'\\' and L'\0'
! Assert(cchPathBuffer < (MAX_PATH -1));
hr = StringCchCopyW(wzPathBuffer, countof(wzPathBuffer), wzCabDir);
--- 162,166 ----
// Need room to terminate with L'\\' and L'\0'
! Assert(cchPathBuffer < (MAX_PATH - 1));
hr = StringCchCopyW(wzPathBuffer, countof(wzPathBuffer), wzCabDir);
***************
*** 101,136 ****
if (NULL == dwMaxSize)
pcd->ccab.cb = CAB_MAX_SIZE;
else
pcd->ccab.cb = dwMaxSize;
! if (NULL == dwMaxThresh)
pcd->ccab.cbFolderThresh = CAB_MAX_SIZE;
else
pcd->ccab.cbFolderThresh = dwMaxThresh;
// Translate the compression type
if (COMPRESSION_TYPE_NONE == ct)
pcd->tc = tcompTYPE_NONE;
else if (COMPRESSION_TYPE_LOW == ct)
pcd->tc = tcompTYPE_LZX | tcompLZX_WINDOW_LO;
else if (COMPRESSION_TYPE_MEDIUM == ct)
pcd->tc = TCOMPfromLZXWindow(18);
else if (COMPRESSION_TYPE_HIGH == ct)
pcd->tc = tcompTYPE_LZX | tcompLZX_WINDOW_HI;
else if (COMPRESSION_TYPE_MSZIP == ct)
pcd->tc = tcompTYPE_MSZIP;
else
! ExitOnFailure(hr = E_INVALIDARG, "invalid compression type specified");
if (0 == ::WideCharToMultiByte(CP_ACP, 0, wzCab, -1, pcd->ccab.szCab, sizeof(pcd->ccab.szCab), NULL, NULL))
! ExitOnLastError(hr, "failed to convert cab name to multi-byte");
if (0 == ::WideCharToMultiByte(CP_ACP, 0, wzPathBuffer, -1, pcd->ccab.szCabPath, sizeof(pcd->ccab.szCab), NULL, NULL))
! ExitOnLastError(hr, "failed to convert cab dir to multi-byte");
! pcd->hfci = ::FCICreate(&(pcd->erf), CabCFilePlaced, CabCAlloc, CabCFree, CabCOpen, CabCRead, CabCWrite, CabCClose, CabCSeek, CabCDelete, CabCGetTempFile, &(pcd->ccab), NULL);
! if (pcd->hfci == NULL || pcd->erf.fError)
{
// If we have a last error, use that, otherwise return the useless error
--- 179,256 ----
if (NULL == dwMaxSize)
+ {
pcd->ccab.cb = CAB_MAX_SIZE;
+ }
else
+ {
pcd->ccab.cb = dwMaxSize;
+ }
! if (0 == dwMaxThresh)
! {
pcd->ccab.cbFolderThresh = CAB_MAX_SIZE;
+ }
else
+ {
pcd->ccab.cbFolderThresh = dwMaxThresh;
+ }
// Translate the compression type
if (COMPRESSION_TYPE_NONE == ct)
+ {
pcd->tc = tcompTYPE_NONE;
+ }
else if (COMPRESSION_TYPE_LOW == ct)
+ {
pcd->tc = tcompTYPE_LZX | tcompLZX_WINDOW_LO;
+ }
else if (COMPRESSION_TYPE_MEDIUM == ct)
+ {
pcd->tc = TCOMPfromLZXWindow(18);
+ }
else if (COMPRESSION_TYPE_HIGH == ct)
+ {
pcd->tc = tcompTYPE_LZX | tcompLZX_WINDOW_HI;
+ }
else if (COMPRESSION_TYPE_MSZIP == ct)
+ {
pcd->tc = tcompTYPE_MSZIP;
+ }
else
! {
! ExitOnFailure(hr = E_INVALIDARG, "Invalid compression type specified.");
! }
if (0 == ::WideCharToMultiByte(CP_ACP, 0, wzCab, -1, pcd->ccab.szCab, sizeof(pcd->ccab.szCab), NULL, NULL))
! {
! ExitWithLastError(hr, "failed to convert cab name to multi-byte");
! }
if (0 == ::WideCharToMultiByte(CP_ACP, 0, wzPathBuffer, -1, pcd->ccab.szCabPath, sizeof(pcd->ccab.szCab), NULL, NULL))
! {
! ExitWithLastError(hr, "failed to convert cab dir to multi-byte");
! }
! // Remember the path to the cabinet.
! hr= ::StringCchCopyW(pcd->wzCabinetPath, countof(pcd->wzCabinetPath), wzPathBuffer);
! ExitOnFailure1(hr, "Failed to copy cabinet path from path: %S", wzPathBuffer);
! hr = ::StringCchCatW(pcd->wzCabinetPath, countof(pcd->wzCabinetPath), wzCab);
! ExitOnFailure1(hr, "Failed to concat to cabinet path cabinet name: %S", wzCab);
!
! // Get the empty file to use as the blank marker for duplicates.
! if (!::GetTempPathA(countof(szTempPath), szTempPath))
! {
! ExitWithLastError(hr, "Failed to get temp path.");
! }
!
! if (!::GetTempFileNameA(szTempPath, "WSC", 0, pcd->szEmptyFile))
! {
! ExitWithLastError(hr, "Failed to create a temp file name.");
! }
!
! // Tell cabinet API about our configuration.
! pcd->hfci = ::FCICreate(&(pcd->erf), CabCFilePlaced, CabCAlloc, CabCFree, CabCOpen, CabCRead, CabCWrite, CabCClose, CabCSeek, CabCDelete, CabCGetTempFile, &(pcd->ccab), NULL);
! if (NULL == pcd->hfci || pcd->erf.fError)
{
// If we have a last error, use that, otherwise return the useless error
***************
*** 140,146 ****
--- 260,270 ----
*phContext = pcd;
+
LExit:
if (FAILED(hr) && pcd && pcd->hfci)
+ {
::FCIDestroy(pcd->hfci);
+ }
+
return hr;
}
***************
*** 168,172 ****
extern "C" HRESULT DAPI CabCAddFile(
__in LPCWSTR wzFile,
! __in LPCWSTR wzToken,
__in HANDLE hContext
)
--- 292,296 ----
extern "C" HRESULT DAPI CabCAddFile(
__in LPCWSTR wzFile,
! __in_opt LPCWSTR wzToken,
__in HANDLE hContext
)
***************
*** 179,195 ****
LPSTR pszFileName = NULL;
CABC_DATA *pcd = reinterpret_cast(hContext);
// use the token if given
if (wzToken && *wzToken)
wzFileName = wzToken;
else
wzFileName = FileFromPath(wzFile);
! // convert filenames to ANSI
! hr = StrAnsiAllocString(&pszFile, wzFile, 0, CP_ACP);
! ExitOnFailure1(hr, "failed to convert to ANSI: %S", wzFile);
hr = StrAnsiAllocString(&pszFileName, wzFileName, 0, CP_ACP);
ExitOnFailure1(hr, "failed to convert to ANSI: %S", wzFileName);
// add the file to the cab
if (!::FCIAddFile(pcd->hfci, pszFile, pszFileName, FALSE, CabCGetNextCabinet, CabCStatus, CabCGetOpenInfo, pcd->tc))
--- 303,352 ----
LPSTR pszFileName = NULL;
CABC_DATA *pcd = reinterpret_cast(hContext);
+ CABC_FILE *pcfDuplicate = NULL;
// use the token if given
if (wzToken && *wzToken)
+ {
wzFileName = wzToken;
+ }
else
+ {
wzFileName = FileFromPath(wzFile);
+ }
! pcfDuplicate = CheckForDuplicateFile(pcd, wzFile);
! if (pcfDuplicate)
! {
! // For duplicate files, we point them at our empty (zero-byte) file so it takes up no space
! // in the resultant cabinet. Later on (CabCFinish) we'll go through and change all the zero
! // byte files to point at their duplicated file index.
! //
! // Notice that duplicate files are not added to the list of file paths because all duplicate
! // files point at the same path (the empty file) so there is no point in tracking them with
! // their path.
! hr = StrAnsiAlloc(&pszFile, MAX_PATH);
! ExitOnFailure1(hr, "Failed to allocate space for empty file name: %s", pcd->szEmptyFile);
!
! hr = ::StringCchCopyA(pszFile, MAX_PATH, pcd->szEmptyFile);
! ExitOnFailure1(hr, "Failed to copy empty file name: %s", pcd->szEmptyFile);
!
! hr = AddDuplicateFile(pcd, pcfDuplicate, pcd->dwLastFileIndex);
! ExitOnFailure1(hr, "Failed to add duplicate of file name: %S", pcfDuplicate->pwzSourcePath);
! }
! else
! {
! // Just a normal, non-duplicated file. We'll add it to the list for later checking of
! // duplicates.
! hr = StrAnsiAllocString(&pszFile, wzFile, 0, CP_ACP);
! ExitOnFailure1(hr, "failed to convert to ANSI: %S", wzFile);
!
! hr = AddNonDuplicateFile(pcd, wzFile, pcd->dwLastFileIndex);
! ExitOnFailure1(hr, "Failed to add non-duplicated file: %S", wzFile);
! }
hr = StrAnsiAllocString(&pszFileName, wzFileName, 0, CP_ACP);
ExitOnFailure1(hr, "failed to convert to ANSI: %S", wzFileName);
+ ++pcd->dwLastFileIndex;
+
// add the file to the cab
if (!::FCIAddFile(pcd->hfci, pszFile, pszFileName, FALSE, CabCGetNextCabinet, CabCStatus, CabCGetOpenInfo, pcd->tc))
***************
*** 231,235 ****
::FCIDestroy(pcd->hfci);
! MemFree(pcd);
LExit:
--- 388,405 ----
::FCIDestroy(pcd->hfci);
! if (pcd->cDuplicates)
! {
! hr = UpdateDuplicateFiles(pcd);
! ExitOnFailure1(hr, "Failed to update duplicates in cabinet: %S", pcd->wzCabinetPath);
! }
!
! for (DWORD i = 0; i < pcd->cFilePaths; ++i)
! {
! ReleaseStr(pcd->prgFiles[i].pwzSourcePath);
! }
! ReleaseMem(pcd->prgFiles);
! ReleaseMem(pcd->prgDuplicates);
!
! ReleaseMem(pcd);
LExit:
***************
*** 243,247 ****
/********************************************************************
! FCI callback functions
*********************************************************************/
--- 413,663 ----
/********************************************************************
! SmartCab functions
!
! ********************************************************************/
!
! static CABC_FILE* CheckForDuplicateFile(
! __in CABC_DATA *pcd,
! __in LPCWSTR wzFileName
! )
! {
! HRESULT hr = S_OK;
! CABC_FILE *pcf = NULL;
!
! // TODO: turn this into a binary search to improve perf
! for (DWORD i = 0; i < pcd->cFilePaths; ++i)
! {
! if (CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, pcd->prgFiles[i].pwzSourcePath, -1, wzFileName, -1))
! {
! pcf = pcd->prgFiles + i;
! break;
! }
! }
!
! return pcf;
! }
!
!
! static HRESULT AddDuplicateFile(
! __in CABC_DATA *pcd,
! __in CABC_FILE *pcf,
! __in DWORD dwDuplicateFileIndex
! )
! {
! HRESULT hr = S_OK;
! LPVOID pv = NULL;
!
! // Ensure there is enough memory to store this duplicate file index.
! if (pcd->cDuplicates == pcd->cMaxDuplicates)
! {
! pcd->cMaxDuplicates += 20; // grow by a reasonable number (20 is reasonable, right?)
!
! if (pcd->cDuplicates)
! {
! pv = MemReAlloc(pcd->prgDuplicates, pcd->cMaxDuplicates * sizeof(CABC_DUPLICATEFILE), FALSE);
! ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to reallocate memory for duplicate file.");
! }
! else
! {
! pv = MemAlloc(pcd->cMaxDuplicates * sizeof(CABC_DUPLICATEFILE), FALSE);
! ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for duplicate file.");
! }
!
! ZeroMemory(reinterpret_cast(pv) + (pcd->cDuplicates * sizeof(CABC_DUPLICATEFILE)), (pcd->cMaxDuplicates - pcd->cDuplicates) * sizeof(CABC_DUPLICATEFILE));
!
! pcd->prgDuplicates = static_cast(pv);
! pv = NULL;
! }
!
! // Store the duplicate file index.
! pcd->prgDuplicates[pcd->cDuplicates].dwFileIndex = pcf->dwIndex;
! pcd->prgDuplicates[pcd->cDuplicates].dwDuplicateFileIndex = dwDuplicateFileIndex;
! ++pcd->cDuplicates;
!
! LExit:
! ReleaseMem(pv);
! return hr;
! }
!
!
! static HRESULT AddNonDuplicateFile(
! __in CABC_DATA *pcd,
! __in LPCWSTR wzFile,
! __in DWORD dwFileIndex
! )
! {
! HRESULT hr = S_OK;
! LPVOID pv = NULL;
!
! // Ensure there is enough memory to store this file index.
! if (pcd->cFilePaths == pcd->cMaxFilePaths)
! {
! pcd->cMaxFilePaths += 100; // grow by a reasonable number (100 is reasonable, right?)
!
! if (pcd->cFilePaths)
! {
! pv = MemReAlloc(pcd->prgFiles, pcd->cMaxFilePaths * sizeof(CABC_FILE), FALSE);
! ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to reallocate memory for file.");
! }
! else
! {
! pv = MemAlloc(pcd->cMaxFilePaths * sizeof(CABC_FILE), FALSE);
! ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to allocate memory for file.");
! }
!
! ZeroMemory(reinterpret_cast(pv) + (pcd->cFilePaths * sizeof(CABC_FILE)), (pcd->cMaxFilePaths - pcd->cFilePaths) * sizeof(CABC_FILE));
!
! pcd->prgFiles = static_cast(pv);
! pv = NULL;
! }
!
! // Store the file index information.
! // TODO: add this to a sorted list so we can do a binary search later.
! CABC_FILE *pcf = pcd->prgFiles + pcd->cFilePaths;
! pcf->dwIndex = dwFileIndex;
! hr = StrAllocString(&pcf->pwzSourcePath, wzFile, 0);
! ExitOnFailure1(hr, "Failed to copy file path: %S", wzFile);
! ++pcd->cFilePaths;
!
! LExit:
! ReleaseMem(pv);
! return hr;
! }
!
!
! static HRESULT UpdateDuplicateFiles(
! __in CABC_DATA *pcd
! )
! {
! HRESULT hr = S_OK;
! DWORD cbCabinet = 0;
! LARGE_INTEGER liCabinetSize = { 0 };
! HANDLE hCabinet = INVALID_HANDLE_VALUE;
! HANDLE hCabinetMapping = NULL;
! LPVOID pv = NULL;
! MS_CABINET_HEADER *pCabinetHeader = NULL;
! MS_CABINET_ITEM *pOriginalItem = NULL;
! MS_CABINET_ITEM *pDuplicateItem = NULL;
!
! hCabinet = ::CreateFileW(pcd->wzCabinetPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
! if (INVALID_HANDLE_VALUE == hCabinet)
! {
! ExitWithLastError1(hr, "Failed to open cabinet: %S", pcd->wzCabinetPath);
! }
!
! // Shouldn't need more than 128 MB to get the whole cabinet header into memory so use that as
! // the upper bound for the memory map.
! if (!::GetFileSizeEx(hCabinet, &liCabinetSize))
! {
! ExitWithLastError1(hr, "Failed to get size of cabinet: %S", pcd->wzCabinetPath);
! }
!
! if (0 == liCabinetSize.HighPart && liCabinetSize.LowPart < ONEHUNDRED_TWENTYEIGHT_MB)
! {
! cbCabinet = liCabinetSize.LowPart;
! }
! else
! {
! cbCabinet = ONEHUNDRED_TWENTYEIGHT_MB;
! }
!
! hCabinetMapping = ::CreateFileMappingW(hCabinet, NULL, PAGE_READWRITE | SEC_COMMIT, 0, cbCabinet, NULL);
! if (INVALID_HANDLE_VALUE == hCabinetMapping)
! {
! ExitWithLastError1(hr, "Failed to memory map cabinet file: %S", pcd->wzCabinetPath);
! }
!
! pv = ::MapViewOfFile(hCabinetMapping, FILE_MAP_WRITE, 0, 0, 0);
! ExitOnNullWithLastError1(pv, hr, "Failed to map view of cabinet file: %S", pcd->wzCabinetPath);
!
! pCabinetHeader = static_cast(pv);
!
! for (DWORD i = 0; i < pcd->cDuplicates; ++i)
! {
! CABC_DUPLICATEFILE *pDuplicateFile = pcd->prgDuplicates + i;
!
! hr = DuplicateFile(pCabinetHeader, pDuplicateFile);
! ExitOnFailure2(hr, "Failed to find cabinet file items at index: %d and %d", pDuplicateFile->dwFileIndex, pDuplicateFile->dwDuplicateFileIndex);
! }
!
! LExit:
! if (pv)
! {
! ::UnmapViewOfFile(pv);
! }
! if (hCabinetMapping)
! {
! ::CloseHandle(hCabinetMapping);
! }
! if (INVALID_HANDLE_VALUE != hCabinet)
! {
! ::CloseHandle(hCabinet);
! }
!
! return hr;
! }
!
!
! static HRESULT DuplicateFile(
! __in MS_CABINET_HEADER *pHeader,
! __in CABC_DUPLICATEFILE *pDuplicate
! )
! {
! HRESULT hr = S_OK;
! BYTE *pbHeader = reinterpret_cast(pHeader);
! BYTE* pbItem = pbHeader + pHeader->coffFiles;
! MS_CABINET_ITEM *pOriginalItem = NULL;
! MS_CABINET_ITEM *pDuplicateItem = NULL;
!
! if (pHeader->cFiles dwFileIndex ||
! pHeader->cFiles dwDuplicateFileIndex ||
! pDuplicate->dwDuplicateFileIndex dwFileIndex)
! {
! hr = E_UNEXPECTED;
! ExitOnFailure3(hr, "Unexpected duplicate file indicies, header cFiles: %d, file index: %d, duplicate index: %d", pHeader->cFiles, pDuplicate->dwFileIndex, pDuplicate->dwDuplicateFileIndex);
! }
!
! // Step through each cabinet items until we get to the original
! // file's index. Notice that the name of the cabinet item is
! // appended to the end of the MS_CABINET_INFO, that's why we can't
! // index straight to the data we want.
! for (DWORD i = 0; i < pDuplicate->dwFileIndex; ++i)
! {
! LPSTR szItemName = reinterpret_cast(pbItem + sizeof(MS_CABINET_ITEM));
! pbItem = pbItem + sizeof(MS_CABINET_ITEM) + lstrlenA(szItemName) + 1;
! }
!
! pOriginalItem = reinterpret_cast(pbItem);
!
! // Now pick up where we left off after the original file's index
! // was found and loop until we find the duplicate file's index.
! for (DWORD i = pDuplicate->dwFileIndex; i < pDuplicate->dwDuplicateFileIndex; ++i)
! {
! LPSTR szItemName = reinterpret_cast(pbItem + sizeof(MS_CABINET_ITEM));
! pbItem = pbItem + sizeof(MS_CABINET_ITEM) + lstrlenA(szItemName) + 1;
! }
!
! pDuplicateItem = reinterpret_cast(pbItem);
!
! if (0 != pDuplicateItem->cbFile)
! {
! hr = E_UNEXPECTED;
! ExitOnFailure1(hr, "Failed because duplicate file does not have a file size of zero: %d", pDuplicateItem->cbFile);
! }
!
! pDuplicateItem->cbFile = pOriginalItem->cbFile;
! pDuplicateItem->uoffFolderStart = pOriginalItem->uoffFolderStart;
! pDuplicateItem->iFolder = pOriginalItem->iFolder;
! pDuplicateItem->date = pOriginalItem->date;
! pDuplicateItem->time = pOriginalItem->time;
! pDuplicateItem->attribs = pOriginalItem->attribs;
!
! LExit:
! return hr;
! }
!
!
! /********************************************************************
! FCI callback functions
*********************************************************************/
Index: procutil.cpp
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/procutil.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** procutil.cpp 13 Dec 2006 07:44:20 -0000 1.1
--- procutil.cpp 27 Jun 2007 05:36:19 -0000 1.2
***************
*** 2,5 ****
--- 2,13 ----
//
// Copyright (c) Microsoft Corporation. All rights reserved.
+ //
+ // The use and distribution terms for this software are covered by the
+ // Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ // which can be found in the file CPL.TXT at the root of this distribution.
+ // By using this software in any fashion, you are agreeing to be bound by
+ // the terms of this license.
+ //
+ // You must not remove this notice, or any other, from this software.
//
//
Index: proc2utl.cpp
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/proc2utl.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** proc2utl.cpp 13 Dec 2006 07:44:20 -0000 1.1
--- proc2utl.cpp 27 Jun 2007 05:36:19 -0000 1.2
***************
*** 2,5 ****
--- 2,13 ----
//
// Copyright (c) Microsoft Corporation. All rights reserved.
+ //
+ // The use and distribution terms for this software are covered by the
+ // Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ // which can be found in the file CPL.TXT at the root of this distribution.
+ // By using this software in any fashion, you are agreeing to be bound by
+ // the terms of this license.
+ //
+ // You must not remove this notice, or any other, from this software.
//
//
Index: sqlutil.h
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/sqlutil.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** sqlutil.h 16 Feb 2007 09:35:05 -0000 1.7
--- sqlutil.h 27 Jun 2007 05:36:19 -0000 1.8
***************
*** 20,24 ****
#include
#include
- #include
#include
--- 20,23 ----
Index: fileutil.cpp
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/fileutil.cpp,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** fileutil.cpp 13 Dec 2006 07:44:20 -0000 1.12
--- fileutil.cpp 27 Jun 2007 05:36:19 -0000 1.13
***************
*** 24,45 ****
********************************************************************/
extern "C" LPWSTR DAPI FileFromPath(
! __in LPCWSTR wzPath
! )
{
! if (!wzPath)
! return NULL;
! LPWSTR wzFile = const_cast(wzPath);
! for (LPWSTR wz = wzFile; *wz; wz++)
! {
! // valid delineators
! // \ => Windows path
! // / => unix and URL path
! // : => relative path from mapped root
! if (L'\\' == *wz || L'/' == *wz || L':' == *wz)
! wzFile = wz + 1;
! }
! return wzFile;
}
--- 24,45 ----
********************************************************************/
extern "C" LPWSTR DAPI FileFromPath(
! __in LPCWSTR wzPath
! )
{
! if (!wzPath)
! return NULL;
! LPWSTR wzFile = const_cast(wzPath);
! for (LPWSTR wz = wzFile; *wz; wz++)
! {
! // valid delineators
! // \ => Windows path
! // / => unix and URL path
! // : => relative path from mapped root
! if (L'\\' == *wz || L'/' == *wz || L':' == *wz)
! wzFile = wz + 1;
! }
! return wzFile;
}
***************
*** 51,138 ****
********************************************************************/
extern "C" HRESULT DAPI FileResolvePath(
! __in LPCWSTR wzRelativePath,
! __out LPWSTR *ppwzFullPath
! )
{
! Assert(wzRelativePath && *wzRelativePath);
! HRESULT hr = S_OK;
! DWORD cch = 0;
! LPWSTR pwzExpandedPath = NULL;
! DWORD cchExpandedPath = 0;
! LPWSTR pwzFullPath = NULL;
! DWORD cchFullPath = 0;
! LPWSTR wzFileName = NULL;
! //
! // First, expand any environment variables.
! //
! cchExpandedPath = MAX_PATH;
! hr = StrAlloc(&pwzExpandedPath, cchExpandedPath);
! ExitOnFailure(hr, "Failed to allocate space for expanded path.");
! cch = ::ExpandEnvironmentStringsW(wzRelativePath, pwzExpandedPath, cchExpandedPath);
! if (0 == cch)
! {
! ExitWithLastError1(hr, "Failed to expand environment variables in string: %S", wzRelativePath);
! }
! else if (cchExpandedPath < cch)
! {
! cchExpandedPath = cch;
! hr = StrAlloc(&pwzExpandedPath, cchExpandedPath);
! ExitOnFailure(hr, "Failed to re-allocate more space for expanded path.");
! cch = ::ExpandEnvironmentStringsW(wzRelativePath, pwzExpandedPath, cchExpandedPath);
! if (0 == cch)
! {
! ExitWithLastError1(hr, "Failed to expand environment variables in string: %S", wzRelativePath);
! }
! else if (cchExpandedPath < cch)
! {
! hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
! ExitOnFailure(hr, "Failed to allocate buffer for expanded path.");
! }
! }
! //
! // Second, get the full path.
! //
! cchFullPath = MAX_PATH;
! hr = StrAlloc(&pwzFullPath, cchFullPath);
! ExitOnFailure(hr, "Failed to allocate space for full path.");
! cch = ::GetFullPathNameW(pwzExpandedPath, cchFullPath, pwzFullPath, &wzFileName);
! if (0 == cch)
! {
! ExitWithLastError1(hr, "Failed to get full path for string: %S", pwzExpandedPath);
! }
! else if (cchFullPath < cch)
! {
! cchFullPath = cch;
! hr = StrAlloc(&pwzFullPath, cchFullPath);
! ExitOnFailure(hr, "Failed to re-allocate more space for full path.");
! cch = ::GetFullPathNameW(pwzExpandedPath, cchFullPath, pwzFullPath, &wzFileName);
! if (0 == cch)
! {
! ExitWithLastError1(hr, "Failed to get full path for string: %S", pwzExpandedPath);
! }
! else if (cchFullPath < cch)
! {
! hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
! ExitOnFailure(hr, "Failed to allocate buffer for full path.");
! }
! }
! *ppwzFullPath = pwzFullPath;
! pwzFullPath = NULL;
LExit:
! ReleaseStr(pwzFullPath);
! ReleaseStr(pwzExpandedPath);
! return hr;
}
--- 51,187 ----
********************************************************************/
extern "C" HRESULT DAPI FileResolvePath(
! __in LPCWSTR wzRelativePath,
! __out LPWSTR *ppwzFullPath
! )
{
! Assert(wzRelativePath && *wzRelativePath);
! HRESULT hr = S_OK;
! DWORD cch = 0;
! LPWSTR pwzExpandedPath = NULL;
! DWORD cchExpandedPath = 0;
! LPWSTR pwzFullPath = NULL;
! DWORD cchFullPath = 0;
! LPWSTR wzFileName = NULL;
! //
! // First, expand any environment variables.
! //
! cchExpandedPath = MAX_PATH;
! hr = StrAlloc(&pwzExpandedPath, cchExpandedPath);
! ExitOnFailure(hr, "Failed to allocate space for expanded path.");
! cch = ::ExpandEnvironmentStringsW(wzRelativePath, pwzExpandedPath, cchExpandedPath);
! if (0 == cch)
! {
! ExitWithLastError1(hr, "Failed to expand environment variables in string: %S", wzRelativePath);
! }
! else if (cchExpandedPath < cch)
! {
! cchExpandedPath = cch;
! hr = StrAlloc(&pwzExpandedPath, cchExpandedPath);
! ExitOnFailure(hr, "Failed to re-allocate more space for expanded path.");
! cch = ::ExpandEnvironmentStringsW(wzRelativePath, pwzExpandedPath, cchExpandedPath);
! if (0 == cch)
! {
! ExitWithLastError1(hr, "Failed to expand environment variables in string: %S", wzRelativePath);
! }
! else if (cchExpandedPath < cch)
! {
! hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
! ExitOnFailure(hr, "Failed to allocate buffer for expanded path.");
! }
! }
! //
! // Second, get the full path.
! //
! cchFullPath = MAX_PATH;
! hr = StrAlloc(&pwzFullPath, cchFullPath);
! ExitOnFailure(hr, "Failed to allocate space for full path.");
! cch = ::GetFullPathNameW(pwzExpandedPath, cchFullPath, pwzFullPath, &wzFileName);
! if (0 == cch)
! {
! ExitWithLastError1(hr, "Failed to get full path for string: %S", pwzExpandedPath);
! }
! else if (cchFullPath < cch)
! {
! cchFullPath = cch;
! hr = StrAlloc(&pwzFullPath, cchFullPath);
! ExitOnFailure(hr, "Failed to re-allocate more space for full path.");
! cch = ::GetFullPathNameW(pwzExpandedPath, cchFullPath, pwzFullPath, &wzFileName);
! if (0 == cch)
! {
! ExitWithLastError1(hr, "Failed to get full path for string: %S", pwzExpandedPath);
! }
! else if (cchFullPath < cch)
! {
! hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
! ExitOnFailure(hr, "Failed to allocate buffer for full path.");
! }
! }
! *ppwzFullPath = pwzFullPath;
! pwzFullPath = NULL;
LExit:
! ReleaseStr(pwzFullPath);
! ReleaseStr(pwzExpandedPath);
! return hr;
! }
!
!
! /*******************************************************************
! FileStripExtension - Strip extension from filename
! ********************************************************************/
! extern "C" HRESULT DAPI FileStripExtension(
! __in LPCWSTR wzFileName,
! __out LPWSTR *ppwzFileNameNoExtension
! )
! {
! Assert(wzFileName && *wzFileName);
!
! HRESULT hr = S_OK;
!
! DWORD cchFileName = wcslen(wzFileName);
!
! LPWSTR pwzFileNameNoExtension = NULL;
! DWORD cchFileNameNoExtension = 0;
!
! // Filename without extension can not be longer than _MAX_FNAME
! // Filename without extension should also not be longer than filename itself
! if (_MAX_FNAME > cchFileName)
! {
! cchFileNameNoExtension = cchFileName;
! }
! else
! {
! cchFileNameNoExtension = _MAX_FNAME;
! }
!
! hr = StrAlloc(&pwzFileNameNoExtension, cchFileNameNoExtension);
! ExitOnFailure(hr, "failed to allocate space for File Name without extension");
!
! // _wsplitpath_s can handle drive/path/filename/extension
! errno_t err = _wsplitpath_s(wzFileName, NULL, NULL, NULL, NULL, pwzFileNameNoExtension, cchFileNameNoExtension, NULL, NULL);
! if (0 != err)
! {
! hr = E_INVALIDARG;
! ExitOnFailure1(hr, "failed to parse filename: %S", wzFileName);
! }
!
! *ppwzFileNameNoExtension = pwzFileNameNoExtension;
! pwzFileNameNoExtension = NULL;
!
! LExit:
! ReleaseStr(pwzFileNameNoExtension);
!
! return hr;
}
***************
*** 143,202 ****
*******************************************************************/
extern "C" HRESULT DAPI FileVersionFromString(
! __in LPCWSTR wzVersion,
! __out DWORD *pdwVerMajor,
! __out DWORD* pdwVerMinor
! )
{
! Assert(pdwVerMajor && pdwVerMinor);
! HRESULT hr = S_OK;
! LPCWSTR pwz = wzVersion;
! DWORD dw;
! dw = wcstoul(pwz, (WCHAR**)&pwz, 10);
! if (pwz && L'.' == *pwz && dw < 0x10000)
! {
! *pdwVerMajor = dw relative path from mapped root
! if (L'\\' == *wz || L'/' == *wz || (L':' == *wz && wz == wzPath + 1))
! {
wzFile = wz + 1;
+ }
}
***************
*** 48,51 ****
--- 52,87 ----
/*******************************************************************
+ PathGetDirectory - extracts the directory from a path.
+
+ ********************************************************************/
+ extern "C" HRESULT DAPI PathGetDirectory(
+ __in LPCWSTR wzPath,
+ __out LPWSTR *ppwzDirectory
+ )
+ {
+ HRESULT hr = S_OK;
+ DWORD cchDirectory = 0;
+
+ for (LPCWSTR wz = wzPath; *wz; wz++)
+ {
+ // valid delineators:
+ // \ => Windows path
+ // / => unix and URL path
+ // : => relative path from mapped root
+ if (L'\\' == *wz || L'/' == *wz || (L':' == *wz && wz == wzPath + 1))
+ {
+ cchDirectory = wz - wzPath + 1;
+ }
+ }
+
+ hr = StrAllocString(ppwzDirectory, wzPath, cchDirectory);
+ ExitOnFailure(hr, "Failed to copy directory.");
+
+ LExit:
+ return hr;
+ }
+
+
+ /*******************************************************************
PathExpand - gets the full path to a file resolving environment
variables along the way.
***************
*** 247,251 ****
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
! else if (wzPath[cLength - 1] != L'\\')
{
wzPath[cLength] = L'\\';
--- 283,287 ----
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
! else if (L'\\' != wzPath[cLength - 1])
{
wzPath[cLength] = L'\\';
***************
*** 265,278 ****
HRESULT hr = S_OK;
! DWORD_PTR cbPath = 0;
size_t cLength = 0;
! hr = StrSize(*ppwzPath, &cbPath);
ExitOnFailure(hr, "Failed to get size of path string.");
! hr = ::StringCbLengthW(*ppwzPath, cbPath, &cLength);
ExitOnFailure(hr, "Failed to get length of path.");
! if ((*ppwzPath)[cLength - 1] != L'\\')
{
hr = StrAllocConcat(ppwzPath, L"\\", 1);
--- 301,314 ----
HRESULT hr = S_OK;
! DWORD_PTR cchPath = 0;
size_t cLength = 0;
! hr = StrMaxLength(*ppwzPath, &cchPath);
ExitOnFailure(hr, "Failed to get size of path string.");
! hr = ::StringCchLengthW(*ppwzPath, cchPath, &cLength);
ExitOnFailure(hr, "Failed to get length of path.");
! if (L'\\' != (*ppwzPath)[cLength - 1])
{
hr = StrAllocConcat(ppwzPath, L"\\", 1);
***************
*** 283,284 ****
--- 319,560 ----
return hr;
}
+
+
+ /*******************************************************************
+ PathForCurrentProcess - gets the full path to the currently executing
+ process or (optinally) a module inside the process.
+
+ ********************************************************************/
+ extern "C" HRESULT DAPI PathForCurrentProcess(
+ __inout LPWSTR *ppwzFullPath,
+ __in_opt HMODULE hModule
+ )
+ {
+ HRESULT hr = S_OK;
+ DWORD cch = MAX_PATH;
+
+ do
+ {
+ hr = StrAlloc(ppwzFullPath, cch);
+ ExitOnFailure(hr, "Failed to allocate string for module path.");
+
+ DWORD cchRequired = ::GetModuleFileNameW(hModule, *ppwzFullPath, cch);
+ if (0 == cchRequired)
+ {
+ ExitWithLastError(hr, "Failed to get path for executing process.");
+ }
+ else if (cchRequired == cch)
+ {
+ cch = cchRequired + 1;
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ else
+ {
+ hr = S_OK;
+ }
+ } while (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr);
+
+ LExit:
+ return hr;
+ }
+
+
+ /*******************************************************************
+ PathCreateTempFile
+
+ Note: if wzDirectory is null, ::GetTempPath() will be used instead.
+ if wzFileNameTemplate is null, GetTempFileName() will be used instead.
+ *******************************************************************/
+ extern "C" HRESULT DAPI PathCreateTempFile(
+ __in_opt LPCWSTR wzDirectory,
+ __in_opt __format_string LPCWSTR wzFileNameTemplate,
+ __in DWORD dwUniqueCount,
+ __in DWORD dwFileAttributes,
+ __out_opt LPWSTR* ppwzTempFile,
+ __out_opt HANDLE* phTempFile
+ )
+ {
+ AssertSz(0 == dwUniqueCount, "Must specify a non-zero unique count.");
+
+ HRESULT hr = S_OK;
+
+ LPWSTR pwzTempPath = NULL;
+ DWORD cchTempPath = MAX_PATH;
+
+ HANDLE hTempFile = INVALID_HANDLE_VALUE;
+ LPWSTR pwz = NULL;
+ LPWSTR pwzTempFile = NULL;
+
+ if (wzDirectory && *wzDirectory)
+ {
+ hr = StrAllocString(&pwzTempPath, wzDirectory, 0);
+ ExitOnFailure(hr, "Failed to copy temp path.");
+ }
+ else
+ {
+ hr = StrAlloc(&pwzTempPath, cchTempPath);
+ ExitOnFailure(hr, "Failed to allocate memory for the temp path.");
+
+ if (!::GetTempPathW(cchTempPath, pwzTempPath))
+ {
+ ExitWithLastError(hr, "Failed to get temp path.");
+ }
+ }
+
+ if (wzFileNameTemplate && *wzFileNameTemplate)
+ {
+ for (DWORD i = 1; i put_validateOnParse(VARIANT_FALSE);
***************
*** 213,216 ****
--- 233,250 ----
)
{
+ return XmlLoadDocumentFromFileEx(wzPath, 0, ppixdDocument);
+ }
+
+
+ /*******************************************************************
+ XmlLoadDocumentFromFileEx
+
+ ********************************************************************/
+ extern "C" HRESULT DAPI XmlLoadDocumentFromFileEx(
+ __in LPCWSTR wzPath,
+ __in DWORD dwAttributes,
+ __out IXMLDOMDocument** ppixdDocument
+ )
+ {
HRESULT hr;
VARIANT varPath;
***************
*** 229,232 ****
--- 263,272 ----
ExitOnFailure(hr, "failed XmlCreateDocument");
+ if (dwAttributes & XML_LOAD_PRESERVE_WHITESPACE)
+ {
+ hr = pixd->put_preserveWhiteSpace(VARIANT_TRUE);
+ ExitOnFailure(hr, "failed put_preserveWhiteSpace");
+ }
+
pixd->put_async(VARIANT_FALSE);
hr = pixd->load(varPath, &vbSuccess);
Index: procutil.h
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/procutil.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** procutil.h 13 Dec 2006 07:44:20 -0000 1.1
--- procutil.h 27 Jun 2007 05:36:19 -0000 1.2
***************
*** 3,6 ****
--- 3,14 ----
//
// Copyright (c) Microsoft Corporation. All rights reserved.
+ //
+ // The use and distribution terms for this software are covered by the
+ // Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
+ // which can be found in the file CPL.TXT at the root of this distribution.
+ // By using this software in any fashion, you are agreeing to be bound by
+ // the terms of this license.
+ //
+ // You must not remove this notice, or any other, from this software.
//
//
Index: dirutil.cpp
===================================================================
RCS file: /cvsroot/wix/wix/src/dutil/dirutil.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** dirutil.cpp 5 Apr 2006 07:24:55 -0000 1.5
--- dirutil.cpp 27 Jun 2007 05:36:19 -0000 1.6
***************
*** 2,6 ****
//
// Copyright (c) Microsoft Corporation. All rights reserved.
! //
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
--- 2,6 ----
//
// Copyright (c) Microsoft Corporation. All rights reserved.
! //
// The use and distribution terms for this software are covered by the
// Common Public License 1.0 (http://opensource.org/licenses/cpl.php)
***************
*** 8,12 ****
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license.
! //
// You must not remove this notice, or any other, from this software.
//
--- 8,12 ----
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license.
! //
// You must not remove this notice, or any other, from this software.
//
***************
*** 25,50 ****
*******************************************************************/
extern "C" BOOL DAPI DirExists(
! __in LPCWSTR wzPath,
! __out_opt DWORD *pdwAttributes
! )
{
! Assert(wzPath);
! HRESULT hr = S_OK;
! BOOL fExists = FALSE;
! DWORD dwAttributes = ::GetFileAttributesW(wzPath);
! if (0xFFFFFFFF == dwAttributes) // TODO: figure out why "INVALID_FILE_ATTRIBUTES" can't be used here
! ExitFunction();
! if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
! {
! if (pdwAttributes)
! *pdwAttributes = dwAttributes;
! fExists = TRUE;
! }
LExit:
! return fExists;
}
--- 25,55 ----
*******************************************************************/
extern "C" BOOL DAPI DirExists(
! __in LPCWSTR wzPath,
! __out_opt DWORD *pdwAttributes
! )
{
! Assert(wzPath);
! HRESULT hr = S_OK;
! BOOL fExists = FALSE;
! DWORD dwAttributes = ::GetFileAttributesW(wzPath);
! if (0xFFFFFFFF == dwAttributes) // TODO: figure out why "INVALID_FILE_ATTRIBUTES" can't be used here
! {
! ExitFunction();
! }
! if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
! {
! if (pdwAttributes)
! {
! *pdwAttributes = dwAttributes;
! }
!
! fExists = TRUE;
! }
LExit:
! return fExists;
}
***************
*** 53,87 ****
DirCreateTempPath
! *******************************************************************/
extern "C" HRESULT DAPI DirCreateTempPath(
! __in LPCWSTR wzPrefix,
! __in LPWSTR wzPath,
! __in DWORD cchPath
! )
{
! Assert(wzPrefix);
! Assert(wzPath);
! HRESULT hr = S_OK;
! WCHAR wzDir[MAX_PATH];
! WCHAR wzFile[MAX_PATH];
! DWORD cch = 0;
! cch = ::GetTempPathW(countof(wzDir), wzDir);
! if (!cch || cch >= countof(wzDir))
! {
! ExitWithLastError(hr, "Failed to GetTempPath.");
! }
! if (!::GetTempFileNameW(wzDir, wzPrefix, 0, wzFile))
! {
! ExitWithLastError(hr, "Failed to GetTempFileName.");
! }
! hr = ::StringCchCopyW(wzPath, cchPath, wzFile);
LExit:
! return hr;
}
--- 58,92 ----
DirCreateTempPath
! *******************************************************************/
extern "C" HRESULT DAPI DirCreateTempPath(
! __in LPCWSTR wzPrefix,
! __in LPWSTR wzPath,
! __in DWORD cchPath
! )
{
! Assert(wzPrefix);
! Assert(wzPath);
! HRESULT hr = S_OK;
! WCHAR wzDir[MAX_PATH];
! WCHAR wzFile[MAX_PATH];
! DWORD cch = 0;
! cch = ::GetTempPathW(countof(wzDir), wzDir);
! if (!cch || cch >= countof(wzDir))
! {
! ExitWithLastError(hr, "Failed to GetTempPath.");
! }
! if (!::GetTempFileNameW(wzDir, wzPrefix, 0, wzFile))
! {
! ExitWithLastError(hr, "Failed to GetTempFileName.");
! }
! hr = ::StringCchCopyW(wzPath, cchPath, wzFile);
LExit:
! return hr;
}
***************
*** 92,139 ****
*******************************************************************/
extern "C" HRESULT DAPI DirEnsureExists(
! __in LPCWSTR wzPath,
! __in_opt LPSECURITY_ATTRIBUTES psa
! )
{
! HRESULT hr = S_OK;
! UINT er;
! // try to create this directory
! if (!::CreateDirectoryW(wzPath, psa))
! {
! // if the directory already exists, bail
! er = ::GetLastError();
! if (ERROR_ALREADY_EXISTS == er)
! ExitFunction1(hr = S_OK);
! // get the parent path and try to create it
! LPWSTR pwzLastSlash = NULL;
! for (LPWSTR pwz = const_cast(wzPath); *pwz; pwz++)
! if (*pwz == L'\\')
! pwzLastSlash = pwz;
! // if there is no parent directory fail
! ExitOnNullDebugTrace(pwzLastSlash, hr, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "cannot find parent path");
! *pwzLastSlash = L'\0'; // null terminate the parent path
! hr = DirEnsureExists(wzPath, psa); // recurse!
! *pwzLastSlash = L'\\'; // put the slash back
! ExitOnFailureDebugTrace1(hr, "failed to create path: %S", wzPath);
! // try to create the directory now that all parents are created
! if (!::CreateDirectoryW(wzPath, psa))
! {
! // if the directory already exists for some reason no error
! er = ::GetLastError();
! if (ERROR_ALREADY_EXISTS == er)
! hr = S_FALSE;
! else
! hr = HRESULT_FROM_WIN32(er);
! }
! else
! hr = S_OK;
! }
LExit:
! return hr;
}
--- 97,286 ----
*******************************************************************/
extern "C" HRESULT DAPI DirEnsureExists(
! __in LPCWSTR wzPath,
! __in_opt LPSECURITY_ATTRIBUTES psa
! )
{
! HRESULT hr = S_OK;
! UINT er;
! // try to create this directory
! if (!::CreateDirectoryW(wzPath, psa))
! {
! // if the directory already exists, bail
! er = ::GetLastError();
! if (ERROR_ALREADY_EXISTS == er)
! {
! ExitFunction1(hr = S_OK);
! }
! // get the parent path and try to create it
! LPWSTR pwzLastSlash = NULL;
! for (LPWSTR pwz = const_cast(wzPath); *pwz; pwz++)
! {
! if (*pwz == L'\\')
! {
! pwzLastSlash = pwz;
! }
! }
! // if there is no parent directory fail
! ExitOnNullDebugTrace(pwzLastSlash, hr, HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "cannot find parent path");
! *pwzLastSlash = L'\0'; // null terminate the parent path
! hr = DirEnsureExists(wzPath, psa); // recurse!
! *pwzLastSlash = L'\\'; // put the slash back
! ExitOnFailureDebugTrace1(hr, "failed to create path: %S", wzPath);
! // try to create the directory now that all parents are created
! if (!::CreateDirectoryW(wzPath, psa))
! {
! // if the directory already exists for some reason no error
! er = ::GetLastError();
! if (ERROR_ALREADY_EXISTS == er)
! {
! hr = S_FALSE;
! }
! else
! {
! hr = HRESULT_FROM_WIN32(er);
! }
! }
! else
! {
! hr = S_OK;
! }
! }
LExit:
! return hr;
! }
!
!
! /*******************************************************************
! DirEnsureDelete - removes an entire directory structure
!
! NOTE: path must be in canonical form
! *******************************************************************/
! extern "C" HRESULT DAPI DirEnsureDelete(
! __in LPCWSTR wzPath,
! __in BOOL fDeleteFiles,
! __in BOOL fRecurse
! )
! {
! Assert(wzPath && *wzPath);
!
! HRESULT hr = S_OK;
! DWORD er;
!
! DWORD dwAttrib;
! HANDLE hFind = INVALID_HANDLE_VALUE;
! LPWSTR pwzDelete = NULL;
! WIN32_FIND_DATAW wfd;
!
! if (-1 == (dwAttrib = ::GetFileAttributesW(wzPath)))
! {
! ExitOnLastError1(hr, "Failed to get attributes for path: %S", wzPath);
! }
!
! if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)
! {
! if (dwAttrib & FILE_ATTRIBUTE_READONLY)
! {
! if (!::SetFileAttributesW(wzPath, FILE_ATTRIBUTE_NORMAL))
! {
! ExitOnLastError1(hr, "Failed to remove read-only attribute from path: %S", wzPath);
! }
! }
!
! // If we're not recursing, just exit and we'll try to delete this path alone down
! // below.
! if (!fDeleteFiles && !fRecurse)
! {
! ExitFunction1(hr = S_OK);
! }
!
! // Delete everything in this directory.
! hr = StrAllocString(&pwzDelete, wzPath, 0);
! ExitOnFailure1(hr, "Failed to copy source string: %S", wzPath);
! hr = StrAllocConcat(&pwzDelete, L"\\*.*", 0);
! ExitOnFailure1(hr, "Failed to concat wild cards to string: %S", pwzDelete);
!
! hFind = ::FindFirstFileW(pwzDelete, &wfd);
! if (INVALID_HANDLE_VALUE == hFind)
! {
! ExitOnLastError1(hr, "failed to get first file in directory: %S", wzPath);
! }
!
! do
! {
! // Skip the dot directories.
! if (L'.' == wfd.cFileName[0] && (L'\0' == wfd.cFileName[1] || (L'.' == wfd.cFileName[1] && L'\0' == wfd.cFileName[2])))
! {
! continue;
! }
!
! hr = StrAllocString(&pwzDelete, wzPath, 0);
! ExitOnFailure1(hr, "Failed to copy source string: %S", wzPath);
! hr = StrAllocConcat(&pwzDelete, wfd.cFileName, 0);
! ExitOnFailure2(hr, "Failed to concat filename '%S' to string: %S", wfd.cFileName, pwzDelete);
!
! if (fRecurse && wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
! {
! hr = StrAllocConcat(&pwzDelete, L"\\", 0);
! ExitOnFailure1(hr, "Failed to concat \\ to string: %S", pwzDelete);
!
! hr = DirEnsureDelete(pwzDelete, fDeleteFiles, fRecurse); // recursive call
! ExitOnFailure1(hr, "Failed to delete: %S", pwzDelete);
! }
! else if (fDeleteFiles) // this is a file, just delete it
! {
! if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY || wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN || wfd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
! {
! if (!::SetFileAttributesW(pwzDelete, FILE_ATTRIBUTE_NORMAL))
! {
! ExitOnLastError1(hr, "Failed to remove attributes from file: %S", pwzDelete);
! }
! }
!
! if (!::DeleteFileW(pwzDelete))
! {
! ExitOnLastError1(hr, "Failed to delete file: %S", pwzDelete);
! }
! }
! } while (::FindNextFileW(hFind, &wfd));
!
! er = ::GetLastError();
! if (ERROR_NO_MORE_FILES == er)
! {
! hr = S_OK;
! }
! else
! {
! hr = HRESULT_FROM_WIN32(er);
! ExitOnFailure1(hr, "Failed while looping through files in directory: %S", wzPath);
! }
! }
! else
! {
! hr = E_UNEXPECTED;
! ExitOnFailure1(hr, "Directory delete cannot delete file: %S", wzPath);
! }
!
! Assert(S_OK == hr);
! LExit:
! if (INVALID_HANDLE_VALUE != hFind)
! {
! ::FindClose(hFind);
! }
!
! ReleaseStr(pwzDelete);
!
! // If all is well so far, try to remove the directory
! if (SUCCEEDED(hr) && !::RemoveDirectoryW(wzPath))
! {
! er = ::GetLastError();
! hr = HRESULT_FROM_WIN32(er);
! }
!
! return hr;
}
------------------------------
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
------------------------------
_______________________________________________
Wix-commits mailing list
Wix-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wix-commits
End of Wix-commits Digest, Vol 11, Issue 54
*******************************************
P.S. И не забудьте послать роботу вашу рекламу :)
Обработано объявлений: 11776
Стас Давыдов & Outcorp © 2007