Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1176 lines
36 KiB

#include <windows.h>
#include <fusenetincludes.h>
#include <msxml2.h>
#include <stdio.h>
#include <md5.h>
#include "list.h"
#include "manifestnode.h"
#include "xmlutil.h"
#include "version.h"
#define ASSEMBLY L"assembly"
#define NAMESPACE_TITLE L"xmlns:asm_namespace_v1"
#define NAMESPACE_VALUE L"urn:schemas-microsoft-com:asm.v1"
#define MANIFEST_VERSION_TITLE L"manifestVersion"
#define MANIFEST_VERSION_VALUE L"1.0"
#define DESCRIPTION L"description"
#define ASSEMBLY_IDENTITY L"assemblyIdentity"
#define DEPENDENCY L"dependency"
#define DEPENDENCY_QUERY L"/assembly/dependency"
#define DEPENDANT_ASSEMBLY L"dependentAssembly"
#define INSTALL L"install"
#define CODEBASE L"codebase"
#define APPLICATION L"application"
#define SHELL_STATE L"shellState"
#define ACTIVATION L"activation"
#define FILE L"file"
#define FILE_NAME L"name"
#define FILE_HASH L"hash"
class __declspec(uuid("f6d90f11-9c73-11d3-b32e-00c04f990bb4")) private_MSXML_DOMDocument30;
#define HASHLENGTH 32
#define HASHSTRINGLENGTH HASHLENGTH+1
/////////////////////////////////////////////////////////////////////////
// FowardSlash
/////////////////////////////////////////////////////////////////////////
VOID FowardSlash(LPWSTR pwz)
{
LPWSTR ptr = pwz;
while (*ptr)
{
if (*ptr == L'\\')
*ptr = L'/';
ptr++;
}
}
/////////////////////////////////////////////////////////////////////////
// GetHash
/////////////////////////////////////////////////////////////////////////
HRESULT GetHash(LPCWSTR pwzFilename, LPWSTR *ppwzHash)
{
HRESULT hr = S_OK;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwLength = 0; // cblength
LPWSTR pwzHash = new WCHAR[HASHSTRINGLENGTH];
// BUGBUG - heap allocate large buffers like this.
unsigned char buffer[16384];
MD5_CTX md5c;
int i;
WCHAR* p;
if(!pwzHash)
{
hr = E_OUTOFMEMORY;
goto exit;
}
MD5Init(&md5c);
hFile = CreateFile(pwzFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
printf("Open file error during hashing\n");
goto exit;
}
ZeroMemory(buffer, sizeof(buffer));
// BUGBUG - error checking here.
while(ReadFile(hFile, buffer, sizeof(buffer), &dwLength, NULL) && dwLength)
MD5Update(&md5c, buffer, (unsigned) dwLength);
CloseHandle(hFile);
MD5Final(&md5c);
// convert hash from byte array to hex
p = pwzHash;
for (int i = 0; i < sizeof(md5c.digest); i++)
{
wsprintf(p, L"%02X", md5c.digest[i]);
p += 2;
}
*ppwzHash = pwzHash;
pwzHash = NULL;
exit:
SAFEDELETEARRAY(pwzHash);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// CreateXMLElement
/////////////////////////////////////////////////////////////////////////
HRESULT CreateXMLTextNode(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzText, IXMLDOMNode **ppNode)
{
HRESULT hr = S_OK;
IXMLDOMNode *pNode = NULL;
BSTR bstrText = NULL;
bstrText = ::SysAllocString(pwzText);
if (!bstrText)
{
hr = E_OUTOFMEMORY;
goto exit;
}
if(FAILED(pXMLDoc->createTextNode(bstrText, (IXMLDOMText**)&pNode)))
goto exit;
*ppNode = pNode;
(*ppNode)->AddRef();
exit:
if (bstrText)
::SysFreeString(bstrText);
SAFERELEASE (pNode);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// CreateXMLComment
/////////////////////////////////////////////////////////////////////////
HRESULT CreateXMLComment(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzComment,
IXMLDOMComment **ppComment)
{
HRESULT hr=S_OK;
BSTR bstrComment = NULL;
IXMLDOMComment *pComment = NULL;
bstrComment = ::SysAllocString(pwzComment);
if (!bstrComment)
{
hr = E_OUTOFMEMORY;
goto exit;
}
if(FAILED(hr = pXMLDoc->createComment(bstrComment, &pComment)))
goto exit;
*ppComment = pComment;
(*ppComment)->AddRef();
exit:
if (bstrComment)
::SysFreeString(bstrComment);
SAFERELEASE(pComment);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// AddMgVersionAsComment
/////////////////////////////////////////////////////////////////////////
HRESULT AddMgVersionAsComment(IXMLDOMDocument2 *pXMLDoc, IXMLDOMNode **ppRoot)
{
HRESULT hr = S_OK;
CString sComment;
IXMLDOMComment *pComment = NULL;
IXMLDOMNode *pNewNode = NULL;
// ASSERT(pXMLDoc && ppRoot);
sComment.Assign(L"Created using mg version ");
sComment.Append(VER_PRODUCTVERSION_STR_L);
if(FAILED(hr = CreateXMLComment(pXMLDoc, sComment._pwz, &pComment)))
goto exit;
if(*ppRoot)
{
if (FAILED(hr = (*ppRoot)->appendChild((IXMLDOMNode *)pComment, &pNewNode)))
goto exit;
}
else
{
if (FAILED(hr = pXMLDoc->appendChild((IXMLDOMNode *)pComment, ppRoot)))
goto exit;
}
exit:
SAFERELEASE(pNewNode);
SAFERELEASE(pComment);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// CreateXMLElement
/////////////////////////////////////////////////////////////////////////
HRESULT CreateXMLElement(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzElementName,
IXMLDOMElement **ppElement)
{
HRESULT hr=S_OK;
BSTR bstrElementName = NULL;
IXMLDOMElement *pElement = NULL;
IXMLDOMNode *pNode =NULL, *pNewNode = NULL;
bstrElementName = ::SysAllocString(pwzElementName);
if (!bstrElementName)
{
hr = E_OUTOFMEMORY;
goto exit;
}
// NOTENOTE - createElement doesn't append the node to the doc
// so we're just using pXMLDoc for convenience of calling create.
if(FAILED(hr = pXMLDoc->createElement(bstrElementName, &pElement)))
goto exit;
*ppElement = pElement;
(*ppElement)->AddRef();
exit:
if (bstrElementName)
::SysFreeString(bstrElementName);
SAFERELEASE(pNode);
SAFERELEASE(pNewNode);
SAFERELEASE(pElement);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// SetXMLElementAttribute
/////////////////////////////////////////////////////////////////////////
HRESULT SetXMLElementAttribute(IXMLDOMElement *pElement, LPWSTR pwzAttributeName,
LPWSTR pwzAttributeValue)
{
HRESULT hr=S_OK;
BSTR bstrAttributeName = NULL, bstrAttributeValue = NULL;
VARIANT varAttributeValue;
bstrAttributeName = ::SysAllocString(pwzAttributeName);
bstrAttributeValue = ::SysAllocString(pwzAttributeValue);
if (!bstrAttributeName || (!bstrAttributeValue && pwzAttributeValue))
{
hr = E_OUTOFMEMORY;
goto exit;
}
VariantInit(&varAttributeValue);
varAttributeValue.vt = VT_BSTR;
V_BSTR(&varAttributeValue) = bstrAttributeValue;
hr = pElement->setAttribute(bstrAttributeName, varAttributeValue);
exit:
if (bstrAttributeName)
::SysFreeString(bstrAttributeName);
if (bstrAttributeValue)
::SysFreeString(bstrAttributeValue);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// CreateXMLAssemblyIdElement
/////////////////////////////////////////////////////////////////////////
HRESULT CreateXMLAssemblyIdElement(IXMLDOMDocument2 *pXMLDoc, IAssemblyIdentity *pAssemblyId,
IXMLDOMElement **ppElement)
{
HRESULT hr = S_OK;
IXMLDOMElement *pASMIdElement = NULL;
LPWSTR pwzBuf = NULL;
DWORD ccBuf = 0;
CString sBuffer;
LPWSTR rpwzAttrNames[6] =
{
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_TYPE,
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION,
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN,
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE,
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE,
};
//Create assemblyIdentity Element
if(FAILED(hr=CreateXMLElement(pXMLDoc, ASSEMBLY_IDENTITY, &pASMIdElement)))
goto exit;
for (int i = 0; i < 6; i++)
{
// BUGBUG - eventually, when we add support for type the only guy which
// is optional is the public key token.
if (FAILED(hr = pAssemblyId->GetAttribute(rpwzAttrNames[i], &pwzBuf, &ccBuf))
&& hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
goto exit;
else if (hr == S_OK)
{
sBuffer.TakeOwnership(pwzBuf, ccBuf);
hr = SetXMLElementAttribute(pASMIdElement, rpwzAttrNames[i], sBuffer._pwz);
}
else
hr = S_OK;
}
*ppElement = pASMIdElement;
(*ppElement)->AddRef();
exit:
SAFERELEASE(pASMIdElement);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// CreateDependantAssemblyNode
/////////////////////////////////////////////////////////////////////////
HRESULT CreateDependantAssemblyNode(IXMLDOMDocument2 *pXMLDoc, ManifestNode*pManifestNode, IXMLDOMNode **ppDependantAssemblyNode)
{
HRESULT hr = S_OK;
LPWSTR pwzBuf = NULL;
DWORD dwType;
IAssemblyIdentity *pAssemblyId = NULL;
IXMLDOMElement *pDependantAssemblyNode = NULL, *pElement = NULL;
IXMLDOMNode *pNewNode = NULL;
CString sCodeBase;
//Get ASMId for Unique Dependency
if(FAILED(hr = pManifestNode->GetAssemblyIdentity(&pAssemblyId)))
goto exit;
//Get the type of manifest
// - Private or GAC, for GACs you don't put the codebase.
if(FAILED(hr = pManifestNode->GetManifestType(&dwType)))
goto exit;
//Get Codebase of the Unique Dependancy
if(FAILED(hr = pManifestNode->GetManifestFilePath(&pwzBuf)))
goto exit;
sCodeBase.TakeOwnership(pwzBuf);
//Create a dependentAssembly node
if(FAILED(hr = CreateXMLElement(pXMLDoc, DEPENDANT_ASSEMBLY, &pDependantAssemblyNode)))
goto exit;
//Create the AssemblyId for the Dependant Assembly
if (FAILED(CreateXMLAssemblyIdElement(pXMLDoc, pAssemblyId, &pElement)))
goto exit;
if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
// Node is added and element, node can be released.
SAFERELEASE(pElement);
SAFERELEASE(pNewNode);
//read the codebase for this DependantAssembly
// GACs don't have a codebase.
if (1) // we need codebase for all assemblies (dwType == PRIVATE_ASSEMBLY)
{
if(FAILED(hr = CreateXMLElement(pXMLDoc, INSTALL, &pElement)))
goto exit;
FowardSlash(sCodeBase._pwz);
if(FAILED(hr = SetXMLElementAttribute(pElement, CODEBASE, sCodeBase._pwz)))
goto exit;
if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pElement);
SAFERELEASE(pNewNode);
}
*ppDependantAssemblyNode = pDependantAssemblyNode;
(*ppDependantAssemblyNode)->AddRef();
exit:
SAFERELEASE(pAssemblyId);
SAFERELEASE(pDependantAssemblyNode);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// GetNode
/////////////////////////////////////////////////////////////////////////
HRESULT GetNode(IXMLDOMDocument2 *pXMLDoc, LPCWSTR pwzNode, IXMLDOMNode **ppNode)
{
HRESULT hr = S_OK;
BSTR bstrtQueryString;
IXMLDOMNode *pNode=NULL;
IXMLDOMNodeList *pNodeList = NULL;
LONG nNodes = 0;
bstrtQueryString = ::SysAllocString(pwzNode);
if (!bstrtQueryString)
{
hr = E_OUTOFMEMORY;
goto exit;
}
if ((hr = pXMLDoc->selectNodes(bstrtQueryString, &pNodeList)) != S_OK)
goto exit;
// NOTENOTE - nNodes > 1 should never happen because only one root node in doc.
hr = pNodeList->get_length(&nNodes);
if (nNodes > 1)
{
// multiple file callouts having the exact same file name/path within a single source assembly
hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
goto exit;
}
else if (nNodes < 1)
{
hr = S_FALSE;
goto exit;
}
if ((hr = pNodeList->get_item(0, &pNode)) != S_OK)
{
hr = S_FALSE ? E_FAIL : hr;
goto exit;
}
*ppNode=pNode;
(*ppNode)->AddRef();
exit:
if(bstrtQueryString)
::SysFreeString(bstrtQueryString);
SAFERELEASE(pNodeList);
SAFERELEASE(pNode);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// FormatXML
// Called recursively.
// BUGBUG - t-peterf to document why selectNodes should not be used when
// adding nodes to an existing document.
/////////////////////////////////////////////////////////////////////////
HRESULT FormatXML(IXMLDOMDocument2 *pXMLDoc, IXMLDOMNode *pRootNode, LONG dwLevel)
{
HRESULT hr = S_OK;
IXMLDOMNode *pNode=NULL, *pNewNode=NULL;
IXMLDOMNode *pTextNode1=NULL, *pTextNode2=NULL;
CString sWhiteSpace1, sWhiteSpace2;
BOOL bHasChildren = FALSE;
int i = 0;
sWhiteSpace1.Assign(L"\n");
for (i = 0; i < (dwLevel-1); i++)
sWhiteSpace1.Append(L"\t");
sWhiteSpace2.Assign(L"\n");
for (i = 0; i < dwLevel; i++)
sWhiteSpace2.Append(L"\t");
hr = pRootNode->get_firstChild(&pNode);
while(pNode != NULL)
{
bHasChildren = TRUE;
// create whitespace with one extra tab.
if(FAILED(CreateXMLTextNode(pXMLDoc, sWhiteSpace2._pwz, &pTextNode2)))
goto exit;
VARIANT varRefNode;
VariantInit(&varRefNode);
varRefNode.vt = VT_UNKNOWN;
V_UNKNOWN(&varRefNode) = pNode;
if (FAILED(hr = pRootNode->insertBefore(pTextNode2, varRefNode, &pNewNode)))
goto exit;
SAFERELEASE(pNewNode);
SAFERELEASE(pTextNode2);
// Recursively call format on the node.
if (FAILED(FormatXML(pXMLDoc, pNode, dwLevel+1)))
goto exit;
pNode->get_nextSibling(&pNewNode);
SAFERELEASE(pNode);
pNode = pNewNode;
}
if (bHasChildren)
{
if(FAILED(CreateXMLTextNode(pXMLDoc, sWhiteSpace1._pwz, &pTextNode1)))
goto exit;
if (FAILED(hr = pRootNode->appendChild(pTextNode1, &pNewNode)))
goto exit;
}
exit:
return hr;
}
/////////////////////////////////////////////////////////////////////////
// CreateManifestFromAssembly
/////////////////////////////////////////////////////////////////////////
HRESULT CreateAppManifestTemplate(LPWSTR pwzTempFile)
{
HRESULT hr=S_OK;
IXMLDOMDocument2 *pXMLDoc = NULL;
IXMLDOMElement *pElement=NULL, *pChildElement=NULL, *pChildElement2=NULL, *pChildElement3=NULL;
IXMLDOMNode *pNewNode=NULL, *pRoot=NULL, *pTextNode = NULL;
if(FAILED(hr = CoCreateInstance(__uuidof(private_MSXML_DOMDocument30),
NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pXMLDoc)))
goto exit;
/*
if(FAILED(hr = AddMgVersionAsComment(pXMLDoc, &pRoot)))
goto exit;
*/
//create the root assembly node and add the default properties
if(FAILED(hr = CreateXMLElement(pXMLDoc, ASSEMBLY, &pElement)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, NAMESPACE_TITLE, NAMESPACE_VALUE)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, MANIFEST_VERSION_TITLE, MANIFEST_VERSION_VALUE)))
goto exit;
//append the root to the DOMDocument
if (FAILED(hr = pXMLDoc->appendChild((IXMLDOMNode *)pElement, &pRoot)))
goto exit;
SAFERELEASE(pElement);
//create the tempate assemblyIdentity node with blank attributes
if(FAILED(hr = CreateXMLElement(pXMLDoc, ASSEMBLY_IDENTITY, &pElement)))
goto exit;
hr = SetXMLElementAttribute(pElement, L"type", L"application");
hr = SetXMLElementAttribute(pElement, L"name", L"");
hr = SetXMLElementAttribute(pElement, L"version", L"");
hr = SetXMLElementAttribute(pElement, L"processorArchitecture", L"");
hr = SetXMLElementAttribute(pElement, L"publicKeyToken", L"");
hr = SetXMLElementAttribute(pElement, L"language", L"");
//append this to the root node
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pElement);
SAFERELEASE(pNewNode);
//create a sample description
if(FAILED(hr = CreateXMLElement(pXMLDoc, DESCRIPTION, &pElement)))
goto exit;
if(FAILED(hr = CreateXMLTextNode(pXMLDoc, L"Put a description of your application here", &pTextNode)))
goto exit;
if (FAILED(hr=pElement->appendChild(pTextNode, &pNewNode)))
goto exit;
SAFERELEASE(pNewNode);
SAFERELEASE(pTextNode);
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pNewNode);
SAFERELEASE(pElement);
//Create the shellState tag and enter in default information
if(FAILED(hr = CreateXMLElement(pXMLDoc, APPLICATION, &pElement)))
goto exit;
if(FAILED(hr = CreateXMLElement(pXMLDoc, SHELL_STATE, &pChildElement)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"friendlyName", L"")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"entryPoint", L"")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"entryImageType", L"")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"showCommand", L"")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"hotKey", L"")))
goto exit;
if (FAILED(hr=pElement->appendChild((IXMLDOMNode *)pChildElement, &pNewNode)))
goto exit;
SAFERELEASE (pNewNode);
SAFERELEASE(pChildElement);
if(FAILED(hr = CreateXMLElement(pXMLDoc, ACTIVATION, &pChildElement)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"assemblyName", L"")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"assemblyClass", L"")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"assemblyMethod", L"")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"assemblyMethodArgs", L"")))
goto exit;
if (FAILED(hr=pElement->appendChild((IXMLDOMNode *)pChildElement, &pNewNode)))
goto exit;
SAFERELEASE (pNewNode);
SAFERELEASE(pChildElement);
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pElement);
SAFERELEASE (pNewNode);
//Create the dependency platform tag and enter in default information
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"dependency", &pElement)))
goto exit;
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"platform", &pChildElement)))
goto exit;
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"osVersionInfo", &pChildElement2)))
goto exit;
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"os", &pChildElement3)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"majorVersion", L"5")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"minorVersion", L"1")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"buildNumber", L"2600")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"servicePackMajor", L"0")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"servicePackMinor", L"0")))
goto exit;
if (FAILED(hr=pChildElement2->appendChild((IXMLDOMNode *)pChildElement3, NULL)))
goto exit;
SAFERELEASE (pChildElement3);
if (FAILED(hr=pChildElement->appendChild((IXMLDOMNode *)pChildElement2, NULL)))
goto exit;
SAFERELEASE (pChildElement2);
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"platformInfo", &pChildElement2)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement2, L"friendlyName", L"Microsoft Windows XP")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement2, L"href", L"http://www.microsoft.com/windows")))
goto exit;
if (FAILED(hr=pChildElement->appendChild((IXMLDOMNode *)pChildElement2, NULL)))
goto exit;
SAFERELEASE (pChildElement2);
if (FAILED(hr=pElement->appendChild((IXMLDOMNode *)pChildElement, NULL)))
goto exit;
SAFERELEASE(pChildElement);
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"platform", &pChildElement)))
goto exit;
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"dotNetVersionInfo", &pChildElement2)))
goto exit;
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"supportedRuntime", &pChildElement3)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"version", L"v1.0.3705")))
goto exit;
if (FAILED(hr=pChildElement2->appendChild((IXMLDOMNode *)pChildElement3, NULL)))
goto exit;
SAFERELEASE (pChildElement3);
if (FAILED(hr=pChildElement->appendChild((IXMLDOMNode *)pChildElement2, NULL)))
goto exit;
SAFERELEASE (pChildElement2);
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"platformInfo", &pChildElement2)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement2, L"friendlyName", L"Microsoft .Net Frameworks")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pChildElement2, L"href", L"http://www.microsoft.com/net")))
goto exit;
if (FAILED(hr=pChildElement->appendChild((IXMLDOMNode *)pChildElement2, NULL)))
goto exit;
SAFERELEASE (pChildElement2);
if (FAILED(hr=pElement->appendChild((IXMLDOMNode *)pChildElement, NULL)))
goto exit;
SAFERELEASE(pChildElement);
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, NULL)))
goto exit;
SAFERELEASE(pElement);
//Format and save the document
if(FAILED(hr = FormatXML(pXMLDoc, pRoot, 1)))
goto exit;
if(FAILED(hr = SaveXMLDocument(pXMLDoc, pwzTempFile)))
goto exit;
printf("\nTemplate file created succesfully\n%ws\n", pwzTempFile);
exit:
SAFERELEASE(pXMLDoc);
SAFERELEASE(pElement);
SAFERELEASE(pChildElement3);
SAFERELEASE(pChildElement2);
SAFERELEASE(pChildElement);
SAFERELEASE(pNewNode);
SAFERELEASE(pTextNode);
SAFERELEASE(pRoot);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// CreateSubscriptionManifest
/////////////////////////////////////////////////////////////////////////
HRESULT CreateXMLSubscriptionManifest(LPWSTR pwzSubscriptionPath,
IAssemblyIdentity *pApplictionAssemblyId, LPWSTR pwzUrl, LPWSTR pwzPollingInterval)
{
HRESULT hr=S_OK;
IXMLDOMDocument2 *pXMLDoc = NULL;
IXMLDOMElement *pElement=NULL, *pChildElement=NULL, *pDependantAssemblyNode=NULL;
IXMLDOMNode *pNewNode=NULL, *pRoot=NULL, *pTextNode = NULL, *pDependancyNode = NULL;
CString sSubscriptionPath, sSubscriptionName;
sSubscriptionPath.Assign(pwzSubscriptionPath);
sSubscriptionPath.LastElement(sSubscriptionName);
sSubscriptionPath.Append(L".manifest");
if(FAILED(hr = CoCreateInstance(__uuidof(private_MSXML_DOMDocument30),
NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pXMLDoc)))
goto exit;
if(FAILED(hr = AddMgVersionAsComment(pXMLDoc, &pRoot)))
goto exit;
//create the root assembly node and add the default properties
if(FAILED(hr = CreateXMLElement(pXMLDoc, ASSEMBLY, &pElement)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, NAMESPACE_TITLE, NAMESPACE_VALUE)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, MANIFEST_VERSION_TITLE, MANIFEST_VERSION_VALUE)))
goto exit;
//append the root to the DOMDocument
if (FAILED(hr = pXMLDoc->appendChild((IXMLDOMNode *)pElement, &pRoot)))
goto exit;
SAFERELEASE(pElement);
//Create the AssemblyId for the Subscription
//Use the AssemblyId of the application, but change the name and type
if (FAILED(CreateXMLAssemblyIdElement(pXMLDoc, pApplictionAssemblyId, &pElement)))
goto exit;
// bugbug - check return code for consistency.
hr = SetXMLElementAttribute(pElement, L"type", L"subscription");
hr = SetXMLElementAttribute(pElement, L"name", sSubscriptionName._pwz);
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pElement);
SAFERELEASE(pNewNode);
//create a sample description
//bugbug, should grab description for original manifest and paste it here
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"description", &pElement)))
goto exit;
if(FAILED(hr = CreateXMLTextNode(pXMLDoc, L"Put a description of your application here", &pTextNode)))
goto exit;
if (FAILED(hr=pElement->appendChild(pTextNode, &pNewNode)))
goto exit;
SAFERELEASE(pNewNode);
SAFERELEASE(pTextNode);
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pNewNode);
SAFERELEASE(pElement);
//Create the Dependancy Node
if(FAILED(hr = CreateXMLElement(pXMLDoc, DEPENDENCY, &pElement)))
goto exit;
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pDependancyNode)))
goto exit;
SAFERELEASE(pElement);
//Create a dependentAssembly node
if(FAILED(hr = CreateXMLElement(pXMLDoc, DEPENDANT_ASSEMBLY, &pDependantAssemblyNode)))
goto exit;
//Create the AssemblyId for the Dependant Assembly
if (FAILED(CreateXMLAssemblyIdElement(pXMLDoc, pApplictionAssemblyId, &pElement)))
goto exit;
//Append the AssemblyId to the dependantAssemblyNode
if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pElement);
SAFERELEASE(pNewNode);
//Add the install codebase to the dependantAssemblyNode
if(FAILED(hr = CreateXMLElement(pXMLDoc, INSTALL, &pElement)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, CODEBASE, pwzUrl)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, L"type", L"required")))
goto exit;
if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pElement);
SAFERELEASE(pNewNode);
//Add the install codebase to the dependantAssemblyNode
if(FAILED(hr = CreateXMLElement(pXMLDoc, L"subscription", &pElement)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, L"synchronizeInterval", pwzPollingInterval)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, L"intervalUnit", L"hours")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, L"synchronizeEvent", L"onApplicationStartup")))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, L"eventDemandConnection", L"no")))
goto exit;
if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
SAFERELEASE(pElement);
SAFERELEASE(pNewNode);
//Append the dependantAssemblyNode to the dependancy node
if (FAILED(hr=pDependancyNode->appendChild(pDependantAssemblyNode, &pNewNode)))
goto exit;
SAFERELEASE(pDependantAssemblyNode);
SAFERELEASE(pNewNode);
//Format and save the document
hr = FormatXML(pXMLDoc, pRoot, 1);
if(FAILED(hr = SaveXMLDocument(pXMLDoc, sSubscriptionPath._pwz)))
goto exit;
printf("Subscription manifest succesfully created\n%ws\n", sSubscriptionPath._pwz);
exit:
SAFERELEASE(pXMLDoc);
SAFERELEASE(pElement);
SAFERELEASE(pChildElement);
SAFERELEASE(pNewNode);
SAFERELEASE(pTextNode);
SAFERELEASE(pRoot);
SAFERELEASE(pDependancyNode);
SAFERELEASE(pDependantAssemblyNode);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// CreateXMLAppManifest
// Creates the app manifest - may want to rename.
/////////////////////////////////////////////////////////////////////////
// NOTENOTE: rename pList -> pAsmList ?
HRESULT CreateXMLAppManifest(LPWSTR pwzAppBase, LPWSTR pwzTemplateFilePath, List<ManifestNode *> *pList, List<LPWSTR> *pFileList)
{
HRESULT hr = S_OK;
DWORD cc = 0, cb = 0, ccName = 0;
LPWSTR pwz=NULL, pwzCodeBase = NULL, pwzName = NULL;
IAssemblyIdentity *pASMId= NULL;
IXMLDOMDocument2 *pXMLDoc=NULL;
IXMLDOMElement *pElement=NULL, *pAssemblyIdElement = NULL;
IXMLDOMNode *pRoot=NULL, *pDependancyNode = NULL, *pNewNode = NULL;
IXMLDOMNode *pAssemblyIdNode = NULL, *pDependantAssemblyNode=NULL;
BSTR bstrAttribute = NULL;
VARIANT varAttribute;
ManifestNode *pManNode = NULL;
CString sAppName, sFileName, sFileHash, sAbsoluteFilePath, sManifestFilePath;
LISTNODE pos = NULL;
VariantInit(&varAttribute);
//Load the template
if(FAILED(hr = LoadXMLDocument(pwzTemplateFilePath, &pXMLDoc)))
goto exit;
//grab the first child(the only child) as the root node
if(FAILED(hr = GetNode(pXMLDoc, ASSEMBLY, &pRoot)))
goto exit;
if (hr == S_FALSE)
{
hr = E_INVALIDARG;
goto exit;
}
//Get the name from the assemblyId, this will be the manifests file name
if(FAILED(hr = pRoot->get_firstChild(&pAssemblyIdNode)))
goto exit;
//Query for the Element interface
if (FAILED(hr = pAssemblyIdNode->QueryInterface(IID_IXMLDOMElement, (void**) &pAssemblyIdElement)))
goto exit;
bstrAttribute = ::SysAllocString(L"name");
if (!bstrAttribute)
{
hr = E_OUTOFMEMORY;
goto exit;
}
if ((hr = pAssemblyIdElement->getAttribute(bstrAttribute, &varAttribute)) != S_OK)
goto exit;
ccName = ::SysStringLen(varAttribute.bstrVal) + 1;
pwzName = new WCHAR[ccName];
if (!pwzName)
{
hr = E_OUTOFMEMORY;
goto exit;
}
memcpy(pwzName, varAttribute.bstrVal, ccName * sizeof(WCHAR));
if((*pwzName)== NULL)
{
hr = E_FAIL;
printf("Invalid Template Format. Template must have a name attribute in the assemblyIdentity tag\n");
goto exit;
}
::SysFreeString(varAttribute.bstrVal);
::SysFreeString(bstrAttribute);
SAFERELEASE(pAssemblyIdElement);
SAFERELEASE(pAssemblyIdNode);
if(FAILED(hr = AddMgVersionAsComment(pXMLDoc, &pRoot)))
goto exit;
// Add all the raw files to the manifest
pos = pFileList->GetHeadPosition();
while (pos)
{
pwz = pFileList->GetNext(pos);
sFileName.Assign(pwz);
if(FAILED(hr = CreateXMLElement(pXMLDoc, FILE, &pElement)))
goto exit;
if(FAILED(hr = SetXMLElementAttribute(pElement, FILE_NAME, sFileName._pwz)))
goto exit;
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
goto exit;
//Get Absolute File Path of file
sAbsoluteFilePath.Assign(pwzAppBase);
sAbsoluteFilePath.Append(sFileName);
//get the hash of the file
if(FAILED(hr = GetHash(sAbsoluteFilePath._pwz, &pwz)))
goto exit;
sFileHash.TakeOwnership(pwz);
if(FAILED(hr = SetXMLElementAttribute(pElement, FILE_HASH, sFileHash._pwz)))
goto exit;
SAFERELEASE(pNewNode);
}
// Get Dependency Node if exists
if (FAILED(hr = GetNode(pXMLDoc, DEPENDENCY_QUERY, &pDependancyNode)))
goto exit;
if (hr == S_FALSE)
{
//Create the Dependancy Node
if(FAILED(hr = CreateXMLElement(pXMLDoc, DEPENDENCY, &pElement)))
goto exit;
if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pDependancyNode)))
goto exit;
SAFERELEASE(pElement);
}
//Walk thorugh the list of dependant assemblies and add them to the App Manifest
pos = pList->GetHeadPosition();
while (pos)
{
//Get next Dependant Assembly from list
pManNode = pList->GetNext(pos);
if (FAILED(hr = CreateDependantAssemblyNode(pXMLDoc, pManNode, &pDependantAssemblyNode)))
goto exit;
if (FAILED(hr=pDependancyNode->appendChild(pDependantAssemblyNode, &pNewNode)))
goto exit;
SAFERELEASE(pDependantAssemblyNode);
SAFERELEASE(pNewNode);
}
//Indent the manifest
hr = FormatXML(pXMLDoc, pRoot, 1);
// Save the manifest to a file
sManifestFilePath.Assign(pwzAppBase);
sManifestFilePath.Append(pwzName);
sManifestFilePath.Append(L".manifest");
if(FAILED(hr = SaveXMLDocument(pXMLDoc, sManifestFilePath._pwz)))
goto exit;
printf("\nManifest created succesfully\n%ws\n", sManifestFilePath._pwz);
exit:
if (varAttribute.bstrVal)
::SysFreeString(varAttribute.bstrVal);
SAFEDELETEARRAY(pwzName);
SAFERELEASE(pXMLDoc);
SAFERELEASE(pElement);
SAFERELEASE(pAssemblyIdElement);
SAFERELEASE(pNewNode);
SAFERELEASE(pAssemblyIdNode);
SAFERELEASE(pRoot);
SAFERELEASE(pDependancyNode);
SAFERELEASE(pDependantAssemblyNode);
return hr;
}
/////////////////////////////////////////////////////////////////////////
// SaveXMLDocument
/////////////////////////////////////////////////////////////////////////
HRESULT SaveXMLDocument(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzDocumentName)
{
HRESULT hr = S_OK;
CString sDocumentName;
BSTR bstrFileName = NULL;
VARIANT varFileName;
// Save the manifest to a file
sDocumentName.Assign(pwzDocumentName);
bstrFileName = ::SysAllocString(sDocumentName._pwz);
if (!bstrFileName)
{
hr = E_OUTOFMEMORY;
goto exit;
}
VariantInit(&varFileName);
varFileName.vt = VT_BSTR;
V_BSTR(&varFileName) = bstrFileName;
hr = pXMLDoc->save(varFileName);
exit:
if(bstrFileName)
::SysFreeString(bstrFileName);
return hr;
}
/////////////////////////////////////////////////////////////////////////
//LoadXMLDocument
/////////////////////////////////////////////////////////////////////////
HRESULT LoadXMLDocument(LPWSTR pwzDocumentPath, IXMLDOMDocument2 **ppXMLDoc)
{
HRESULT hr = S_OK;
IXMLDOMDocument2 *pXMLDoc;
VARIANT varFileName;
VARIANT_BOOL varBool;
BSTR bstrFileName = NULL;
bstrFileName = ::SysAllocString(pwzDocumentPath);
if (!bstrFileName)
{
hr = E_OUTOFMEMORY;
goto exit;
}
VariantInit(&varFileName);
varFileName.vt = VT_BSTR;
V_BSTR(&varFileName) = bstrFileName;
if(FAILED(hr = CoCreateInstance(__uuidof(private_MSXML_DOMDocument30),
NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pXMLDoc)))
goto exit;
// Load synchronously
if (FAILED(hr = pXMLDoc->put_async(VARIANT_FALSE)))
goto exit;
if ((hr = pXMLDoc->load(varFileName, &varBool)) != S_OK)
{
if(!varBool)
hr = E_INVALIDARG;
goto exit;
}
*ppXMLDoc=pXMLDoc;
(*ppXMLDoc)->AddRef();
exit:
if(bstrFileName)
::SysFreeString(bstrFileName);
SAFERELEASE(pXMLDoc);
return hr;
}