windows-nt/Source/XPSP1/NT/sdktools/appparse/appparseweb/appparsewrapper.cpp
2020-09-26 16:20:57 +08:00

1014 lines
30 KiB
C++

// AppParse.cpp : Implementation of CAppParse
#include "stdafx.h"
#include "AppParseWeb.h"
#include "AppParseWrapper.h"
#include "AppParse.h"
#include <oledb.h>
#include <shlobj.h>
#include <comdef.h>
#include <rpcdce.h>
#include <msxml.h>
#include <icrsint.h>
#include <assert.h>
#include "filebrowser.h"
// Progress dialog functions
void InitProgressDialog(char* szText, HANDLE hEvent);
void KillProgressDialog();
// Save time by creating only seven ADO objects, and sharing, when parsing information
// into the database.
struct SADOInfo
{
_ConnectionPtr pConn;
IADORecordBinding* prbProjects;
IADORecordBinding* prbModules;
IADORecordBinding* prbFuncs;
SProjectRecord pr;
SModuleRecord mr;
SFunctionRecord fr;
};
// Display an error message, then throw a COM error
void APError(char* szMessage, HRESULT hr)
{
::MessageBox(0, szMessage, "AppParse Error", MB_OK | MB_ICONERROR);
_com_issue_error(hr);
}
// Get text subordinate to another node (e.g., <SIZE>0xabcdefg</SIZE>)
bool GetChildText(IXMLDOMNode* pXMLNode, variant_t* pVtVal)
{
HRESULT hr;
IXMLDOMNode* pXMLTextNode = 0;
// Try to get first child node, return FALSE if not present
hr = pXMLNode->get_firstChild(&pXMLTextNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
if(!pXMLTextNode)
return false;
// Check if it is a text node.
DOMNodeType domNodeType;
hr = pXMLTextNode->get_nodeType(&domNodeType);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
// If so, copy text into variant, otherwise return
if(domNodeType == NODE_TEXT)
{
hr = pXMLTextNode->get_nodeValue(pVtVal);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
SafeRelease(pXMLTextNode);
return true;
}
else
{
SafeRelease(pXMLTextNode);
return false;
}
SafeRelease(pXMLTextNode);
}
// Convert a Month/Day/Year date into a DB-friendly date.
// A DB Friendly date is a double, indicating number of days since
// 1899 in the whole part, time in the fractional. We disregard time.
double DateToDBDate(int month, int day, int year)
{
// Check that the date is even valid.
assert (month > 0 && month < 13);
assert(day > 0 && day < 32);
assert(year > 1899);
// Quick lookup for number of days in each month.
int DaysInMonth[] = {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
double dbDate = 0;
// Get full years
dbDate = (year - 1899 - 1) * 365;
// Adjust for leap years
dbDate += ((year-1899-1)/4);
dbDate -= ((year-1899-1)/100);
dbDate += ((year-1899-1)/400);
// Add days for each month.
for(int i = 1; i < month; i++)
dbDate += DaysInMonth[i];
// Add the day of month to total.
dbDate += day;
return dbDate;
}
// Get file information for the image from an <INFO> node.
void GetImageInfo(IXMLDOMNode* pXMLInfoNode, SImageFileInfo* pInfo)
{
HRESULT hr;
IXMLDOMNode* pXMLAttrChild = 0;
IXMLDOMNodeList* pXMLChildList = 0;
IXMLDOMNode* pXMLTextNode = 0;
// Get list of child nodes and move to first.
hr = pXMLInfoNode->get_childNodes(&pXMLChildList);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLChildList->nextNode(&pXMLAttrChild);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
// As long as there is a child node
while(pXMLAttrChild)
{
// Get thename of the node
BSTR bstrName;
hr = pXMLAttrChild->get_nodeName(&bstrName);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
bstr_t bsz(bstrName, false);
// Extract info based on node type
if(stricmp(bsz, "DATE")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
int month, day, year;
sscanf(static_cast<bstr_t>(vtVal), "%d/%d/%d", &month,
&day, &year);
pInfo->Date = DateToDBDate(month, day, year);
pInfo->DateStatus = adFldOK;
}
}
else if(stricmp(bsz, "SIZE")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
sscanf(static_cast<bstr_t>(vtVal), "%x", &pInfo->Size);
pInfo->SizeStatus = adFldOK;
}
}
else if(stricmp(bsz, "BIN_FILE_VERSION")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
strncpy(pInfo->BinFileVersion, static_cast<bstr_t>(vtVal),50);
pInfo->BinFileVersion[49] = '\0';
pInfo->BinFileVersionStatus = adFldOK;
}
}
else if(stricmp(bsz, "BIN_PRODUCT_VERSION")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
strncpy(pInfo->BinProductVersion, static_cast<bstr_t>(vtVal),50);
pInfo->BinProductVersion[49] = '\0';
pInfo->BinProductVersionStatus = adFldOK;
}
}
else if(stricmp(bsz, "CHECKSUM")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
sscanf(static_cast<bstr_t>(vtVal), "%x", &pInfo->CheckSum);
pInfo->CheckSumStatus = adFldOK;
}
}
else if(stricmp(bsz, "COMPANY_NAME")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
strncpy(pInfo->CompanyName, static_cast<bstr_t>(vtVal),255);
pInfo->CompanyName[254] = '\0';
pInfo->CompanyNameStatus = adFldOK;
}
}
else if(stricmp(bsz, "PRODUCT_VERSION")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
strncpy(pInfo->ProductVersion, static_cast<bstr_t>(vtVal),50);
pInfo->ProductVersion[49];
pInfo->ProductVersionStatus = adFldOK;
}
}
else if(stricmp(bsz, "PRODUCT_NAME")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
strncpy(pInfo->ProductName, static_cast<bstr_t>(vtVal),255);
pInfo->ProductName[254] = '\0';
pInfo->ProductNameStatus = adFldOK;
}
}
else if(stricmp(bsz, "FILE_DESCRIPTION")==0)
{
variant_t vtVal;
if(GetChildText(pXMLAttrChild, &vtVal))
{
strncpy(pInfo->FileDesc, static_cast<bstr_t>(vtVal),255);
pInfo->FileDesc[254] = '\0';
pInfo->FileDescStatus = adFldOK;
}
}
SafeRelease(pXMLAttrChild);
// Move to next node
hr = pXMLChildList->nextNode(&pXMLAttrChild);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
SafeRelease(pXMLChildList);
SafeRelease(pXMLAttrChild);
SafeRelease(pXMLTextNode);
}
// Get all info related to a function from XML
void GetFunctionInfo(IXMLDOMNode* pXMLFunctionNode, ULONG lModuleID, SADOInfo* pADOInfo)
{
HRESULT hr;
IXMLDOMNamedNodeMap* pXMLAttrList= 0;
IXMLDOMNode* pXMLAttrNode = 0;
// Start with no members valid.
pADOInfo->fr.AddressStatus = pADOInfo->fr.HintStatus =
pADOInfo->fr.OrdinalStatus = pADOInfo->fr.ForwardNameStatus = adFldNull;
// Get parent ID
pADOInfo->fr.ModuleID = lModuleID;
// Get all attribute nodes
hr = pXMLFunctionNode->get_attributes(&pXMLAttrList);
if(FAILED(hr) || !pXMLAttrList)
APError("Unable to parse XML output", hr);
hr = pXMLAttrList->nextNode(&pXMLAttrNode);
if(FAILED(hr) || !pXMLAttrNode)
APError("Unable to parse XML output", hr);
// Loop through the list.
while(pXMLAttrNode)
{
BSTR bszName;
variant_t vtVal;
// Get attribute name and value.
hr = pXMLAttrNode->get_nodeName(&bszName);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLAttrNode->get_nodeValue(&vtVal);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
bstr_t bsz(bszName, false);
bstr_t bszVal = vtVal;
// Copy info into struct
if(stricmp(static_cast<PSTR>(bsz), "NAME")==0)
{
strncpy(pADOInfo->fr.Name, static_cast<PSTR>(bszVal), 255);
}
else if(stricmp(static_cast<PSTR>(bsz), "HINT")== 0)
{
pADOInfo->fr.HintStatus = adFldOK;
pADOInfo->fr.Hint = atoi(bszVal);
}
else if (stricmp(static_cast<PSTR>(bsz), "ORDINAL") == 0)
{
pADOInfo->fr.OrdinalStatus = adFldOK;
pADOInfo->fr.Ordinal = atoi(bszVal);
}
else if(stricmp(static_cast<PSTR>(bsz), "ADDRESS") == 0)
{
pADOInfo->fr.AddressStatus = adFldOK;
pADOInfo->fr.Address = atoi(bszVal);
}
else if(stricmp(static_cast<PSTR>(bsz), "FORWARD_TO")==0)
{
pADOInfo->fr.ForwardNameStatus = adFldOK;
strncpy(pADOInfo->fr.ForwardName, bszVal, 255);
}
else if(stricmp(static_cast<PSTR>(bsz), "DELAYED") == 0)
{
pADOInfo->fr.Delayed = (stricmp(bszVal, "true")==0);
}
SafeRelease(pXMLAttrNode);
hr = pXMLAttrList->nextNode(&pXMLAttrNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
// Add a new record to the database.
hr = pADOInfo->prbFuncs->AddNew(&pADOInfo->fr);
if(FAILED(hr))
APError("Unable to add new function record to database", hr);
SafeRelease(pXMLAttrList);
SafeRelease(pXMLAttrNode);
}
// Get all info related to a module.
void GetModuleInfo(IXMLDOMNode* pXMLModuleNode, ULONG lParentID, SADOInfo* pADOInfo,
HANDLE hEvent, bool fTopLevel = false)
{
if(WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
return;
HRESULT hr;
IXMLDOMNode* pXMLChildNode = 0;
IXMLDOMNodeList* pXMLNodeList = 0;
IXMLDOMNamedNodeMap* pXMLAttrList= 0;
IXMLDOMNode* pXMLAttrNode = 0;
// All members are initially invalid.
pADOInfo->mr.info.BinFileVersionStatus =
pADOInfo->mr.info.BinProductVersionStatus =
pADOInfo->mr.info.CheckSumStatus =
pADOInfo->mr.info.CompanyNameStatus =
pADOInfo->mr.info.DateStatus =
pADOInfo->mr.info.FileDescStatus =
pADOInfo->mr.info.ProductNameStatus =
pADOInfo->mr.info.ProductVersionStatus =
pADOInfo->mr.info.SizeStatus =
pADOInfo->mr.ParentIDStatus =
pADOInfo->mr.PtolemyIDStatus = adFldNull;
// Copy parent ID
pADOInfo->mr.ParentID = lParentID;
// Check appropriate parent.
if(fTopLevel)
pADOInfo->mr.PtolemyIDStatus = adFldOK;
else
pADOInfo->mr.ParentIDStatus = adFldOK;
// Get attributes
hr = pXMLModuleNode->get_attributes(&pXMLAttrList);
if(FAILED(hr) || !pXMLAttrList)
APError("Unable to parse XML output", hr);
hr = pXMLAttrList->nextNode(&pXMLAttrNode);
if(FAILED(hr) || !pXMLAttrNode)
APError("Unable to parse XML output", hr);
// Loop through attribute list.
while(pXMLAttrNode)
{
BSTR bszName;
variant_t vtVal;
// Get attribute name and value.
hr = pXMLAttrNode->get_nodeName(&bszName);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLAttrNode->get_nodeValue(&vtVal);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
bstr_t bsz(bszName, false);
if(stricmp(static_cast<PSTR>(bsz), "NAME")==0)
{
bstr_t bszTemp = vtVal;
strncpy(pADOInfo->mr.Name, static_cast<PSTR>(bszTemp), 100);
}
SafeRelease(pXMLAttrNode);
hr = pXMLAttrList->nextNode(&pXMLAttrNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
// Get info block, if present, for this module.
hr = pXMLModuleNode->get_childNodes(&pXMLNodeList);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLNodeList->nextNode(&pXMLChildNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
while(pXMLChildNode)
{
DOMNodeType domNodeType;
hr = pXMLChildNode->get_nodeType(&domNodeType);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
if(domNodeType == NODE_ELEMENT)
{
BSTR bstr;
hr = pXMLChildNode->get_nodeName(&bstr);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
bstr_t bszName(bstr, false);
// If info node, get info block.
if(stricmp(bszName, "Info") == 0)
GetImageInfo(pXMLChildNode, &pADOInfo->mr.info);
// Otherwise, if a systemmodule node, get systemmodule state.
else if(stricmp(bszName, "SYSTEMMODULE")==0)
{
hr = pXMLChildNode->get_attributes(&pXMLAttrList);
if(FAILED(hr) || !pXMLAttrList)
APError("Unable to parse XML output", hr);
hr = pXMLAttrList->nextNode(&pXMLAttrNode);
if(FAILED(hr) || !pXMLAttrNode)
APError("Unable to parse XML output", hr);
while(pXMLAttrNode)
{
BSTR bszAttrName;
variant_t vtVal;
hr = pXMLAttrNode->get_nodeName(&bszAttrName);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLAttrNode->get_nodeValue(&vtVal);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
bstr_t bsz(bszAttrName, false);
if(stricmp(static_cast<PSTR>(bsz), "VALUE")==0)
{
bstr_t bszTemp = vtVal;
pADOInfo->mr.SysMod = atoi(bszTemp);
}
SafeRelease(pXMLAttrNode);
hr = pXMLAttrList->nextNode(&pXMLAttrNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
}
}
SafeRelease(pXMLChildNode);
hr = pXMLNodeList->nextNode(&pXMLChildNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
// Add a new module record to the database
hr = pADOInfo->prbModules->AddNew(&pADOInfo->mr);
if(FAILED(hr))
APError("Unable to new module record to database", hr);
ULONG lThisModuleID = pADOInfo->mr.ModuleID;
// Get all functions's imported by this module, and DLL's
hr = pXMLModuleNode->get_childNodes(&pXMLNodeList);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLNodeList->nextNode(&pXMLChildNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
while(pXMLChildNode)
{
DOMNodeType domNodeType;
hr = pXMLChildNode->get_nodeType(&domNodeType);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
if(domNodeType == NODE_ELEMENT)
{
BSTR bstr;
hr = pXMLChildNode->get_nodeName(&bstr);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
bstr_t bszName(bstr, false);
if(stricmp(bszName, "Function") == 0)
GetFunctionInfo(pXMLChildNode, lThisModuleID, pADOInfo);
else if(stricmp(bszName, "DLL") == 0)
GetModuleInfo(pXMLChildNode, lThisModuleID, pADOInfo, hEvent);
}
SafeRelease(pXMLChildNode);
hr = pXMLNodeList->nextNode(&pXMLChildNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
SafeRelease(pXMLChildNode);
SafeRelease(pXMLNodeList);
SafeRelease(pXMLAttrList);
SafeRelease(pXMLAttrNode);
}
// Get project information from XML
void GetProjectInfo(IXMLDOMNode* pXMLProjectNode, SADOInfo* pADOInfo, HANDLE hEvent)
{
if(WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
return;
HRESULT hr;
IXMLDOMNamedNodeMap* pXMLAttrList= 0;
IXMLDOMNode* pXMLAttrNode = 0;
IXMLDOMNode* pXMLChildNode = 0;
IXMLDOMNodeList* pXMLNodeList = 0;
pADOInfo->pr.PtolemyID = -1;
pADOInfo->pr.Name[0] = '\0';
// Get name and ptolemy id attributes
hr = pXMLProjectNode->get_attributes(&pXMLAttrList);
if(FAILED(hr) || !pXMLAttrList)
APError("Unable to parse XML output", hr);
hr = pXMLAttrList->nextNode(&pXMLAttrNode);
if(FAILED(hr) || !pXMLAttrNode)
APError("Unable to parse XML output", hr);
while(pXMLAttrNode)
{
BSTR bszName;
variant_t vtVal;
hr = pXMLAttrNode->get_nodeName(&bszName);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLAttrNode->get_nodeValue(&vtVal);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
bstr_t bsz(bszName, false);
if(stricmp(static_cast<PSTR>(bsz), "NAME")==0)
{
bstr_t bszTemp = vtVal;
strncpy(pADOInfo->pr.Name, static_cast<PSTR>(bszTemp), 100);
}
else if(stricmp(static_cast<PSTR>(bsz), "ID") == 0)
{
bstr_t bszTemp = vtVal;
pADOInfo->pr.PtolemyID = atoi(static_cast<PSTR>(bszTemp));
}
SafeRelease(pXMLAttrNode);
hr = pXMLAttrList->nextNode(&pXMLAttrNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
hr = pADOInfo->prbProjects->AddNew(&pADOInfo->pr);
if(FAILED(hr))
APError("Unable to add new project record to database", hr);
// Parse all Exe's included in this project
hr = pXMLProjectNode->get_childNodes(&pXMLNodeList);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLNodeList->nextNode(&pXMLChildNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
while(pXMLChildNode)
{
DOMNodeType domNodeType;
hr = pXMLChildNode->get_nodeType(&domNodeType);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
if(domNodeType == NODE_ELEMENT)
{
BSTR bstr;
hr = pXMLChildNode->get_nodeName(&bstr);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
bstr_t bszName(bstr, false);
if(stricmp(bszName, "EXE") == 0)
GetModuleInfo(pXMLChildNode, pADOInfo->pr.PtolemyID, pADOInfo, hEvent, true);
}
SafeRelease(pXMLChildNode);
hr = pXMLNodeList->nextNode(&pXMLChildNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
SafeRelease(pXMLAttrList);
SafeRelease(pXMLAttrNode);
SafeRelease(pXMLNodeList);
SafeRelease(pXMLChildNode);
}
// Functions for walking an XML DOM object and storing
// information to the database
void ParseXMLWriteDB(const char* szXML, const char* szConnect, HANDLE hEvent)
{
HRESULT hr;
// Get DOM object associated with Projects node
IXMLDOMDocument* pXMLDoc = 0;
IXMLDOMNode* pXMLRootNode = 0;
IXMLDOMNode* pXMLChildNode = 0;
IXMLDOMNode* pXMLProjectNode = 0;
IXMLDOMNodeList* pXMLChildNodeList = 0;
// Create all ADO objects needed.
SADOInfo adoInfo;
_ConnectionPtr pConn = 0;
_RecordsetPtr pRSProjects = 0;
_RecordsetPtr pRSModules = 0;
_RecordsetPtr pRSFuncs = 0;
pConn.CreateInstance(__uuidof(Connection));
pRSProjects.CreateInstance(__uuidof(Recordset));
pRSModules.CreateInstance(__uuidof(Recordset));
pRSFuncs.CreateInstance(__uuidof(Recordset));
hr = pRSProjects->QueryInterface(__uuidof(IADORecordBinding),
reinterpret_cast<void**>(&adoInfo.prbProjects));
if(FAILED(hr))
APError("Unable to retrieve ADO Recordset interface", hr);
hr = pRSModules->QueryInterface(__uuidof(IADORecordBinding),
reinterpret_cast<void**>(&adoInfo.prbModules));
if(FAILED(hr))
APError("Unable to retrieve ADO Recordset interface", hr);
hr = pRSFuncs->QueryInterface(__uuidof(IADORecordBinding),
reinterpret_cast<void**>(&adoInfo.prbFuncs));
if(FAILED(hr))
APError("Unable to retrieve ADO Recordset interface", hr);
pConn->Open(szConnect, "", "", adConnectUnspecified);
pConn->BeginTrans();
pRSProjects->Open("Projects", variant_t((IDispatch*)pConn, true),
adOpenKeyset, adLockOptimistic, adCmdTable);
pRSModules->Open("Modules", variant_t((IDispatch*)pConn, true),
adOpenKeyset, adLockOptimistic, adCmdTable);
pRSFuncs->Open("Functions", variant_t((IDispatch*)pConn, true),
adOpenKeyset, adLockOptimistic, adCmdTable);
adoInfo.pConn = pConn;
adoInfo.pr.Name[0] = '\0';
adoInfo.pr.PtolemyID = -1;
adoInfo.mr.info.BinFileVersionStatus =
adoInfo.mr.info.BinProductVersionStatus =
adoInfo.mr.info.CheckSumStatus =
adoInfo.mr.info.CompanyNameStatus =
adoInfo.mr.info.DateStatus =
adoInfo.mr.info.FileDescStatus =
adoInfo.mr.info.ProductNameStatus =
adoInfo.mr.info.ProductVersionStatus =
adoInfo.mr.info.SizeStatus =
adoInfo.mr.ParentIDStatus =
adoInfo.mr.PtolemyIDStatus =
adoInfo.fr.AddressStatus =
adoInfo.fr.HintStatus =
adoInfo.fr.OrdinalStatus =
adoInfo.fr.ForwardNameStatus = adFldNull;
hr = adoInfo.prbProjects->BindToRecordset(&adoInfo.pr);
if(FAILED(hr))
APError("Unable to bind ADO recordset", hr);
hr = adoInfo.prbModules->BindToRecordset(&adoInfo.mr);
if(FAILED(hr))
APError("Unable to bind ADO recordset", hr);
hr = adoInfo.prbFuncs->BindToRecordset(&adoInfo.fr);
if(FAILED(hr))
APError("Unable to bind ADO recordset", hr);
hr = CoCreateInstance(CLSID_DOMDocument, 0, CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument, reinterpret_cast<void**>(&pXMLDoc));
if(FAILED(hr))
APError("Unable to create IE XML DOM object", hr);
VARIANT_BOOL fSuccess;
hr = pXMLDoc->load(variant_t(szXML), &fSuccess);
if(FAILED(hr) || fSuccess == VARIANT_FALSE)
APError("Unable to load XML output", hr);
// Walk the tree until we find the top-level project node
// which is the only top-level node we care about.
hr = pXMLDoc->QueryInterface(IID_IXMLDOMNode,
reinterpret_cast<void**>(&pXMLRootNode));
if(FAILED(hr))
APError("Unable to retrieve IE XML interface", hr);
hr = pXMLRootNode->get_childNodes(&pXMLChildNodeList);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLChildNodeList->nextNode(&pXMLChildNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
while(pXMLChildNode)
{
// Check if this is the projects node.
DOMNodeType domNodeType;
hr = pXMLChildNode->get_nodeType(&domNodeType);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
if(domNodeType == NODE_ELEMENT)
{
BSTR bszName;
hr = pXMLChildNode->get_nodeName(&bszName);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
_bstr_t bsz(bszName, false);
if(stricmp(static_cast<PSTR>(bsz), "AppParseResults")==0)
{
break;
}
}
SafeRelease(pXMLChildNode);
hr = pXMLChildNodeList->nextNode(&pXMLChildNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
SafeRelease(pXMLChildNodeList);
// No child node, record not found.
if(!pXMLChildNode)
APError("Unable to parse XML output", hr);
// Locate project node in that.
hr = pXMLChildNode->get_childNodes(&pXMLChildNodeList);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
hr = pXMLChildNodeList->nextNode(&pXMLProjectNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
while(pXMLProjectNode)
{
// Check if this is the projects node.
DOMNodeType domNodeType;
hr = pXMLProjectNode->get_nodeType(&domNodeType);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
if(domNodeType == NODE_ELEMENT)
{
BSTR bszName;
hr = pXMLProjectNode->get_nodeName(&bszName);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
_bstr_t bsz(bszName, false);
if(stricmp(static_cast<PSTR>(bsz), "Project")==0)
{
GetProjectInfo(pXMLProjectNode, &adoInfo, hEvent);
}
}
SafeRelease(pXMLProjectNode);
hr = pXMLChildNodeList->nextNode(&pXMLProjectNode);
if(FAILED(hr))
APError("Unable to parse XML output", hr);
}
pRSProjects->UpdateBatch(adAffectAll);
pRSModules->UpdateBatch(adAffectAll);
pRSFuncs->UpdateBatch(adAffectAll);
// Important, skip commit if cancel was clicked by user.
if(WaitForSingleObject(hEvent, 0) != WAIT_OBJECT_0)
pConn->CommitTrans();
pRSProjects->Close();
pRSModules->Close();
pRSFuncs->Close();
pConn->Close();
SafeRelease(adoInfo.prbProjects);
SafeRelease(adoInfo.prbModules);
SafeRelease(adoInfo.prbFuncs);
SafeRelease(pXMLChildNodeList);
SafeRelease(pXMLChildNode);
SafeRelease(pXMLRootNode);
SafeRelease(pXMLDoc);
}
/////////////////////////////////////////////////////////////////////////////
// CAppParse
STDMETHODIMP CAppParse::Parse()
{
if(!m_szPath)
{
::MessageBox(0, TEXT("Please select a path to profile"), TEXT("AppParse"),
MB_OK | MB_ICONERROR);
return S_OK;
}
if(m_ID == -1)
{
::MessageBox(0, TEXT("Please enter a Ptolemy ID"), TEXT("AppParse"),
MB_OK | MB_ICONERROR);
return S_OK;
}
// Show the progress dialog (reset the event to cancel)
ResetEvent(m_hEvent);
InitProgressDialog("Parsing, please do not close your browser window.", m_hEvent);
// Generate a unique temp file name
GUID guid;
unsigned char* szUUID;
char szFileName[MAX_PATH];
HRESULT hr = CoCreateGuid(&guid);
if(FAILED(hr))
return hr;
UuidToString(&guid, &szUUID);
GetTempPath(MAX_PATH, szFileName);
strcat(szFileName, reinterpret_cast<char*>(szUUID));
strcat(szFileName, ".xml");
FILE* pFile = fopen(szFileName, "wb");
if(!pFile)
APError("Unable to open output file", E_FAIL);
// Parse the application
AppParse(m_szPath, pFile, false, false, true, true,
"*", m_ID);
fclose(pFile);
RpcStringFree(&szUUID);
// If user didn't cancel . . .
if(WaitForSingleObject(m_hEvent, 0) != WAIT_OBJECT_0)
{
// Write results to DB
try
{
ParseXMLWriteDB(szFileName, m_szConnect, m_hEvent);
}
catch(_com_error& e)
{
::MessageBox(0, (LPCSTR)e.ErrorMessage(), "COM Error", MB_OK);
}
}
// Terminate temp file
DeleteFile(szFileName);
// Remove progress dialog box.
KillProgressDialog();
return S_OK;
}
STDMETHODIMP CAppParse::Browse()
{
PTSTR szPath = BrowseForFolder(0, 0);
if(!szPath)
return S_FALSE;
if(m_szPath)
delete m_szPath;
m_szPath = new char[strlen(szPath)+1];
strcpy(m_szPath,szPath);
return S_OK;
}
STDMETHODIMP CAppParse::get_path(BSTR *pVal)
{
if(m_szPath)
{
OLECHAR* sz;
sz = new OLECHAR[strlen(m_szPath)+1];
MultiByteToWideChar(CP_ACP, 0, m_szPath, -1, sz, strlen(m_szPath)+1);
*pVal = SysAllocString(sz);
delete sz;
}
else
*pVal = SysAllocString(L"");
return S_OK;
}
STDMETHODIMP CAppParse::put_path(BSTR newVal)
{
if(m_szPath)
{
delete m_szPath;
m_szPath = 0;
}
_bstr_t bstrGhostLoc(newVal);
LPSTR szGhostLoc = (LPSTR)bstrGhostLoc;
m_szPath = new char[strlen(szGhostLoc)+1];
strcpy(m_szPath, szGhostLoc);
return S_OK;
}
STDMETHODIMP CAppParse::get_PtolemyID(long *pVal)
{
*pVal = m_ID;
return S_OK;
}
STDMETHODIMP CAppParse::put_PtolemyID(long newVal)
{
m_ID = newVal;
return S_OK;
}
STDMETHODIMP CAppParse::get_ConnectionString(BSTR *pVal)
{
if(m_szConnect)
{
OLECHAR* sz;
sz = new OLECHAR[strlen(m_szConnect)+1];
MultiByteToWideChar(CP_ACP, 0, m_szConnect, -1, sz, strlen(m_szConnect)+1);
*pVal = SysAllocString(sz);
delete sz;
}
else
*pVal = SysAllocString(L"");
return S_OK;
}
STDMETHODIMP CAppParse::put_ConnectionString(BSTR newVal)
{
if(m_szConnect)
{
delete m_szConnect;
m_szConnect = 0;
}
_bstr_t bstrGhostLoc(newVal);
LPSTR szGhostLoc = (LPSTR)bstrGhostLoc;
m_szConnect = new char[strlen(szGhostLoc)+1];
strcpy(m_szConnect, szGhostLoc);
return S_OK;
}