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.
 
 
 
 
 
 

784 lines
22 KiB

#using <mscorlib.dll>
#using "assm.netmodule"
#include <stdio.h>
#include <windows.h>
#include <fusenet.h>
#include <util.h>
#include <shlwapi.h>
#include <sxsapi.h>
#include <wchar.h>
#include "cor.h"
using namespace System;
using namespace Microsoft::Fusion::ADF;
using System::Runtime::InteropServices::Marshal;
#define ASM_MANIFEST_IMPORT_DEFAULT_ARRAY_SIZE 32
#define MAX_PKT_LEN 33
typedef HRESULT (*pfnGetAssemblyMDImport)(LPCWSTR szFileName, REFIID riid, LPVOID *ppv);
typedef BOOL (*pfnStrongNameTokenFromPublicKey)(LPBYTE, DWORD, LPBYTE*, LPDWORD);
typedef HRESULT (*pfnStrongNameErrorInfo)();
typedef VOID (*pfnStrongNameFreeBuffer)(LPBYTE);
//#pragma unmanaged
pfnGetAssemblyMDImport g_pfnGetAssemblyMDImport = NULL;
pfnStrongNameTokenFromPublicKey g_pfnStrongNameTokenFromPublicKey = NULL;
pfnStrongNameErrorInfo g_pfnStrongNameErrorInfo = NULL;
pfnStrongNameFreeBuffer g_pfnStrongNameFreeBuffer = NULL;
//--------------------------------------------------------------------
// BinToUnicodeHex
//--------------------------------------------------------------------
HRESULT BinToUnicodeHex(LPBYTE pSrc, UINT cSrc, LPWSTR pDst)
{
UINT x;
UINT y;
#define TOHEX(a) ((a)>=10 ? L'a'+(a)-10 : L'0'+(a))
for ( x = 0, y = 0 ; x < cSrc ; ++x )
{
UINT v;
v = pSrc[x]>>4;
pDst[y++] = TOHEX( v );
v = pSrc[x] & 0x0f;
pDst[y++] = TOHEX( v );
}
pDst[y] = '\0';
return S_OK;
}
// ---------------------------------------------------------------------------
// DeAllocateAssemblyMetaData
//-------------------------------------------------------------------
STDAPI DeAllocateAssemblyMetaData(ASSEMBLYMETADATA *pamd)
{
// NOTE - do not 0 out counts
// since struct may be reused.
pamd->cbLocale = 0;
SAFEDELETEARRAY(pamd->szLocale);
SAFEDELETEARRAY(pamd->rProcessor);
SAFEDELETEARRAY(pamd->rOS);
return S_OK;
}
// ---------------------------------------------------------------------------
// InitializeEEShim
//-------------------------------------------------------------------
HRESULT InitializeEEShim()
{
HRESULT hr = S_OK;
MAKE_ERROR_MACROS_STATIC(hr);
HMODULE hMod;
// BUGBUG - mscoree.dll never gets unloaded with increasing ref count.
// what does URT do?
hMod = LoadLibrary(TEXT("mscoree.dll"));
IF_WIN32_FALSE_EXIT(hMod);
g_pfnGetAssemblyMDImport = (pfnGetAssemblyMDImport)GetProcAddress(hMod, "GetAssemblyMDImport");
g_pfnStrongNameTokenFromPublicKey = (pfnStrongNameTokenFromPublicKey)GetProcAddress(hMod, "StrongNameTokenFromPublicKey");
g_pfnStrongNameErrorInfo = (pfnStrongNameErrorInfo)GetProcAddress(hMod, "StrongNameErrorInfo");
g_pfnStrongNameFreeBuffer = (pfnStrongNameFreeBuffer)GetProcAddress(hMod, "StrongNameFreeBuffer");
if (!g_pfnGetAssemblyMDImport || !g_pfnStrongNameTokenFromPublicKey || !g_pfnStrongNameErrorInfo
|| !g_pfnStrongNameFreeBuffer)
{
hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
goto exit;
}
exit:
return hr;
}
// ---------------------------------------------------------------------------
// CreateMetaDataImport
//-------------------------------------------------------------------
HRESULT CreateMetaDataImport(LPCOLESTR pszFilename, IMetaDataAssemblyImport **ppImport)
{
HRESULT hr= S_OK;
MAKE_ERROR_MACROS_STATIC(hr);
IF_FAILED_EXIT(InitializeEEShim());
hr = (*g_pfnGetAssemblyMDImport)(pszFilename, IID_IMetaDataAssemblyImport, (void **)ppImport);
IF_TRUE_EXIT(hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT), hr); // do not assert
IF_FAILED_EXIT(hr);
exit:
return hr;
}
// ---------------------------------------------------------------------------
// AllocateAssemblyMetaData
//-------------------------------------------------------------------
STDAPI AllocateAssemblyMetaData(ASSEMBLYMETADATA *pamd)
{
HRESULT hr = S_OK;
MAKE_ERROR_MACROS_STATIC(hr);
// Re/Allocate Locale array
SAFEDELETEARRAY(pamd->szLocale);
if (pamd->cbLocale) {
IF_ALLOC_FAILED_EXIT(pamd->szLocale = new(WCHAR[pamd->cbLocale]));
}
// Re/Allocate Processor array
SAFEDELETEARRAY(pamd->rProcessor);
IF_ALLOC_FAILED_EXIT(pamd->rProcessor = new(DWORD[pamd->ulProcessor]));
// Re/Allocate OS array
SAFEDELETEARRAY(pamd->rOS);
IF_ALLOC_FAILED_EXIT(pamd->rOS = new(OSINFO[pamd->ulOS]));
exit:
if (FAILED(hr) && pamd)
DeAllocateAssemblyMetaData(pamd);
return hr;
}
// ---------------------------------------------------------------------------
// ByteArrayMaker
// ---------------------------------------------------------------------------
HRESULT ByteArrayMaker(LPVOID pvOriginator, DWORD dwOriginator, LPBYTE *ppbPublicKeyToken, DWORD *pcbPublicKeyToken)
{
//LPBYTE pbPublicKeyToken;
//DWORD cbPublicKeyToken;
if (!(g_pfnStrongNameTokenFromPublicKey((LPBYTE)pvOriginator, dwOriginator, ppbPublicKeyToken, pcbPublicKeyToken)))
{
return g_pfnStrongNameErrorInfo();
}
//*ppbPublicKeyToken = pbPublicKeyToken;
//*pcbPublicKeyToken = cbPublicKeyToken;
return S_OK;
}
// ---------------------------------------------------------------------------
// ByteArrayFreer
// ---------------------------------------------------------------------------
void ByteArrayFreer(LPBYTE pbPublicKeyToken)
{
g_pfnStrongNameFreeBuffer(pbPublicKeyToken);
}
//#pragma managed
namespace FusionADF
{
__gc public class AssemblyManifestParser
{
public:
// ---------------------------------------------------------------------------
// AssemblyManifestParser constructor
// ---------------------------------------------------------------------------
AssemblyManifestParser()
{
_dwSig = 'INAM';
_pMDImport = NULL;
_rAssemblyRefTokens = NULL;
_cAssemblyRefTokens = 0;
_rAssemblyModuleTokens = NULL;
_cAssemblyModuleTokens = 0;
*_szManifestFilePath = TEXT('\0');
_ccManifestFilePath = 0;
*_szAssemblyName = TEXT('\0');
_pvOriginator = NULL;
_dwOriginator = 0;
_name = NULL;
_version = NULL;
*_szPubKeyTokStr = TEXT('\0');
_pktString = NULL;
_procArch = NULL;
_language = NULL;
_hr = S_OK;
instanceValid = false;
initCalledOnce = false;
}
// ---------------------------------------------------------------------------
// AssemblyManifestParser destructor
// ---------------------------------------------------------------------------
~AssemblyManifestParser()
{
SAFERELEASE(_pMDImport);
SAFEDELETEARRAY(_rAssemblyRefTokens);
SAFEDELETEARRAY(_rAssemblyModuleTokens);
}
bool InitFromFile(String* filePath)
{
LPCOLESTR lstr = 0;
HRESULT hr;
if(initCalledOnce) return false;
initCalledOnce = true;
try
{
lstr = static_cast<LPCOLESTR>(const_cast<void*>(static_cast<const void*>(Marshal::StringToHGlobalAuto(filePath))));
}
catch(ArgumentException *e)
{
// handle the exception
return false;
}
catch (OutOfMemoryException *e)
{
// handle the exception
return false;
}
hr = Init(lstr);
if(hr != S_OK) return false;
instanceValid = true;
return true;
}
bool IsInstanceValid()
{
return instanceValid;
}
bool HasInitBeenCalled()
{
return initCalledOnce;
}
// ---------------------------------------------------------------------------
// GetAssemblyIdentity
// ---------------------------------------------------------------------------
AssemblyIdentity* GetAssemblyIdentity()
{
return new AssemblyIdentity(_name, _version, _pktString, _procArch, _language);
}
// ---------------------------------------------------------------------------
// GetNumDependentAssemblies
// ---------------------------------------------------------------------------
int GetNumDependentAssemblies()
{
return _cAssemblyRefTokens;
}
// ---------------------------------------------------------------------------
// GetDependentAssemblyInfo
// ---------------------------------------------------------------------------
DependentAssemblyInfo* GetDependentAssemblyInfo(int nIndex)
{
WCHAR szAssemblyName[MAX_PATH];
const VOID* pvOriginator = 0;
const VOID* pvHashValue = NULL;
DWORD ccAssemblyName = MAX_PATH,
cbOriginator = 0,
ccLocation = MAX_PATH,
cbHashValue = 0,
dwRefFlags = 0;
INT i;
LPWSTR pwz=NULL;
mdAssemblyRef mdmar;
ASSEMBLYMETADATA amd = {0};
String *name = NULL, *pktString = NULL, *procArch = NULL, *language = NULL;
Version *version = NULL;
// Verify the index passed in.
if (nIndex >= _cAssemblyRefTokens)
{
_hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
goto exit;
}
// Reference indexed dep assembly ref token.
mdmar = _rAssemblyRefTokens[nIndex];
// Default allocation sizes.
amd.ulProcessor = amd.ulOS = 32;
amd.cbLocale = MAX_PATH;
// Loop max 2 (try/retry)
for (i = 0; i < 2; i++)
{
// Allocate ASSEMBLYMETADATA instance.
IF_FAILED_EXIT(AllocateAssemblyMetaData(&amd));
// Get the properties for the refrenced assembly.
IF_FAILED_EXIT(_pMDImport->GetAssemblyRefProps(
mdmar, // [IN] The AssemblyRef for which to get the properties.
&pvOriginator, // [OUT] Pointer to the PublicKeyToken blob.
&cbOriginator, // [OUT] Count of bytes in the PublicKeyToken Blob.
szAssemblyName, // [OUT] Buffer to fill with name.
MAX_PATH, // [IN] Size of buffer in wide chars.
&ccAssemblyName, // [OUT] Actual # of wide chars in name.
&amd, // [OUT] Assembly MetaData.
&pvHashValue, // [OUT] Hash blob.
&cbHashValue, // [OUT] Count of bytes in the hash blob.
&dwRefFlags // [OUT] Flags.
));
// Check if retry necessary.
if (!i)
{
if (amd.ulProcessor <= 32
&& amd.ulOS <= 32)
{
break;
}
else
DeAllocateAssemblyMetaData(&amd);
}
// Retry with updated sizes
}
// Allow for funky null locale convention
// in metadata - cbLocale == 0 means szLocale ==L'\0'
if (!amd.cbLocale)
{
amd.cbLocale = 1;
}
else if (amd.szLocale)
{
WCHAR *ptr;
ptr = StrChrW(amd.szLocale, L';');
if (ptr)
{
(*ptr) = L'\0';
amd.cbLocale = ((DWORD) (ptr - amd.szLocale) + sizeof(WCHAR));
}
}
else
{
_hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
goto exit;
}
//Name
name = new String(szAssemblyName);
//Version
version = new Version(amd.usMajorVersion, amd.usMinorVersion, amd.usBuildNumber, amd.usRevisionNumber);
//Public Key Token
if (cbOriginator)
{
IF_ALLOC_FAILED_EXIT(pwz = new WCHAR[cbOriginator*2 +1]);
IF_FAILED_EXIT(BinToUnicodeHex((LPBYTE)pvOriginator, cbOriginator, pwz));
pktString = new String(pwz);
SAFEDELETEARRAY(pwz);
}
//Architecture
procArch = S"x86";
//Language
if (!(*amd.szLocale)) language = S"*";
else language = new String(amd.szLocale);
_hr = S_OK;
exit:
DeAllocateAssemblyMetaData(&amd);
SAFEDELETEARRAY(pwz);
if(_hr != S_OK) return NULL;
else return new DependentAssemblyInfo(new AssemblyIdentity(name, version, pktString, procArch, language), NULL);
}
// ---------------------------------------------------------------------------
// GetNumDependentFiles
// ---------------------------------------------------------------------------
int GetNumDependentFiles()
{
return _cAssemblyModuleTokens;
}
// ---------------------------------------------------------------------------
// GetDependentFileInfo
// ---------------------------------------------------------------------------
DependentFileInfo* GetDependentFileInfo(int nIndex)
{
LPWSTR pszName = NULL;
DWORD ccPath = 0;
WCHAR szModulePath[MAX_PATH];
mdFile mdf;
WCHAR szModuleName[MAX_PATH];
DWORD ccModuleName = MAX_PATH;
const VOID* pvHashValue = NULL;
DWORD cbHashValue = 0;
DWORD dwFlags = 0;
LPWSTR pwz=NULL;
String *name = NULL, *hash = NULL;
// Verify the index.
if (nIndex >= _cAssemblyModuleTokens)
{
_hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
goto exit;
}
// Reference indexed dep assembly ref token.
mdf = _rAssemblyModuleTokens[nIndex];
// Get the properties for the refrenced assembly.
IF_FAILED_EXIT(_pMDImport->GetFileProps(
mdf, // [IN] The File for which to get the properties.
szModuleName, // [OUT] Buffer to fill with name.
MAX_CLASS_NAME, // [IN] Size of buffer in wide chars.
&ccModuleName, // [OUT] Actual # of wide chars in name.
&pvHashValue, // [OUT] Pointer to the Hash Value Blob.
&cbHashValue, // [OUT] Count of bytes in the Hash Value Blob.
&dwFlags)); // [OUT] Flags.
//name
name = new String(szModuleName);
//hash
if (cbHashValue)
{
IF_ALLOC_FAILED_EXIT(pwz = new WCHAR[cbHashValue*2 +1]);
IF_FAILED_EXIT(_hr = BinToUnicodeHex((LPBYTE)pvHashValue, cbHashValue, pwz));
hash = new String(pwz);
SAFEDELETEARRAY(pwz);
}
_hr = S_OK;
exit:
SAFEDELETEARRAY(pwz);
if(_hr != S_OK) return NULL;
else return new DependentFileInfo(name, hash);
}
private:
DWORD _dwSig;
HRESULT _hr;
WCHAR _szManifestFilePath __nogc[MAX_PATH];
DWORD _ccManifestFilePath;
WCHAR _szAssemblyName __nogc[MAX_CLASS_NAME];
IMetaDataAssemblyImport *_pMDImport;
PBYTE _pMap;
mdAssembly *_rAssemblyRefTokens;
DWORD _cAssemblyRefTokens;
mdFile *_rAssemblyModuleTokens;
DWORD _cAssemblyModuleTokens;
LPVOID _pvOriginator;
DWORD _dwOriginator;
String* _name;
Version* _version;
WCHAR _szPubKeyTokStr __nogc[MAX_PKT_LEN];
String* _pktString;
String* _procArch;
String* _language;
bool instanceValid;
bool initCalledOnce;
// ---------------------------------------------------------------------------
// Init
// ---------------------------------------------------------------------------
HRESULT Init(LPCOLESTR szManifestFilePath)
{
WCHAR __pin *tempFP = _szManifestFilePath;
WCHAR __pin *temp_szAssemblyName = _szAssemblyName;
WCHAR __pin *temp_szPubKeyTokStr = _szPubKeyTokStr;
LPBYTE pbPublicKeyToken = NULL;
DWORD cbPublicKeyToken = 0;
DWORD dwFlags = 0, dwSize = 0, dwHashAlgId = 0;
INT i;
ASSEMBLYMETADATA amd = {0};
const cElems = ASM_MANIFEST_IMPORT_DEFAULT_ARRAY_SIZE;
// ********** First, work on getting metadata from file.
// ********** ------------------------------------------
IF_NULL_EXIT(szManifestFilePath, E_INVALIDARG);
_ccManifestFilePath = lstrlenW(szManifestFilePath) + 1;
memcpy(tempFP, szManifestFilePath, _ccManifestFilePath * sizeof(WCHAR));
IF_ALLOC_FAILED_EXIT(_rAssemblyRefTokens = new(mdAssemblyRef[cElems]));
IF_ALLOC_FAILED_EXIT(_rAssemblyModuleTokens = new(mdFile[cElems]));
// Create meta data importer if necessary.
if (!_pMDImport)
{
IMetaDataAssemblyImport *temp_pMDImport;
// Create meta data importer
_hr = CreateMetaDataImport((LPCOLESTR)tempFP, &temp_pMDImport);
IF_TRUE_EXIT(_hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT), _hr);
IF_FAILED_EXIT(_hr);
_pMDImport = temp_pMDImport;
}
// ********** Next, get the assembly identity fields.
// ********** ---------------------------------------
mdAssembly mda;
// Get the assembly token.
if(FAILED(_hr = _pMDImport->GetAssemblyFromScope(&mda)))
{
// This fails when called with managed module and not manifest. mg does such things.
_hr = S_FALSE; // this will convert CLDB_E_RECORD_NOTFOUND (0x80131130) to S_FALSE;
goto exit;
}
// Default allocation sizes.
amd.ulProcessor = amd.ulOS = 32;
amd.cbLocale = MAX_PATH;
// Loop max 2 (try/retry)
for (i = 0; i < 2; i++)
{
// Create an ASSEMBLYMETADATA instance.
IF_FAILED_EXIT(AllocateAssemblyMetaData(&amd));
LPVOID temp_pvOriginator;
DWORD temp_dwOriginator;
// Get name and metadata
IF_FAILED_EXIT(_pMDImport->GetAssemblyProps(
mda, // [IN] The Assembly for which to get the properties.
(const void **)&temp_pvOriginator, // [OUT] Pointer to the Originator blob.
&temp_dwOriginator, // [OUT] Count of bytes in the Originator Blob.
&dwHashAlgId, // [OUT] Hash Algorithm.
temp_szAssemblyName, // [OUT] Buffer to fill with name.
MAX_CLASS_NAME, // [IN] Size of buffer in wide chars.
&dwSize, // [OUT] Actual # of wide chars in name.
&amd, // [OUT] Assembly MetaData.
&dwFlags // [OUT] Flags.
));
_pvOriginator = temp_pvOriginator;
_dwOriginator = temp_dwOriginator;
// Check if retry necessary.
if (!i)
{
if (amd.ulProcessor <= 32 && amd.ulOS <= 32)
break;
else
DeAllocateAssemblyMetaData(&amd);
}
}
// Allow for funky null locale convention
// in metadata - cbLocale == 0 means szLocale ==L'\0'
if (!amd.cbLocale)
{
amd.cbLocale = 1;
}
else if (amd.szLocale)
{
WCHAR *ptr;
ptr = StrChrW(amd.szLocale, L';');
if (ptr)
{
(*ptr) = L'\0';
amd.cbLocale = ((DWORD) (ptr - amd.szLocale) + sizeof(WCHAR));
}
}
else
{
_hr = E_FAIL;
goto exit;
}
// NAME is _szAssemblyName, pinned in temp_szAssemblyName, set to _name using the following code:
_name = new String(temp_szAssemblyName);
// VERSION is _version, set using the following code:
_version = new Version(amd.usMajorVersion, amd.usMinorVersion, amd.usBuildNumber, amd.usRevisionNumber);
// PUBLICKEYTOKEN is being figured out
if (_dwOriginator)
{
if(FAILED(_hr = ByteArrayMaker(_pvOriginator, _dwOriginator, &pbPublicKeyToken, &cbPublicKeyToken)))
{
goto exit;
}
if(FAILED(_hr = BinToUnicodeHex(pbPublicKeyToken, cbPublicKeyToken, temp_szPubKeyTokStr)))
{
goto exit;
}
ByteArrayFreer(pbPublicKeyToken);
_pktString = new String(temp_szPubKeyTokStr);
}
// LANGUAGE is _language, set using the following code:
if (!(*amd.szLocale)) _language = S"*";
else _language = new String(amd.szLocale);
// PROCESSOR ARCHITECTURE is _procArch, set using the following code:
_procArch = S"x86";
// ********** Next, get the dependent assemblies.
// ********** -----------------------------------
if (!_cAssemblyRefTokens)
{
DWORD cTokensMax = 0;
HCORENUM hEnum = 0;
// Attempt to get token array. If we have insufficient space
// in the default array we will re-allocate it.
if (FAILED(_hr = _pMDImport->EnumAssemblyRefs(
&hEnum,
_rAssemblyRefTokens,
ASM_MANIFEST_IMPORT_DEFAULT_ARRAY_SIZE,
&cTokensMax)))
{
goto exit;
}
// Number of tokens known. close enum.
_pMDImport->CloseEnum(hEnum);
hEnum = 0;
// Insufficient array size. Grow array.
if (cTokensMax > ASM_MANIFEST_IMPORT_DEFAULT_ARRAY_SIZE)
{
// Re-allocate space for tokens.
SAFEDELETEARRAY(_rAssemblyRefTokens);
_cAssemblyRefTokens = cTokensMax;
_rAssemblyRefTokens = new(mdAssemblyRef[_cAssemblyRefTokens]);
if (!_rAssemblyRefTokens)
{
_hr = E_OUTOFMEMORY;
goto exit;
}
DWORD temp_cART;
// Re-get tokens.
if (FAILED(_hr = _pMDImport->EnumAssemblyRefs(
&hEnum,
_rAssemblyRefTokens,
cTokensMax,
&temp_cART)))
{
goto exit;
}
_cAssemblyRefTokens = temp_cART;
// Close enum.
_pMDImport->CloseEnum(hEnum);
hEnum = 0;
}
// Otherwise, the default array size was sufficient.
else
{
_cAssemblyRefTokens = cTokensMax;
}
}
// ********** Next, get the dependent files / modules.
// ********** ----------------------------------------
if (!_cAssemblyModuleTokens)
{
DWORD cTokensMax = 0;
HCORENUM hEnum = 0;
// Attempt to get token array. If we have insufficient space
// in the default array we will re-allocate it.
if (FAILED(_hr = _pMDImport->EnumFiles(&hEnum, _rAssemblyModuleTokens,
ASM_MANIFEST_IMPORT_DEFAULT_ARRAY_SIZE, &cTokensMax)))
{
goto exit;
}
// Number of tokens known. close enum.
_pMDImport->CloseEnum(hEnum);
hEnum = 0;
if (cTokensMax > ASM_MANIFEST_IMPORT_DEFAULT_ARRAY_SIZE)
{
// Insufficient array size. Grow array.
_cAssemblyModuleTokens = cTokensMax;
SAFEDELETEARRAY(_rAssemblyModuleTokens);
_rAssemblyModuleTokens = new(mdFile[_cAssemblyModuleTokens]);
if(_hr == S_OK) Console::WriteLine(S"Still OK 3");
if (!_rAssemblyModuleTokens)
{
_hr = E_OUTOFMEMORY;
//Console::WriteLine(S"2 HR set, failure, going to exit");
goto exit;
}
DWORD temp_cAMT;
// Re-get tokens.
if (FAILED(_hr = _pMDImport->EnumFiles(
&hEnum,
_rAssemblyModuleTokens,
cTokensMax,
&temp_cAMT)))
{
//Console::WriteLine(S"3 HR set, failure, going to exit");
goto exit;
}
_cAssemblyModuleTokens = temp_cAMT;
// Close enum.
_pMDImport->CloseEnum(hEnum);
hEnum = 0;
}
// Otherwise, the default array size was sufficient.
else _cAssemblyModuleTokens = cTokensMax;
}
_hr = S_OK;
exit:
// ********** If everything worked, _hr will be S_OK. That is for caller to determine.
// ********** ------------------------------------------------------------------------
DeAllocateAssemblyMetaData(&amd);
return _hr;
}
//Functions not implemented
HRESULT GetSubscriptionInfo(IManifestInfo **ppSubsInfo)
{
return E_NOTIMPL;
}
HRESULT GetNextPlatform(DWORD nIndex, IManifestData **ppPlatformInfo)
{
return E_NOTIMPL;
}
HRESULT GetManifestApplicationInfo(IManifestInfo **ppAppInfo)
{
return E_NOTIMPL;
}
HRESULT CQueryFile(LPCOLESTR pwzFileName,IManifestInfo **ppAssemblyFile)
{
return E_NOTIMPL;
}
};
}