[Msi2xml-users] CVS: msi2xml/msi2xml msi2xml.cpp,1.8,1.9
Brought to you by:
dgehriger
|
From: Daniel G. <dge...@us...> - 2002-10-27 19:25:41
|
Update of /cvsroot/msi2xml/msi2xml/msi2xml
In directory usw-pr-cvs1:/tmp/cvs-serv6198/msi2xml
Modified Files:
msi2xml.cpp
Log Message:
no message
Index: msi2xml.cpp
===================================================================
RCS file: /cvsroot/msi2xml/msi2xml/msi2xml/msi2xml.cpp,v
retrieving revision 1.8
retrieving revision 1.9
diff -C2 -d -r1.8 -r1.9
*** msi2xml.cpp 26 Oct 2002 16:50:29 -0000 1.8
--- msi2xml.cpp 27 Oct 2002 19:23:46 -0000 1.9
***************
*** 1,3 ****
! //------------------------------------------------------------------
//
// $Id$
--- 1,3 ----
! //------------------------------------------------------------------------------
//
// $Id$
***************
*** 24,28 ****
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
! //------------------------------------------------------------------
#include "stdafx.h"
#include "resource.h"
--- 24,28 ----
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
! //------------------------------------------------------------------------------
#include "stdafx.h"
#include "resource.h"
***************
*** 33,39 ****
#include "_BldNum.h"
! //------------------------------------------------------------------
// MS-XML include files
! //------------------------------------------------------------------
#if _MSC_VER >= 1200
#import <msxml4.dll> rename_namespace("xml")
--- 33,39 ----
#include "_BldNum.h"
! //------------------------------------------------------------------------------
// MS-XML include files
! //------------------------------------------------------------------------------
#if _MSC_VER >= 1200
#import <msxml4.dll> rename_namespace("xml")
***************
*** 47,53 ****
#endif
! //------------------------------------------------------------------
// MSI include files
! //------------------------------------------------------------------
#include <Msi.h>
// ^^^^^^^
--- 47,53 ----
#endif
! //------------------------------------------------------------------------------
// MSI include files
! //------------------------------------------------------------------------------
#include <Msi.h>
// ^^^^^^^
***************
*** 62,68 ****
#include <Msiquery.h>
! //------------------------------------------------------------------
// STL include files
! //------------------------------------------------------------------
#include <list>
#include <deque>
--- 62,68 ----
#include <Msiquery.h>
! //------------------------------------------------------------------------------
// STL include files
! //------------------------------------------------------------------------------
#include <list>
#include <deque>
***************
*** 78,84 ****
#include <limits>
! //------------------------------------------------------------------
// Helper function for return code validation
! //------------------------------------------------------------------
#ifdef _DEBUG
#include <crtdbg.h>
--- 78,84 ----
#include <limits>
! //------------------------------------------------------------------------------
// Helper function for return code validation
! //------------------------------------------------------------------------------
#ifdef _DEBUG
#include <crtdbg.h>
***************
*** 94,100 ****
#endif
! //------------------------------------------------------------------
// Define UNICODE aware classes
! //------------------------------------------------------------------
typedef std::basic_istringstream<TCHAR> tistringstream;
typedef std::basic_ostringstream<TCHAR> tostringstream;
--- 94,100 ----
#endif
! //------------------------------------------------------------------------------
// Define UNICODE aware classes
! //------------------------------------------------------------------------------
typedef std::basic_istringstream<TCHAR> tistringstream;
typedef std::basic_ostringstream<TCHAR> tostringstream;
***************
*** 109,128 ****
#endif
! //------------------------------------------------------------------
// Fix "for" scoping rules to conform to ANSI C++
! //------------------------------------------------------------------
#if _MSC_VER <= 1200
#define for if(0)__assume(0);else for
#endif
! //------------------------------------------------------------------
// Binary stream chunk size and corresponding size of base64 encoded data
! //------------------------------------------------------------------
#define CHUNK_BIN 54
#define CHUNK_BASE64 (4 * CHUNK_BIN / 3 + 1)
! //------------------------------------------------------------------
// Define smart handles
! //------------------------------------------------------------------
//>>>> If you are getting error messages from the compiler, see <<<<
//>>>> http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q216722 <<<<
--- 109,137 ----
#endif
! //------------------------------------------------------------------------------
! // Pipe structures
! //------------------------------------------------------------------------------
! struct PipeInfo
! {
! HANDLE pipe;
! std::deque<char> buf;
! };
!
! //------------------------------------------------------------------------------
// Fix "for" scoping rules to conform to ANSI C++
! //------------------------------------------------------------------------------
#if _MSC_VER <= 1200
#define for if(0)__assume(0);else for
#endif
! //------------------------------------------------------------------------------
// Binary stream chunk size and corresponding size of base64 encoded data
! //------------------------------------------------------------------------------
#define CHUNK_BIN 54
#define CHUNK_BASE64 (4 * CHUNK_BIN / 3 + 1)
! //------------------------------------------------------------------------------
// Define smart handles
! //------------------------------------------------------------------------------
//>>>> If you are getting error messages from the compiler, see <<<<
//>>>> http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q216722 <<<<
***************
*** 133,139 ****
typedef SmrtHandle<LPCVOID, BOOL, UnmapViewOfFile> SmrtFileMap;
! //------------------------------------------------------------------
// declarations
! //------------------------------------------------------------------
void checkMSXML();
--- 142,148 ----
typedef SmrtHandle<LPCVOID, BOOL, UnmapViewOfFile> SmrtFileMap;
! //------------------------------------------------------------------------------
// declarations
! //------------------------------------------------------------------------------
void checkMSXML();
***************
*** 143,146 ****
--- 152,163 ----
const xml::IXMLDOMDocument2Ptr& pDoc);
+ void extractCabs(
+ const SmrtMsiHandle& hDb,
+ const xml::IXMLDOMNodePtr& pNodeMsi,
+ const xml::IXMLDOMDocument2Ptr& pDoc);
+
+ DWORD WINAPI readFromPipe(
+ LPVOID args);
+
void indent(
const xml::IXMLDOMDocument2Ptr& pDoc,
***************
*** 186,213 ****
WORD idRes);
! //------------------------------------------------------------------
// global variables
! //------------------------------------------------------------------
#define BUF_SIZE 512 // initial buffer size (arbitrary)
! namespace {
! tstring strInFile; // input file
! tstring strOutFile; // output file
! tstring strBinPath; // full path for binary files
! tstring strBinDir; // directory for binary files
! tstring strXmlEncoding; // XML encoding
! tstring strStyleSheet; // name of alternative stylesheet
! bool bDefStyleSheet = true; // use default stylesheet
! bool bBinDump = false; // write external binary files
! bool bSort = true; // sort rows according to first field
! bool bDataTypes = true; // include datatypes in XML file
! bool bQuiet = false; // don't show progress
! std::set<tstring> streamIds; // ids of extracted streams
}
! //------------------------------------------------------------------
//
// Main entry
//
! //------------------------------------------------------------------
int __cdecl _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
--- 203,233 ----
WORD idRes);
! //------------------------------------------------------------------------------
// global variables
! //------------------------------------------------------------------------------
#define BUF_SIZE 512 // initial buffer size (arbitrary)
! namespace
! {
! tstring strInFile; // input file
! tstring strOutFile; // output file
! tstring strBinPath; // full path for binary files
! tstring strCabDir; // full path for extracted CAB files
! tstring strBinDir; // directory for binary files
! tstring strXmlEncoding; // XML encoding
! tstring strStyleSheet; // name of alternative stylesheet
! bool bDefStyleSheet = true; // use default stylesheet
! bool bBinDump = false; // write external binary files
! bool bCabExtract = false; // extract content of cabinet files
! bool bSort = true; // sort rows according to first field
! bool bDataTypes = true; // include datatypes in XML file
! bool bQuiet = false; // don't show progress
! std::set<tstring> streamIds; // ids of extracted streams
}
! //------------------------------------------------------------------------------
//
// Main entry
//
! //------------------------------------------------------------------------------
int __cdecl _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
***************
*** 383,391 ****
}
! //------------------------------------------------------------------
//
// Check if MSXML 3.0 (or higher) is installed in side-by-side mode
//
! //------------------------------------------------------------------
void checkMSXML()
{
--- 403,411 ----
}
! //------------------------------------------------------------------------------
//
// Check if MSXML 3.0 (or higher) is installed in side-by-side mode
//
! //------------------------------------------------------------------------------
void checkMSXML()
{
***************
*** 418,426 ****
}
! //------------------------------------------------------------------
//
// Dump summary information
//
! //------------------------------------------------------------------
void listSummaryInformation(const SmrtMsiHandle& hDb,
const xml::IXMLDOMNodePtr& pNodeMsi,
--- 438,446 ----
}
! //------------------------------------------------------------------------------
//
// Dump summary information
//
! //------------------------------------------------------------------------------
void listSummaryInformation(const SmrtMsiHandle& hDb,
const xml::IXMLDOMNodePtr& pNodeMsi,
***************
*** 521,529 ****
}
! //------------------------------------------------------------------
! //
// List column headers
! //
! //------------------------------------------------------------------
void listCols(const SmrtMsiHandle& hDb,
LPCTSTR szTable,
--- 541,682 ----
}
! //------------------------------------------------------------------------------
! // Extract cabinet files
! //------------------------------------------------------------------------------
! void extractCabs(const SmrtMsiHandle& hDb,
! const xml::IXMLDOMNodePtr& pNodeMsi,
! const xml::IXMLDOMDocument2Ptr& pDoc)
! {
! // extract cab files listed in Media table
! indent(pDoc, pNodeMsi, 1);
! indent(pDoc, pNodeMsi, 1);
! xml::IXMLDOMElementPtr pElement(pDoc->createElement(L"cabs"));
! xml::IXMLDOMNodePtr pNodeCabs(pNodeMsi->appendChild(pElement));
!
! // list the rows
! SmrtMsiHandle hViewMedia;
! OK(MsiDatabaseOpenView(hDb, _T("SELECT `Cabinet` FROM `Media`"), &hViewMedia));
! OK(MsiViewExecute(hViewMedia, NULL));
!
! // iterate over rows
! UINT res;
! SmrtMsiHandle hRec;
! tcharvector buf(BUF_SIZE);
! DWORD len;
! while ((res = MsiViewFetch(hViewMedia, &hRec)) != ERROR_NO_MORE_ITEMS)
! {
! OK(MsiRecordGetString(hRec, 1, &buf[0], &(len=buf.size())));
! tstring cab(&buf[0]);
!
! // skip if empty or not embedded cabinet file (ie no leading '#')
! if (cab.empty() || cab[0] != _T('#'))
! continue;
!
! // dump cab stream to temporary file
! tstring query = _T("SELECT `Data` FROM `_Streams` WHERE `Name`='") + cab.substr(1) + _T("'");
! SmrtMsiHandle hViewStream;
! OK(MsiDatabaseOpenView(hDb, query.c_str(), &hViewStream));
! OK(MsiViewExecute(hViewStream, NULL));
!
! // fetch the stream
! SmrtMsiHandle hRecStream;
! if (MsiViewFetch(hViewStream, &hRecStream) == ERROR_NO_MORE_ITEMS)
! continue;
!
! // read binary data
! DWORD cbSize = MsiRecordDataSize(hRecStream, 1);
! std::vector<char> bufBinary(cbSize+1);
! OK(MsiRecordReadStream(hRecStream, 1, &bufBinary[0], &cbSize));
!
! // prepare temporary file
! TCHAR tmpDir[MAX_PATH], tmpCabPath[MAX_PATH];
! GetTempPath(MAX_PATH, tmpDir);
! GetTempFileName(tmpDir, _T("cab"), 0, tmpCabPath);
! SmrtFileHandle hFile(CreateFile(tmpCabPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL));
! if (hFile.isNull())
! continue;
!
! // write file
! DWORD dwWritten = 0;
! WriteFile(hFile, (LPCVOID)&bufBinary[0], cbSize, &dwWritten, NULL);
! CloseHandle(hFile.release());
!
! // create col element
! indent(pDoc, pNodeCabs, 2);
! xml::IXMLDOMElementPtr pElement;
! pElement = pDoc->createElement(L"cab");
! pElement->setAttribute(L"name", cab.substr(1).c_str());
! pNodeCabs->appendChild(pElement);
!
! // prepare data structures for child pricess
! STARTUPINFO si = { sizeof STARTUPINFO };
! si.dwFlags = STARTF_USESTDHANDLES;
! si.hStdInput = INVALID_HANDLE_VALUE;
! si.hStdError = INVALID_HANDLE_VALUE;
!
! HANDLE hDummy;
! PipeInfo out;
! out.pipe = INVALID_HANDLE_VALUE;
!
! SECURITY_ATTRIBUTES sa = { sizeof SECURITY_ATTRIBUTES };
! sa.bInheritHandle = TRUE;
! CreatePipe(&out.pipe, &hDummy, &sa, 0);
! DuplicateHandle(GetCurrentProcess(), hDummy, GetCurrentProcess(), &si.hStdOutput, 0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
!
! PROCESS_INFORMATION pi;
!
! // extract from cab files
! tstring cmd = _T("extract.exe \"") + tstring(tmpCabPath) + _T("\" /e /y /l \"") + strCabDir + _T("\" ");
! if (!CreateProcess(NULL, cmd.c_str(), NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
! {
! tcerr << _T("Error: unable to run extract.exe (") << cmd << _T(")") << std::endl;
! continue;
! }
!
! CloseHandle(si.hStdOutput);
! WaitForInputIdle(pi.hProcess, INFINITE);
! CloseHandle(pi.hThread);
!
! // start pipe reader
! DWORD threadId;
! HANDLE hThread = CreateThread(NULL, 0, readFromPipe, &out, 0, &threadId);
!
! // block until extracted
! WaitForSingleObject(pi.hProcess, INFINITE);
! CloseHandle(pi.hProcess);
!
! // wait for pipe readers
! WaitForSingleObject(pi.hProcess, INFINITE);
! CloseHandle(pi.hProcess);
!
! // save Id so that cab does not get extracted anymore
! streamIds.insert(cab.substr(1));
!
! // delete cab file
! DeleteFile(tmpCabPath);
! }
!
! }
!
! //------------------------------------------------------------------------------
! DWORD WINAPI readFromPipe(LPVOID args)
! {
! PipeInfo* out = reinterpret_cast<PipeInfo*>(args);
!
! char buf[32];
! DWORD dwRead;
! while (ReadFile(out->pipe, buf, 32, &dwRead, 0L) && dwRead != 0)
! {
! out->buf.insert(out->buf.end(), buf, buf + dwRead);
! }
!
! CloseHandle(out->pipe);
! return 0;
! }
!
!
! //------------------------------------------------------------------------------
// List column headers
! //------------------------------------------------------------------------------
void listCols(const SmrtMsiHandle& hDb,
LPCTSTR szTable,
***************
*** 626,634 ****
}
! //------------------------------------------------------------------
//
// List rows
//
! //------------------------------------------------------------------
void listRows(const SmrtMsiHandle& hDb,
LPCTSTR szTable,
--- 779,787 ----
}
! //------------------------------------------------------------------------------
//
// List rows
//
! //------------------------------------------------------------------------------
void listRows(const SmrtMsiHandle& hDb,
LPCTSTR szTable,
***************
*** 661,665 ****
SmrtMsiHandle hRecRow;
UINT res;
-
tcharvector buf(BUF_SIZE);
DWORD len;
--- 814,817 ----
***************
*** 723,731 ****
case 'v': { // binary data
! // create id from column 1
static int nCnt = 0;
tostringstream oss;
while ((res = MsiRecordGetString(hRecInfo, 1, &buf[0], &(len=buf.size()))) == ERROR_MORE_DATA)
buf.resize(len+1); OK(res);
if (tolower(buf[0]) != _T('v'))
{
--- 875,887 ----
case 'v': { // binary data
! // create stream id from column 1
! // MSDN: "Binary data is stored with an index name created by
! // concatenating the table name and the values of the
! // record's primary keys using a period delimiter."
static int nCnt = 0;
tostringstream oss;
while ((res = MsiRecordGetString(hRecInfo, 1, &buf[0], &(len=buf.size()))) == ERROR_MORE_DATA)
buf.resize(len+1); OK(res);
+
if (tolower(buf[0]) != _T('v'))
{
***************
*** 751,759 ****
}
! //------------------------------------------------------------------
//
// Dump _Streams table
//
! //------------------------------------------------------------------
void dumpStreams(const SmrtMsiHandle& hDb,
const xml::IXMLDOMNodePtr& pNodeTable,
--- 907,915 ----
}
! //------------------------------------------------------------------------------
//
// Dump _Streams table
//
! //------------------------------------------------------------------------------
void dumpStreams(const SmrtMsiHandle& hDb,
const xml::IXMLDOMNodePtr& pNodeTable,
***************
*** 806,810 ****
tstring strId(&buf[0]);
! if (streamIds.find(strId) != streamIds.end()) continue; // already extracted
// search insert location
--- 962,967 ----
tstring strId(&buf[0]);
! if (streamIds.find(strId) != streamIds.end())
! continue; // already extracted
// search insert location
***************
*** 849,863 ****
}
! //------------------------------------------------------------------
//
// Get msi codepage
//
! //------------------------------------------------------------------
long getCodePage(const SmrtMsiHandle& hDb)
{
unsigned uCodePage;
! char szTmpDir[_MAX_PATH];
! char szTmpFile[_MAX_PATH];
! GetTempPathA(_MAX_PATH, szTmpDir);
GetTempFileNameA(szTmpDir, "msi", 0, szTmpFile);
OK(MsiDatabaseExportA(hDb, "_ForceCodepage", szTmpDir, szTmpFile + strlen(szTmpDir)));
--- 1006,1020 ----
}
! //------------------------------------------------------------------------------
//
// Get msi codepage
//
! //------------------------------------------------------------------------------
long getCodePage(const SmrtMsiHandle& hDb)
{
unsigned uCodePage;
! char szTmpDir[MAX_PATH];
! char szTmpFile[MAX_PATH];
! GetTempPathA(MAX_PATH, szTmpDir);
GetTempFileNameA(szTmpDir, "msi", 0, szTmpFile);
OK(MsiDatabaseExportA(hDb, "_ForceCodepage", szTmpDir, szTmpFile + strlen(szTmpDir)));
***************
*** 883,891 ****
}
! //------------------------------------------------------------------
! //
// Extract binary stream
! //
! //------------------------------------------------------------------
void writeBinaryStream(const tstring& strId,
const xml::IXMLDOMElementPtr& pElementTd,
--- 1040,1046 ----
}
! //------------------------------------------------------------------------------
// Extract binary stream
! //------------------------------------------------------------------------------
void writeBinaryStream(const tstring& strId,
const xml::IXMLDOMElementPtr& pElementTd,
***************
*** 1050,1058 ****
! //------------------------------------------------------------------
//
// Indent
//
! //------------------------------------------------------------------
void indent(const xml::IXMLDOMDocument2Ptr& pDoc,
const xml::IXMLDOMNodePtr& pParent,
--- 1205,1213 ----
! //------------------------------------------------------------------------------
//
// Indent
//
! //------------------------------------------------------------------------------
void indent(const xml::IXMLDOMDocument2Ptr& pDoc,
const xml::IXMLDOMNodePtr& pParent,
***************
*** 1065,1077 ****
}
! //------------------------------------------------------------------
//
// Parse command line
//
! //------------------------------------------------------------------
void parseCommandLine(int argc, TCHAR* argv[])
{
! static TCHAR infile[_MAX_PATH];
! static TCHAR outfile[_MAX_PATH];
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
--- 1220,1232 ----
}
! //------------------------------------------------------------------------------
//
// Parse command line
//
! //------------------------------------------------------------------------------
void parseCommandLine(int argc, TCHAR* argv[])
{
! static TCHAR infile[MAX_PATH];
! static TCHAR outfile[MAX_PATH];
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
***************
*** 1096,1100 ****
int c;
! while ((c = getopt(argc, argv, _T("qdnls:b:o:e:"))) != EOF)
{
if (optarg != NULL && (*optarg == _T('-') || *optarg == _T('/')) ||
--- 1251,1255 ----
int c;
! while ((c = getopt(argc, argv, _T("qdnls:b:o:e:c:"))) != EOF)
{
if (optarg != NULL && (*optarg == _T('-') || *optarg == _T('/')) ||
***************
*** 1135,1138 ****
--- 1290,1304 ----
break;
+ case 'c': // extract cabinet files
+ bCabExtract = true;
+ if (optarg) strCabDir = optarg;
+ if (strCabDir.find_first_of(_T(":/\\")) != tstring::npos)
+ {
+ tcerr << _T("Invalid folder name specified: ") << strCabDir << std::endl << std::endl;
+ printUsage();
+ exit(2);
+ }
+ break;
+
case 'o': // out file
if (!optarg)
***************
*** 1215,1219 ****
if (bDefStyleSheet)
{
! TCHAR szStyleSheet[_MAX_PATH];
_tsplitpath(strOutFile.c_str(), drive, dir, NULL, NULL);
_tmakepath(szStyleSheet, drive, dir, _T("msi.xsl"), NULL);
--- 1381,1385 ----
if (bDefStyleSheet)
{
! TCHAR szStyleSheet[MAX_PATH];
_tsplitpath(strOutFile.c_str(), drive, dir, NULL, NULL);
_tmakepath(szStyleSheet, drive, dir, _T("msi.xsl"), NULL);
***************
*** 1250,1254 ****
if (bBinDump)
{
! TCHAR path[_MAX_PATH];
_tsplitpath(strOutFile.c_str(), drive, dir, NULL, NULL);
_tmakepath(path, drive, dir, strBinDir.c_str(), NULL);
--- 1416,1420 ----
if (bBinDump)
{
! TCHAR path[MAX_PATH];
_tsplitpath(strOutFile.c_str(), drive, dir, NULL, NULL);
_tmakepath(path, drive, dir, strBinDir.c_str(), NULL);
***************
*** 1270,1282 ****
}
! //------------------------------------------------------------------
//
// Print usage message
//
! //------------------------------------------------------------------
void printUsage()
{
tcerr << _T("Usage: ") << std::endl;
! tcerr << _T("msi2xml [-q] [-n] [-d] [-e encoding] [-s [name]] [-b [folder]] [-o file] file\n");
tcerr << _T(" -q quiet processing") << std::endl;
tcerr << _T(" -n disable sorting of rows") << std::endl;
--- 1436,1448 ----
}
! //------------------------------------------------------------------------------
//
// Print usage message
//
! //------------------------------------------------------------------------------
void printUsage()
{
tcerr << _T("Usage: ") << std::endl;
! tcerr << _T("msi2xml [-q] [-n] [-d] [-e encoding] [-s [name]] [-b [folder]] [-c [folder]] [-o file] file\n");
tcerr << _T(" -q quiet processing") << std::endl;
tcerr << _T(" -n disable sorting of rows") << std::endl;
***************
*** 1285,1295 ****
tcerr << _T(" -s disable default XSL stylesheet") << std::endl;
tcerr << _T(" -s name use XSL stylesheet 'name'") << std::endl;
! tcerr << _T(" -b save binary stream to external files") << std::endl;
! tcerr << _T(" -b folder save binary stream to external files in 'folder'") << std::endl;
tcerr << _T(" -o file write XML file to 'file'") << std::endl;
tcerr << _T(" file MSI file") << std::endl << std::endl;
}
! //------------------------------------------------------------------
//
// Load text resource
--- 1451,1463 ----
tcerr << _T(" -s disable default XSL stylesheet") << std::endl;
tcerr << _T(" -s name use XSL stylesheet 'name'") << std::endl;
! tcerr << _T(" -b save binary streams to external files") << std::endl;
! tcerr << _T(" -b folder save binary streams to external files in 'folder'") << std::endl;
! tcerr << _T(" -c extract content of cabinet files") << std::endl;
! tcerr << _T(" -c folder extract content of cabinet files to 'folder'") << std::endl;
tcerr << _T(" -o file write XML file to 'file'") << std::endl;
tcerr << _T(" file MSI file") << std::endl << std::endl;
}
! //------------------------------------------------------------------------------
//
// Load text resource
***************
*** 1303,1307 ****
// pointer to text array
//
! //------------------------------------------------------------------
LPCSTR loadTextResource(WORD idRes)
{
--- 1471,1475 ----
// pointer to text array
//
! //------------------------------------------------------------------------------
LPCSTR loadTextResource(WORD idRes)
{
|