Thread: [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) { |