|
|
#include <windows.h>
#include <fusenetincludes.h>
#include <stdio.h>
#include "mg.h"
#include "manifestnode.h"
#include "xmlutil.h"
#include "assemblycache.h"
#include "version.h"
#define DIRECTORY_PATH 0
#define FILE_PATH 1
#define DEFAULT_POLLING_INTERVAL L"6"
#define MAX_DEPLOY_DIRS (5)
CString g_sDeployDirs[MAX_DEPLOY_DIRS]; DWORD g_dwDeployDirs=0;
typedef enum _COMMAND_MODE_ { CmdUsage, CmdTemplate, CmdList, CmdDependencyList, CmdSubscription, CmdManifest, } COMMAND_MODE, *LPCOMMAND_MODE;
CString g_sTargetDir; CString g_sTemplateFile; CString g_sAppManifestURL; CString g_sPollingInterval; CString g_sSubscriptionManifestDir; CString g_sAppManifestFile;
CString g_sAppBase;
BOOL g_bFailOnWarnings=TRUE; BOOL g_bLookInGACForDependencies; BOOL g_bCopyDependentSystemAssemblies;
class __declspec(uuid("f6d90f11-9c73-11d3-b32e-00c04f990bb4")) private_MSXML_DOMDocument30;
typedef HRESULT(*PFNGETCORSYSTEMDIRECTORY)(LPWSTR, DWORD, LPDWORD); typedef HRESULT (__stdcall *PFNCREATEASSEMBLYCACHE) (IAssemblyCache **ppAsmCache, DWORD dwReserved);
#define WZ_MSCOREE_DLL_NAME L"mscoree.dll"
#define GETCORSYSTEMDIRECTORY_FN_NAME "GetCORSystemDirectory"
#define CREATEASSEMBLYCACHE_FN_NAME "CreateAssemblyCache"
#define WZ_FUSION_DLL_NAME L"Fusion.dll"
// ---------------------------------------------------------------------------
// CreateFusionAssemblyCache
// ---------------------------------------------------------------------------
HRESULT CreateFusionAssemblyCache(IAssemblyCache **ppFusionAsmCache) { HRESULT hr = S_OK; HMODULE hEEShim = NULL; HMODULE hFusion = NULL; WCHAR szFusionPath[MAX_PATH]; DWORD ccPath = MAX_PATH;
PFNGETCORSYSTEMDIRECTORY pfnGetCorSystemDirectory = NULL; PFNCREATEASSEMBLYCACHE pfnCreateAssemblyCache = NULL;
// Find out where the current version of URT is installed
hEEShim = LoadLibrary(WZ_MSCOREE_DLL_NAME); if(!hEEShim) { hr = E_FAIL; goto exit; } pfnGetCorSystemDirectory = (PFNGETCORSYSTEMDIRECTORY) GetProcAddress(hEEShim, GETCORSYSTEMDIRECTORY_FN_NAME);
if((!pfnGetCorSystemDirectory)) { hr = E_FAIL; goto exit; }
// Get cor path.
if (FAILED(hr = (pfnGetCorSystemDirectory(szFusionPath, MAX_PATH, &ccPath)))) goto exit;
// Form path to fusion.
lstrcatW(szFusionPath, WZ_FUSION_DLL_NAME); hFusion = LoadLibrary(szFusionPath); if(!hFusion) { hr = E_FAIL; goto exit; }
// Get method ptr.
pfnCreateAssemblyCache = (PFNCREATEASSEMBLYCACHE) GetProcAddress(hFusion, CREATEASSEMBLYCACHE_FN_NAME);
if((!pfnCreateAssemblyCache)) { hr = E_FAIL; goto exit; }
// Create the fusion cache interface.
if (FAILED(hr = (pfnCreateAssemblyCache(ppFusionAsmCache, 0)))) goto exit;
hr = S_OK; exit: return hr; }
/////////////////////////////////////////////////////////////////////////
// PathNormalize
// Creates absolute path from relative, using current directory of mg.exe or parent process.
/////////////////////////////////////////////////////////////////////////
HRESULT PathNormalize(LPWSTR pwzPath, LPWSTR *ppwzAbsolutePath, DWORD dwFlag, BOOL bExists) { HRESULT hr = S_OK; WCHAR pwzTempDir[MAX_PATH], pwzAbsolutePath[MAX_PATH]; DWORD ccDir = MAX_PATH;
*ppwzAbsolutePath = NULL; //If path is relative, prepend the current directory
if (PathIsRelative(pwzPath)) { GetCurrentDirectory(ccDir, pwzTempDir); StrCat(pwzTempDir, L"\\"); StrCat(pwzTempDir, pwzPath); } else StrCpy(pwzTempDir, pwzPath);
if (!PathCanonicalize(pwzAbsolutePath, pwzTempDir)) { printf("Dir \"%ws\" canonicalize error\n", pwzTempDir); hr = E_FAIL; goto exit; }
//If path is supposed to be a diesctory, append a trailing slash if not already there
ccDir = lstrlen(pwzAbsolutePath); if (dwFlag == DIRECTORY_PATH && pwzAbsolutePath[ccDir -1] != L'\\') { pwzAbsolutePath[ccDir] = L'\\'; pwzAbsolutePath[ccDir +1] = L'\0'; }
//Make sure the direcotry exists
if (dwFlag == DIRECTORY_PATH && !bExists) { if(!PathIsDirectory(pwzAbsolutePath)) { printf("Dir \"%ws\" is not a valid directory\n", pwzPath); hr = E_FAIL; goto exit; } } //Make sure the file exists
else if (dwFlag == FILE_PATH) { if(!bExists) { if(!PathFileExists(pwzAbsolutePath)) { printf("File \"%ws\" does not exist\n", pwzPath); hr = E_FAIL; goto exit; } } if(PathIsDirectory(pwzAbsolutePath)) { printf("File \"%ws\" is a directory\n", pwzPath); hr = E_FAIL; goto exit; } } (*ppwzAbsolutePath) = WSTRDupDynamic(pwzAbsolutePath);
exit: return hr; }
/////////////////////////////////////////////////////////////////////////
// IsUniqueManifest
/////////////////////////////////////////////////////////////////////////
HRESULT IsUniqueManifest(List<ManifestNode *> *pSeenAssemblyList, ManifestNode *pManifestNode) { HRESULT hr = S_OK; ManifestNode *pCurrentNode=NULL; LISTNODE pos;
//cycle through list of unique manifests seen so far
//if new manifest is not found, add it to the list
pos = pSeenAssemblyList->GetHeadPosition(); while (pos) { if (pCurrentNode = pSeenAssemblyList->GetNext(pos)) { //Not Unique, go return
if ((hr =pCurrentNode->IsEqual(pManifestNode)) == S_OK) { hr= S_FALSE; goto exit; } } }
//No match, AsmId is unique, add it to the list
//Dont release pAsmId since list doesnt ref count
hr = S_OK; exit: return hr;
}
/////////////////////////////////////////////////////////////////////////
// DequeueItem
/////////////////////////////////////////////////////////////////////////
HRESULT DequeueItem(List<ManifestNode*> *pList, ManifestNode** ppManifestNode) { HRESULT hr = S_OK; LISTNODE pos = NULL;
(*ppManifestNode) = NULL;
pos = pList->GetHeadPosition(); if (!pos) { hr = S_FALSE; goto exit; }
(*ppManifestNode) = pList->GetAt(pos); pList->RemoveAt(pos);
exit: return hr; }
/////////////////////////////////////////////////////////////////////////
// ProbeForAssemblyInPath
/////////////////////////////////////////////////////////////////////////
HRESULT ProbeForAssemblyInPath(CString &sDeployDir, IAssemblyIdentity *pName, ManifestNode **ppManifestNode) //LPWSTR *ppwzFilePath, DWORD *pdwType)
{ HRESULT hr = S_OK;
DWORD cbBuf = 0, ccBuf =0 ; LPWSTR pwzBuf = NULL;
CString sName, sLocale, sPublicKeyToken, sCLRDisplayName, sRelativeAssemblyPath; CString sProbingPaths[6]; IAssemblyIdentity *pAssemblyId= NULL; IAssemblyManifestImport *pManImport=NULL;
// first try to find assembly by probing
if(FAILED(hr = pName->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &cbBuf))) goto exit; sName.TakeOwnership(pwzBuf);
if(FAILED(hr = pName->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE, &pwzBuf, &cbBuf))) goto exit; sLocale.TakeOwnership(pwzBuf);
if(FAILED(hr = pName->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzBuf, &ccBuf) && hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND))) goto exit; else if(hr == S_OK) sPublicKeyToken.TakeOwnership(pwzBuf);
//bugbug - Hack to supress warning messages for not being able to find mscorlib
if(sPublicKeyToken._pwz && !StrCmpI(sPublicKeyToken._pwz, L"b77a5c561934e089") && !StrCmpI(sName._pwz, L"mscorlib")) { hr = S_FALSE; goto exit; } //Set up the six different probing locations
// 1: appBase\AssemblyName.dll
// 2: appBase\AssemblyName.exe
// 3: appBase\AssemblyName\AssemblyName.dll
// 4: appBase\AssemblyName\AssemblyName.exe
// 5: appBase\local\AssemblyName\AssemblyName.dll
// 6: appBase\local\AssemblyName\AssemblyName.exe
sProbingPaths[0].Assign(sDeployDir); sProbingPaths[0].Append(sName); sProbingPaths[1].Assign(sProbingPaths[0]);
sProbingPaths[0].Append(L".dll"); sProbingPaths[1].Append(L".exe");
sProbingPaths[2].Assign(sDeployDir); sProbingPaths[2].Append(sName); sProbingPaths[2].Append(L"\\"); sProbingPaths[2].Append(sName); sProbingPaths[3].Assign(sProbingPaths[2]);
sProbingPaths[2].Append(L".dll"); sProbingPaths[3].Append(L".exe");
sProbingPaths[4].Assign(sDeployDir); sProbingPaths[4].Append(sLocale); sProbingPaths[4].Append(L"\\"); sProbingPaths[4].Append(sName); sProbingPaths[4].Append(L"\\"); sProbingPaths[4].Append(sName); sProbingPaths[5].Assign(sProbingPaths[4]);
sProbingPaths[4].Append(L".dll"); sProbingPaths[5].Append(L".exe");
for (int i = 0; i < 6; i++) { //Check first to see if the file exists
if (GetFileAttributes(sProbingPaths[i]._pwz) != -1) { hr = CreateAssemblyManifestImport(&pManImport, sProbingPaths[i]._pwz, NULL, 0); if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)) goto exit;
if(hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT) || (hr = pManImport->GetAssemblyIdentity(&pAssemblyId)) != S_OK) { SAFERELEASE(pManImport); continue; }
//bugbug - need to make IsEqual function more robust
//sanity check to make sure the assemblies are the same
if (pName->IsEqual(pAssemblyId) != S_OK) { SAFERELEASE(pAssemblyId); SAFERELEASE(pManImport); continue; }
// Match found
(*ppManifestNode) = new ManifestNode(pManImport, sDeployDir._pwz, sProbingPaths[i]._pwz + sDeployDir._cc - 1, PRIVATE_ASSEMBLY);
SAFERELEASE(pAssemblyId); SAFERELEASE(pManImport); hr = S_OK; goto exit; } }
// assembly not found in this dir.
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
exit: return hr;
}
/////////////////////////////////////////////////////////////////////////
// ProbeForAssemblyInGAC
/////////////////////////////////////////////////////////////////////////
HRESULT ProbeForAssemblyInGAC(IAssemblyIdentity *pName, ManifestNode **ppManifestNode) //LPWSTR *ppwzFilePath, DWORD *pdwType)
{ HRESULT hr = S_OK;
DWORD cbBuf = 0, ccBuf =0 ; LPWSTR pwzBuf = NULL; IAssemblyManifestImport *pManImport=NULL;
CString sCLRDisplayName;
WCHAR pwzPath[MAX_PATH]; ASSEMBLY_INFO asmInfo; IAssemblyCache *pAsmCache = NULL;
memset(&asmInfo, 0, sizeof(asmInfo)); asmInfo.pszCurrentAssemblyPathBuf = pwzPath; asmInfo.cchBuf = MAX_PATH;
if (FAILED(hr = CreateFusionAssemblyCache(&pAsmCache))) goto exit; if(FAILED(hr = pName->GetCLRDisplayName(NULL, &pwzBuf, &ccBuf))) goto exit; sCLRDisplayName.TakeOwnership(pwzBuf, ccBuf);
if ((hr = pAsmCache->QueryAssemblyInfo(0, sCLRDisplayName._pwz, &asmInfo)) == S_OK) { // Assembly found in GAC
if ((hr = CreateAssemblyManifestImport(&pManImport, asmInfo.pszCurrentAssemblyPathBuf, NULL, 0)) != S_OK) goto exit;
(*ppManifestNode) = new ManifestNode(pManImport, NULL, asmInfo.pszCurrentAssemblyPathBuf, GAC_ASSEMBLY); goto exit; }
exit: SAFERELEASE(pAsmCache); return hr;
}
/////////////////////////////////////////////////////////////////////////
// ProbeForAssembly
/////////////////////////////////////////////////////////////////////////
HRESULT ProbeForAssembly(IAssemblyIdentity *pName, ManifestNode **ppManifestNode) //LPWSTR *ppwzFilePath, DWORD *pdwType)
{ HRESULT hr = S_OK; DWORD dwDirCount=0;
*ppManifestNode = NULL;
while(dwDirCount < g_dwDeployDirs) { if(SUCCEEDED(hr = ProbeForAssemblyInPath( g_sDeployDirs[dwDirCount], pName, ppManifestNode))) goto exit;
dwDirCount++; }
if( (IsKnownAssembly(pName, KNOWN_SYSTEM_ASSEMBLY) == S_OK) && (!g_bCopyDependentSystemAssemblies) ) { hr = S_FALSE; // ignore system dependencies
goto exit; }
if( g_bLookInGACForDependencies ) { //Can't find assembly by probing
//Try to find the assembly in the GAC.
if(SUCCEEDED(hr = ProbeForAssemblyInGAC(pName, ppManifestNode))) goto exit; }
// assembly not found
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
exit: return hr; }
/////////////////////////////////////////////////////////////////////////
// FindAssemblies
// note: Assumes that pwzDir has a trailing slash.
/////////////////////////////////////////////////////////////////////////
HRESULT FindAllAssemblies (LPWSTR pwzDir, List<ManifestNode *> *pManifestList) { HRESULT hr = S_OK; HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA fdFile; IAssemblyIdentity *pTempAsmId=NULL; IAssemblyManifestImport *pManifestImport = NULL; ManifestNode *pManifestNode = NULL; CString sSearchString; DWORD dwLastError = 0; // set up search string to find all files in the passed in directory
sSearchString.Assign(pwzDir); sSearchString.Append(L"*");
if (sSearchString._cc > MAX_PATH) { hr = CO_E_PATHTOOLONG; printf("Error: Search path too long\n"); goto exit; }
hFind = FindFirstFile(sSearchString._pwz, &fdFile); if (hFind == INVALID_HANDLE_VALUE) { // BUGBUG - getlasterror() ?
hr = E_FAIL; printf("Find file error\n"); goto exit; }
//enumerate through all the files in the directory,
// and recursivly call FindAllAssemblies on any directories encountered
while(TRUE) { if (StrCmp(fdFile.cFileName, L".") != 0 && StrCmp(fdFile.cFileName, L"..") != 0) { CString sFilePath;
//create absolute file name by appending the filename to the dir name
sFilePath.Assign(pwzDir); sFilePath.Append(fdFile.cFileName);
if (sSearchString._cc > MAX_PATH) { hr = CO_E_PATHTOOLONG; printf("Error: File path too long\n"); goto exit; }
//If the file is a directory, recursivly call FindAllAssemblies
if ((fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { sFilePath.Append(L"\\"); if (FAILED(hr = FindAllAssemblies(sFilePath._pwz, pManifestList))) goto exit; } // If a file, check to see if it is a Assembly, if it is, add it to our master list
else { if((hr = CreateAssemblyManifestImport(&pManifestImport, sFilePath._pwz, NULL, 0)) == S_OK) { // check to make sure file we just opened wasnt just an XML file
if ((hr =pManifestImport->GetAssemblyIdentity(&pTempAsmId)) == S_OK) { // List does not AddRef, so dont release pManifestImport and refcount will stay at one
// Clean up after list is no longer needed.
pManifestNode = new ManifestNode(pManifestImport, g_sAppBase._pwz, sFilePath._pwz+g_sAppBase._cc-1, PRIVATE_ASSEMBLY); pManifestList->AddTail(pManifestNode); SAFERELEASE(pTempAsmId); } else if (FAILED(hr)) goto exit;
SAFERELEASE(pManifestImport); } } } if (!FindNextFile(hFind, &fdFile)) { dwLastError = GetLastError(); break; } }
if(dwLastError == ERROR_NO_MORE_FILES) hr = S_OK; else hr = HRESULT_FROM_WIN32(dwLastError); exit: return hr; }
/////////////////////////////////////////////////////////////////////////
// TraverseManifestDependencyTree
/////////////////////////////////////////////////////////////////////////
HRESULT TraverseManifestDependencyTrees(List<ManifestNode *> *pManifestList, List<LPWSTR> *pAssemblyFileList, List<ManifestNode *> *pUniqueAssemblyList, BOOL bListMode) { HRESULT hr = S_OK; IAssemblyManifestImport *pDepManifestImport=NULL; IManifestInfo *pDepAsmInfo=NULL, *pFileInfo=NULL; IAssemblyIdentity *pAsmId=NULL; ManifestNode *pManifestNode=NULL, *pDepManifestNode = NULL; LPWSTR pwz = NULL; DWORD index = 0, cb = 0, cc = 0, dwFlag = 0, dwHash=0, dwType=0; CString sFileName, sRelativeFilePath, sAbsoluteFilePath, sBuffer, sManifestName;
while((hr = DequeueItem(pManifestList, &pManifestNode)) == S_OK) { // If Assembly has already been parsed, no need doing it again, skip to the next assembly
if ((hr = IsUniqueManifest(pUniqueAssemblyList, pManifestNode)) != S_OK) { SAFEDELETE(pManifestNode); continue; } pUniqueAssemblyList->AddTail(pManifestNode);
pManifestNode->GetManifestFilePath(&pwz); sManifestName.TakeOwnership(pwz);
//If the manifest was found by probing, add its name to the list of files
hr =pManifestNode->GetManifestType(&dwType); if (dwType == PRIVATE_ASSEMBLY) {
dwHash = HashString(sManifestName._pwz, HASHTABLE_SIZE, false); pAssemblyFileList[dwHash].AddTail(WSTRDupDynamic(sManifestName._pwz));
//need the relative dir path of the manifest rwt the app base for future use
sRelativeFilePath.Assign(sManifestName);
sRelativeFilePath.RemoveLastElement(); if(sRelativeFilePath.CharCount() > 1) // add a backslash only if string has any non-null chars. i.e. stringLength is non-zero; note here _cc holds 1(null-char).
sRelativeFilePath.Append(L"\\"); }
if(bListMode) fprintf(stderr, "\nAssembly %ws:\n", sManifestName._pwz); //Add all dependant assemblies to the queue to be later traversed
while ((hr = pManifestNode->GetNextAssembly(index++, &pDepAsmInfo)) == S_OK) { if(FAILED(hr = pDepAsmInfo->Get(MAN_INFO_DEPENDENT_ASM_ID, (LPVOID *)&pAsmId, &cb, &dwFlag))) goto exit;
pAsmId->GetDisplayName(ASMID_DISPLAYNAME_NOMANGLING, &pwz, &cc); //Try to find the assembly by first probing, then by checking in the GAC.
if(FAILED(hr = ProbeForAssembly(pAsmId, &pDepManifestNode))) { //Assembly not found, display warning message
//Bugbug, should mg still spit out a manifest knowing that things are missing?
fprintf(stderr, "WRN: Unable to find dependency %ws. in manifest %ws\n", pwz, sManifestName._pwz); if(g_bFailOnWarnings) { fprintf(stderr, "Warning treated as error. mg exiting....\n"); hr = E_FAIL; goto exit; } SAFERELEASE(pAsmId); continue; } else if (hr == S_OK) { //Dont release since no add refing in the list is taking place
if ((hr = IsUniqueManifest(pUniqueAssemblyList, pDepManifestNode)) == S_OK) pManifestList->AddTail(pDepManifestNode);
SAFERELEASE(pAsmId);
if(bListMode) fprintf(stderr, "\tDependant Assembly: %ws\n", pwz); } SAFERELEASE(pDepAsmInfo); }
// Add all files to hash table
index = 0; pManifestNode->GetManifestType(&dwType); while (dwType == PRIVATE_ASSEMBLY && pManifestNode->GetNextFile(index++, &pFileInfo) == S_OK) { LPWSTR pwzFileName = NULL; if(FAILED(pFileInfo->Get(MAN_INFO_ASM_FILE_NAME, (LPVOID *)&pwz, &cb, &dwFlag))) goto exit;
sBuffer.TakeOwnership(pwz); sFileName.Assign(sRelativeFilePath); sFileName.Append(sBuffer); sAbsoluteFilePath.Assign(g_sAppBase); sAbsoluteFilePath.Append(sFileName); sFileName.ReleaseOwnership(&pwzFileName); dwHash = HashString(pwzFileName, HASHTABLE_SIZE, false); pAssemblyFileList[dwHash].AddTail(pwzFileName);
//If file is listed as part of an assembly, but cannot be found, display a warning.
//Bugbug, should mg still spit out a manifest knowing that things are missing?
if(!PathFileExists(sAbsoluteFilePath._pwz)) printf("Warning: File \"%ws\" does not exist and is called out in \"%ws\"\n",sAbsoluteFilePath._pwz, sManifestName._pwz);
if(bListMode) fprintf(stderr, "\tDependant File: %ws\n", pwzFileName);
//Release ownership since string is now part of hash table and hash table does not ref count
// sFileName.ReleaseOwnership();
} }
hr = S_OK;
exit: return hr; }
/////////////////////////////////////////////////////////////////////////
// CrossReferenceFiles
/////////////////////////////////////////////////////////////////////////
HRESULT CrossReferenceFiles(LPWSTR pwzDir, List<LPWSTR> *pAssemblyFileList, List<LPWSTR> *pRawFiles) { HRESULT hr = S_OK; HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA fdFile; DWORD dwHash = 0; LISTNODE pos; LPWSTR pwzBuf=NULL; bool bRawFile = FALSE; DWORD dwLastError = 0;
CString sSearchString;
// set up search string to find all files in the passed in directory
sSearchString.Assign(pwzDir); sSearchString.Append(L"*");
if (sSearchString._cc > MAX_PATH) { hr = CO_E_PATHTOOLONG; printf("Error: Search path too long\n"); goto exit; }
hFind = FindFirstFile(sSearchString._pwz, &fdFile); if (hFind == INVALID_HANDLE_VALUE) { hr = E_FAIL; printf("Find file error\n"); goto exit; }
//enumerate through all the files in the directory,
// and recursivly call FindAllAssemblies on any directories encountered
while(TRUE) { if (StrCmp(fdFile.cFileName, L".") != 0 && StrCmp(fdFile.cFileName, L"..") != 0) { CString sFilePath;
//create absolute file name by appending the filename to the dir name
sFilePath.Assign(pwzDir); sFilePath.Append(fdFile.cFileName);
if (sSearchString._cc > MAX_PATH) { hr = CO_E_PATHTOOLONG; printf("Error: Search path too long\n"); goto exit; } //if file is actually a direcoty, recrusivly call crossRefernceFiles on the Directory
if ((fdFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { sFilePath.Append(L"\\"); if (FAILED(hr = CrossReferenceFiles(sFilePath._pwz, pAssemblyFileList, pRawFiles))) goto exit; } else { //Check to see if the file is in the hash table.
//If it isnt, then we know it is not called out from any assembly
//add it to the Raw file list
bRawFile = TRUE; dwHash = HashString(sFilePath._pwz+g_sAppBase._cc - 1, HASHTABLE_SIZE, false);
pos = pAssemblyFileList[dwHash].GetHeadPosition(); while (pos) { pwzBuf = pAssemblyFileList[dwHash].GetNext(pos); if (!StrCmpI(pwzBuf, sFilePath._pwz+g_sAppBase._cc - 1)) { bRawFile = FALSE; break; } }
if (bRawFile) { pwzBuf = WSTRDupDynamic(sFilePath._pwz+g_sAppBase._cc - 1); pRawFiles->AddTail(pwzBuf); } } }
// BUGBUG - do fnf, check error.
if (!FindNextFile(hFind, &fdFile)) { dwLastError = GetLastError(); break; } }
if(dwLastError == ERROR_NO_MORE_FILES) hr = S_OK; else hr = HRESULT_FROM_WIN32(dwLastError);
exit: return hr; }
/////////////////////////////////////////////////////////////////////////
// CopyRawFile
/////////////////////////////////////////////////////////////////////////
HRESULT CopyRawFile(LPWSTR pwzFilePath) { HRESULT hr = S_OK; CString sDest; CString sSrc;
sDest.Assign(g_sTargetDir); sDest.Append(pwzFilePath); // this should be relative path ...
if(FAILED(hr = CreateDirectoryHierarchy(sDest._pwz, NULL))) goto exit;
sSrc.Assign(g_sAppBase); sSrc.Append(pwzFilePath);
printf(" Copying RawFile from <%ws> TO <%ws> \n", sSrc._pwz, sDest._pwz);
if(!::CopyFile(sSrc._pwz, sDest._pwz, FALSE)) { hr = FusionpHresultFromLastError(); goto exit; }
exit:
return hr; }
/////////////////////////////////////////////////////////////////////////
// CopyAssemblyBits
/////////////////////////////////////////////////////////////////////////
HRESULT CopyAssemblyBits(CString &sSrcDir, CString &sDestDir, ManifestNode *pManifestNode) { HRESULT hr = S_OK; DWORD nIndex=0; DWORD dwFlag; DWORD cbBuf; LPWSTR pwzBuf=NULL; IManifestInfo *pFileInfo = NULL;
if(FAILED(hr = CreateDirectoryHierarchy(sDestDir._pwz, NULL))) goto exit;
if(!::CopyFile(sSrcDir._pwz, sDestDir._pwz, FALSE)) { hr = FusionpHresultFromLastError(); goto exit; }
//copy all file dependecies of the assembly as well
nIndex = 0;
while (pManifestNode->GetNextFile(nIndex++, &pFileInfo) == S_OK) { if(FAILED(pFileInfo->Get(MAN_INFO_ASM_FILE_NAME, (LPVOID *)&pwzBuf, &cbBuf, &dwFlag))) goto exit; // sRelativeFilePath.TakeOwnership(pwzBuf, ccBuf);
sSrcDir.RemoveLastElement(); sSrcDir.Append(L"\\"); sSrcDir.Append(pwzBuf);
sDestDir.RemoveLastElement(); sDestDir.Append(L"\\"); sDestDir.Append(pwzBuf);
// CreateDirectoryHierarchy(sPrivateAssemblyDir._pwz, sRelativeFilePath._pwz);
if(!::CopyFile(sSrcDir._pwz, sDestDir._pwz, FALSE)) { hr = FusionpHresultFromLastError(); goto exit; }
SAFEDELETEARRAY(pwzBuf); SAFERELEASE(pFileInfo); }
exit :
SAFEDELETEARRAY(pwzBuf); SAFERELEASE(pFileInfo);
return hr; }
/////////////////////////////////////////////////////////////////////////
// CopyAssembly
/////////////////////////////////////////////////////////////////////////
HRESULT CopyAssembly(ManifestNode *pManifestNode) { HRESULT hr = S_OK; CString sDest; CString sSrc; LPWSTR pwzManifestFilePath = NULL; LPWSTR pwzSrcDir=NULL; LPWSTR pwzTemp = NULL; DWORD dwType; IAssemblyIdentity *pAssemblyId = NULL; CString sAssemblyName;
hr = pManifestNode->GetManifestFilePath(&pwzManifestFilePath);
hr = pManifestNode->GetManifestType(&dwType);
sDest.Assign(g_sTargetDir);
if (dwType == PRIVATE_ASSEMBLY) { sDest.Append(pwzManifestFilePath); // this should be relative path ...
if(FAILED(hr = pManifestNode->GetSrcRootDir(&pwzSrcDir))) goto exit; sSrc.Assign(pwzSrcDir); sSrc.Append(pwzManifestFilePath); } else if (dwType == GAC_ASSEMBLY) { LPWSTR pwzBuf = NULL; DWORD ccBuf = 0;
pManifestNode->GetAssemblyIdentity(&pAssemblyId);
if(FAILED(hr = pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &ccBuf))) goto exit;
if(!(pwzTemp = PathFindFileName(pwzManifestFilePath))) { hr = E_FAIL; goto exit; }
sAssemblyName.TakeOwnership(pwzBuf);
sAssemblyName.Append(L"\\"); sAssemblyName.Append(pwzTemp); // manifest file name of the GAC assembly.
sDest.Append(sAssemblyName); sSrc.Assign(pwzManifestFilePath); }
printf(" Copying Assembly Man from <%ws> TO <%ws> \n", sSrc._pwz, sDest._pwz); hr = CopyAssemblyBits(sSrc, sDest, pManifestNode);
if (dwType == GAC_ASSEMBLY) { // set the install codebase of the assembly copied from GAC
// to that of its relative path in target dir. This will be written to manifest ??
hr = pManifestNode->SetManifestFilePath(sAssemblyName._pwz); }
exit:
SAFEDELETEARRAY(pwzSrcDir); SAFEDELETEARRAY(pwzManifestFilePath); SAFERELEASE(pAssemblyId); return hr; }
/////////////////////////////////////////////////////////////////////////
// CopyFilesToTargetDir
/////////////////////////////////////////////////////////////////////////
HRESULT CopyFilesToTargetDir(List<ManifestNode*> *pUniqueManifestList, List<LPWSTR> *pRawFiles) { HRESULT hr = S_OK; ManifestNode *pManifestNode = NULL; LISTNODE pos; LPWSTR pwzBuf;
//Cycle through all of the unique manifests
pos = pUniqueManifestList->GetHeadPosition(); while (pos) { pManifestNode = pUniqueManifestList->GetNext(pos);
//if the manifest was found by probing initially, then it is already in the Appbase's directory
//continue to the next manifest
//if the manifest was found in the GAC and is not a system assembly, copy the
//assembly into the Appbase
if(FAILED(hr = CopyAssembly(pManifestNode))) goto exit; }
//Copy RawFiles to Target Dir
pos = pRawFiles->GetHeadPosition(); while (pos) { pwzBuf = pRawFiles->GetNext(pos); if(FAILED(hr = CopyRawFile(pwzBuf))) goto exit; }
exit: return hr; }
/////////////////////////////////////////////////////////////////////////
// PrivatizeAssemblies
/////////////////////////////////////////////////////////////////////////
HRESULT PrivatizeAssemblies(List<ManifestNode*> *pUniqueManifestList) { HRESULT hr = S_OK; ManifestNode *pManifestNode = NULL; LISTNODE pos; LPWSTR pwzBuf =NULL; DWORD dwType = 0, ccBuf = 0, cbBuf = 0, dwFlag = 0, nIndex = 0; IAssemblyIdentity *pAssemblyId = NULL; IManifestInfo *pFileInfo = NULL; WCHAR pwzPath[MAX_PATH]; ASSEMBLY_INFO asmInfo; IAssemblyCache *pAsmCache = NULL;
CString sPublicKeyToken, sCLRDisplayName; CString sAssemblyName, sAssemblyManifestFileName; CString sPrivateAssemblyPath, sPrivateAssemblyDir; CString sAssemblyGACPath, sAssemblyGACDir; CString sRelativeFilePath, sFileGACPath, sFilePrivatePath; CString sBuffer;
memset(&asmInfo, 0, sizeof(asmInfo)); asmInfo.pszCurrentAssemblyPathBuf = pwzPath; asmInfo.cchBuf = MAX_PATH;
if (FAILED(hr = CreateFusionAssemblyCache(&pAsmCache))) goto exit;
//Cycle through all of the unique manifests
pos = pUniqueManifestList->GetHeadPosition(); while (pos) { pManifestNode = pUniqueManifestList->GetNext(pos); hr = pManifestNode->GetManifestType(&dwType);
//if the manifest was found by probing initially, then it is already in the Appbase's directory
//continue to the next manifest
//if the manifest was found in the GAC and is not a system assembly, copy the
//assembly into the Appbase
if (dwType == PRIVATE_ASSEMBLY) continue; else if (dwType == GAC_ASSEMBLY) { pManifestNode->GetAssemblyIdentity(&pAssemblyId);
hr = pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN, &pwzBuf, &ccBuf); sPublicKeyToken.TakeOwnership(pwzBuf);
//if the assembly is a system assembly, skip to next manifest
if (!StrCmpI(sPublicKeyToken._pwz, L"b77a5c561934e089") || !StrCmpI(sPublicKeyToken._pwz, L"b03f5f7f11d50a3a")) { SAFERELEASE(pAssemblyId); continue; }
//get the assemblies dir by making a call into CreateAssemblyCache
if(FAILED(hr = pAssemblyId->GetCLRDisplayName(NULL, &pwzBuf, &ccBuf))) goto exit; sCLRDisplayName.TakeOwnership(pwzBuf, ccBuf);
if ((hr = pAsmCache->QueryAssemblyInfo(0, sCLRDisplayName._pwz, &asmInfo)) != S_OK) goto exit;
sAssemblyGACPath.Assign(asmInfo.pszCurrentAssemblyPathBuf); sAssemblyGACPath.LastElement(sAssemblyManifestFileName);
sAssemblyGACDir.Assign(sAssemblyGACPath); sAssemblyGACDir.RemoveLastElement();
hr = pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &ccBuf); sAssemblyName.TakeOwnership(pwzBuf);
//set up the new directory to store the assembly in
// g_sAppBase\assemblyname\,
sPrivateAssemblyDir.Assign(g_sAppBase); sPrivateAssemblyDir.Append(sAssemblyName); sPrivateAssemblyDir.Append(L"\\"); CreateDirectoryHierarchy(sPrivateAssemblyDir._pwz, sAssemblyManifestFileName._pwz);
sPrivateAssemblyPath.Assign(sPrivateAssemblyDir); sPrivateAssemblyPath.Append(sAssemblyManifestFileName); ::CopyFile(sAssemblyGACPath._pwz, sPrivateAssemblyPath._pwz, FALSE);
//copy all file dependecies of the assembly as well
nIndex = 0; while (pManifestNode->GetNextFile(nIndex++, &pFileInfo) == S_OK) { if(FAILED(pFileInfo->Get(MAN_INFO_ASM_FILE_NAME, (LPVOID *)&pwzBuf, &cbBuf, &dwFlag))) goto exit; sRelativeFilePath.TakeOwnership(pwzBuf, ccBuf);
sFileGACPath.Assign(sAssemblyGACDir); sFileGACPath.Append(sRelativeFilePath);
sFilePrivatePath.Assign(sPrivateAssemblyDir); sFilePrivatePath.Append(sRelativeFilePath);
CreateDirectoryHierarchy(sPrivateAssemblyDir._pwz, sRelativeFilePath._pwz); ::CopyFile(sFileGACPath._pwz, sFilePrivatePath._pwz, FALSE); }
//update the manifestnode's FileName field with the new relative path wrt the Appbase
pManifestNode->SetManifestFilePath(sPrivateAssemblyPath._pwz + g_sAppBase._cc - 1); pManifestNode->SetManifestType(PRIVATE_ASSEMBLY);
SAFERELEASE(pAssemblyId); } }
exit:
SAFERELEASE(pAsmCache); return hr; }
/////////////////////////////////////////////////////////////////////////
//GetInitialDependencies
/////////////////////////////////////////////////////////////////////////
//Bugbug, Big Avalon Hack
HRESULT GetInitialDependencies(LPWSTR pwzTemplatePath, List<ManifestNode *> *pManifestList) { HRESULT hr = S_OK; IXMLDOMDocument2 *pXMLDoc = NULL; IXMLDOMNode *pRootNode = NULL, *pSearchNode = NULL; BSTR bstrSearchString=NULL; ManifestNode *pManifestNode = NULL;
WCHAR pwzPath[MAX_PATH]; ASSEMBLY_INFO asmInfo; IAssemblyCache *pAsmCache = NULL; IAssemblyManifestImport *pManImport = NULL;
if(FAILED(hr = LoadXMLDocument(pwzTemplatePath, &pXMLDoc))) goto exit;
if(FAILED(hr = pXMLDoc->get_firstChild(&pRootNode))) goto exit;
bstrSearchString = ::SysAllocString(L"//shellState[@entryImageType=\"avalon\"]"); if (!bstrSearchString) { hr = E_OUTOFMEMORY; goto exit; } if (FAILED(hr = pRootNode->selectSingleNode(bstrSearchString, &pSearchNode))) { hr = S_FALSE; goto exit; }
if (pSearchNode) { // Try to find the assembly in the GAC.
memset(&asmInfo, 0, sizeof(asmInfo)); asmInfo.pszCurrentAssemblyPathBuf = pwzPath; asmInfo.cchBuf = MAX_PATH;
if (FAILED(hr = CreateFusionAssemblyCache(&pAsmCache))) goto exit;
if ((hr = pAsmCache->QueryAssemblyInfo(0, L"Avalon.Application", &asmInfo)) == S_OK) { if ((hr = CreateAssemblyManifestImport(&pManImport, asmInfo.pszCurrentAssemblyPathBuf, NULL, 0)) != S_OK) goto exit; pManifestNode = new ManifestNode(pManImport, NULL, asmInfo.pszCurrentAssemblyPathBuf, GAC_ASSEMBLY); pManifestList->AddTail(pManifestNode); } else { hr = S_FALSE; fprintf(stderr, "Warning: Cannot find Avalon Runtime in GAC\n"); } } exit: if (bstrSearchString) ::SysFreeString(bstrSearchString); SAFERELEASE(pSearchNode); SAFERELEASE(pRootNode); SAFERELEASE(pXMLDoc); SAFERELEASE(pManImport); SAFERELEASE(pAsmCache);
return hr; }
/////////////////////////////////////////////////////////////////////////
// CreateSubscriptionManifest
/////////////////////////////////////////////////////////////////////////
HRESULT CreateSubscriptionManifest(LPWSTR pwzApplicationManifestPath, LPWSTR pwzSubscriptionManifestPath, LPWSTR pwzURL, LPWSTR pwzPollingInterval) { HRESULT hr = S_OK; IAssemblyManifestImport *pManImport = NULL; IAssemblyIdentity *pAppAssemblyId = NULL; CString sSubAssemblyName, sSubcriptionFilePath; LPWSTR pwzBuf = NULL; DWORD ccBuf = NULL;
//createmanifest on the input file
if(FAILED(hr = CreateAssemblyManifestImport(&pManImport, pwzApplicationManifestPath, NULL, 0))) goto exit;
if((hr = pManImport->GetAssemblyIdentity(&pAppAssemblyId)) != S_OK) { hr = E_FAIL; goto exit; }
//grab the name of the assembly
//appended with ".subscription", this will be the subscription manifest name
if(FAILED(hr = pAppAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME, &pwzBuf, &ccBuf))) goto exit; sSubAssemblyName.TakeOwnership(pwzBuf, ccBuf); sSubAssemblyName.Append(L".subscription");
sSubcriptionFilePath.Assign(pwzSubscriptionManifestPath); sSubcriptionFilePath.Append(sSubAssemblyName);
if(FAILED(hr = CreateDirectoryHierarchy(sSubcriptionFilePath._pwz, NULL))) goto exit; if(FAILED(hr = CreateXMLSubscriptionManifest(sSubcriptionFilePath._pwz, pAppAssemblyId, pwzURL, pwzPollingInterval))) goto exit;
exit: SAFERELEASE(pManImport); SAFERELEASE(pAppAssemblyId); return hr; }
/////////////////////////////////////////////////////////////////////////
// PrintDependencies
/////////////////////////////////////////////////////////////////////////
HRESULT PrintDependencies(List <LPWSTR> *pRawFileList, List<ManifestNode *> *pUniqueManifestList) { HRESULT hr = S_OK; LPWSTR pwzBuf = NULL, pwz= NULL; DWORD dwType = 0; ManifestNode *pManifestNode = NULL; LISTNODE pos; pos = pRawFileList->GetHeadPosition(); while(pos) { pwzBuf = pRawFileList->GetNext(pos); fprintf(stderr, "Raw File : %ws\n", pwzBuf); }
pos = pUniqueManifestList->GetHeadPosition(); while(pos) { pManifestNode = pUniqueManifestList->GetNext(pos); pManifestNode->GetManifestFilePath(&pwzBuf); pManifestNode->GetManifestType(&dwType); if (dwType == PRIVATE_ASSEMBLY) fprintf(stderr, "Manifest : %ws\n", pwzBuf); else { pwz = StrRChr(pwzBuf, NULL, L'\\') + 1; fprintf(stderr, "GAC Manifest : %ws\n", pwz); } SAFEDELETEARRAY(pwzBuf); }
return hr; }
/////////////////////////////////////////////////////////////////////////
// UsageTopLevel
/////////////////////////////////////////////////////////////////////////
HRESULT UsageTopLevel() { printf("Manifest Generator Usage: \n" "mg -<mode> [<param_name>:<param_value> ... ]\n" "Modes supported in mg\n" "t: Generate Template File Mode\n" "l: List Mode\n" "d: List Dependency Mode\n" "s: Subscription Manifest Gereration Mode \n" "m: Manifest Generation Mode\n\n" "For help on a Mode, Use \"mg -<mode> help\" \n" "Valid <param_name>:<param_value> pairs \n" "sd:<source_directory_path> \n" "td:<target_dir> \n" "dd:<dependency_dir> \n" "tf:<template_file_path> \n" "smd:<subscription_dir> \n" "amf:<app_man_file> \n" "amu:<app_man_URL> \n" "si:<sync_interval> \n" "WRN:allow -- meaning allow warnings. Deafault is exit on warnings.\n" "GAC:follow -- meaning follow dependencies on GAC. Default is don't probe for dependencies in GAC\n" "SYS:copy -- copy dependent system assemblies from GAC to target dir\n" ); return S_OK; }
/////////////////////////////////////////////////////////////////////////
// UsageCmdTemplate
/////////////////////////////////////////////////////////////////////////
HRESULT UsageCmdTemplate() { printf("Usage: \n" "Template Mode:\n" "mg -t tf:<file_path>\n\n" "\t<file_path> = path where template manifest will be created.\n\n" ); return S_OK; }
/////////////////////////////////////////////////////////////////////////
// UsageCmdList
/////////////////////////////////////////////////////////////////////////
HRESULT UsageCmdList() { printf("Usage: \n" "List Mode:\n" "mg -l sd:<source_directory_path> [tf:<template_file_path>] [dd:<dependency_dir> \n\n" "\t[source_directory_path] = path of Application to chase dependencies\n" "\toptional: <template_file_path> = path of Template file\n" "\toptional : <dependency_dir> = user defined dependency dir where some dependencies could be found\n\n" ); return S_OK;
}
/////////////////////////////////////////////////////////////////////////
// UsageCmdDependencyList
/////////////////////////////////////////////////////////////////////////
HRESULT UsageCmdDependencyList() { printf("Usage: \n" "List Dependency Mode:\n" "mg -d sd:<source_directory_path> [dd:<dependency_dir> \n\n" "\t<source_directory path> = path of Application to chase dependencies\n\n" "\toptional : <dependency_dir> = user defined dependency dir where some dependencies could be found\n\n" ); return S_OK;
}
/////////////////////////////////////////////////////////////////////////
// UsageCmdSubscription
/////////////////////////////////////////////////////////////////////////
HRESULT UsageCmdSubscription() { printf("Usage: \n" "Subscription Manifest Gereration Mode:\n" "mg -s smd:<subscription_dir> amf:<app_man_file> amu:<app_man_URL> [si:<sync_interval>] \n\n" "\t<subscription_dir> = path where subscription manifest will be created\n" "\t<app_man_file> = path to the Application manifest you wish to generate a subscription for\n" "\t<app_man_URL] = URL of application manifest\n" "\toptional: <sync_interval] = syncronize interval in hours\n\n" ); return S_OK; }
/////////////////////////////////////////////////////////////////////////
// UsageCmdManifest
/////////////////////////////////////////////////////////////////////////
HRESULT UsageCmdManifest() { printf("Usage: \n" "Manifest Generation Mode:\n" "mg -m sd:<source_dir> td:<target_dir> tf:<template_file> [dd:<dependency_dir>]\n\n" "\t<source_dir> = path of the Application of which you want to generate a manifest for\n" "\t<target_dir> = path to which all app files and dependencies will be copied\n" "\t<template_file> = path of requried input Template file\n" "\toptional : <dependency_dir> = user defined dependency dir where some dependencies could be found\n\n" ); return S_OK; }
/////////////////////////////////////////////////////////////////////////
// UsageAll
/////////////////////////////////////////////////////////////////////////
HRESULT UsageAll() { // call all above functions
return S_OK; }
HRESULT UsageCommand(COMMAND_MODE CmdMode) { switch(CmdMode) { case CmdTemplate: UsageCmdTemplate(); break;
case CmdList: UsageCmdList(); break;
case CmdDependencyList: UsageCmdDependencyList(); break;
case CmdSubscription: UsageCmdSubscription(); break;
case CmdManifest: UsageCmdManifest(); break;
default : UsageTopLevel(); }
return S_OK; }
HRESULT GetDir( LPWSTR pszSrc, LPWSTR *ppwzDir, BOOL bExists) { return PathNormalize(pszSrc, ppwzDir, DIRECTORY_PATH, bExists); }
HRESULT GetFile( LPWSTR pszSrc, LPWSTR *ppwzFile, BOOL bExists) { return PathNormalize(pszSrc, ppwzFile, FILE_PATH, bExists); }
/////////////////////////////////////////////////////////////////////////
// ParseCommandLineArgs
/////////////////////////////////////////////////////////////////////////
HRESULT ParseCommandLineArgs(int argc, WCHAR **argv, COMMAND_MODE & CmdMode ) { HRESULT hr = S_OK; LPWSTR pszBuf=NULL;
if(argc < 2) { hr = E_FAIL; goto exit; }
if ( !StrCmpI(argv[1], L"-t")) { CmdMode = CmdTemplate; } else if ( !StrCmpI(argv[1], L"-l")) { CmdMode = CmdList; } else if ( !StrCmpI(argv[1], L"-d")) { CmdMode = CmdDependencyList; } else if ( !StrCmpI(argv[1], L"-s")) { CmdMode = CmdSubscription; } else if ( !StrCmpI(argv[1], L"-m")) { CmdMode = CmdManifest; } else { hr = E_FAIL; goto exit; }
int currArg = 2; LPWSTR pwzParamName; LPWSTR pwzParamValue;
while ( currArg < argc) { pwzParamName = argv[currArg];
if(pwzParamValue = StrChr(pwzParamName, L':')) { *pwzParamValue = L'\0'; pwzParamValue++; }
if( (!pwzParamValue) || !lstrlen(pwzParamValue) ) { if ( StrCmpI(pwzParamName, L"help")) printf(" Param Value not specified for \"%s\" \n", pwzParamName); hr = E_FAIL; goto exit; }
if ( !StrCmpI(pwzParamName, L"sd")) { if(FAILED(hr = GetDir(pwzParamValue, &pszBuf, TRUE))) goto exit;
g_sAppBase.Assign(pszBuf);
g_sDeployDirs[g_dwDeployDirs++].Assign(pszBuf); } else if ( !StrCmpI(pwzParamName, L"td")) { if(FAILED(hr = GetDir(pwzParamValue, &pszBuf, TRUE))) goto exit;
g_sTargetDir.Assign(pszBuf); } else if ( !StrCmpI(pwzParamName, L"dd")) { if(FAILED(hr = GetDir(pwzParamValue, &pszBuf, TRUE))) goto exit;
g_sDeployDirs[g_dwDeployDirs++].Assign(pszBuf); } else if ( !StrCmpI(pwzParamName, L"tf")) { if(FAILED(hr = GetFile(pwzParamValue, &pszBuf, TRUE))) goto exit;
g_sTemplateFile.Assign(pszBuf); } else if ( !StrCmpI(pwzParamName, L"amu")) { g_sAppManifestURL.Assign(pwzParamValue); } else if ( !StrCmpI(pwzParamName, L"si")) { g_sPollingInterval.Assign(pwzParamValue); } else if ( !StrCmpI(pwzParamName, L"smd")) { if(FAILED(hr = GetDir(pwzParamValue, &pszBuf, TRUE))) goto exit;
g_sSubscriptionManifestDir.Assign(pszBuf); } else if ( !StrCmpI(pwzParamName, L"amf")) { if(FAILED(hr = GetFile(pwzParamValue, &pszBuf, TRUE))) goto exit;
g_sAppManifestFile.Assign(pszBuf); } else if ( !StrCmpI(pwzParamName, L"WRN")) { g_bFailOnWarnings = 0; } else if ( !StrCmpI(pwzParamName, L"GAC")) { g_bLookInGACForDependencies = 1; } else if ( !StrCmpI(pwzParamName, L"SYS")) { g_bCopyDependentSystemAssemblies = 1; } else { hr = E_FAIL; goto exit; }
currArg++;
SAFEDELETEARRAY(pszBuf); }
exit:
return hr; }
/////////////////////////////////////////////////////////////////////////
// wmain
/////////////////////////////////////////////////////////////////////////
int __cdecl wmain(int argc, WCHAR **argv) { HRESULT hr = S_OK; BOOL bCoInitialized = TRUE; List<ManifestNode *> ManifestList; List<ManifestNode *> UniqueManifestList; List<LPWSTR> AssemblyFileList[HASHTABLE_SIZE]; List<LPWSTR> RawFiles; DWORD dwType=0; ManifestNode *pManifestNode = NULL; LISTNODE pos; BOOL bListMode = FALSE;
LPWSTR pwzBuf=NULL;
hr = CoInitialize(NULL); if (FAILED(hr)) { bCoInitialized = FALSE; goto exit; }
COMMAND_MODE CmdMode = CmdUsage;
// Parse
if(FAILED(hr = ParseCommandLineArgs(argc, argv, CmdMode))) { UsageCommand(CmdMode); hr = S_OK; goto exit; } // execute
switch(CmdMode) { case CmdTemplate: if(g_sTemplateFile._cc <= 1) { hr = E_INVALIDARG; goto exit; }
hr = CreateAppManifestTemplate(g_sTemplateFile._pwz); break;
case CmdDependencyList:
bListMode = TRUE; // continue with CmdList.....
case CmdList: { if(g_sAppBase._cc <= 1) { hr = E_INVALIDARG; goto exit; }
if(g_sTemplateFile._cc >= 1) { if(FAILED(hr = GetInitialDependencies(g_sTemplateFile._pwz, &ManifestList))) goto exit; }
if(FAILED(hr = FindAllAssemblies(g_sAppBase._pwz, &ManifestList))) goto exit; if(FAILED(hr = TraverseManifestDependencyTrees(&ManifestList, AssemblyFileList, &UniqueManifestList, bListMode))) goto exit; if(FAILED(hr = CrossReferenceFiles(g_sAppBase._pwz, AssemblyFileList, &RawFiles))) goto exit;
if(!bListMode) { if(FAILED(hr = PrintDependencies(&RawFiles, &UniqueManifestList))) goto exit; } } break;
case CmdManifest: { if((g_sAppBase._cc <= 1) || (g_sTemplateFile._cc <= 1) || (g_sTargetDir._cc <= 1)\ || !StrCmpI(g_sAppBase._pwz, g_sTargetDir._pwz)) { hr = E_INVALIDARG; goto exit; }
if(FAILED(hr = GetInitialDependencies(g_sTemplateFile._pwz, &ManifestList))) goto exit; if(FAILED(hr = FindAllAssemblies(g_sAppBase._pwz, &ManifestList))) goto exit; if(FAILED(hr = TraverseManifestDependencyTrees(&ManifestList, AssemblyFileList, &UniqueManifestList, FALSE))) goto exit; if(FAILED(hr = CrossReferenceFiles(g_sAppBase._pwz, AssemblyFileList, &RawFiles))) goto exit; if(FAILED(hr = CopyFilesToTargetDir(&UniqueManifestList, &RawFiles))) goto exit; if(FAILED(hr = CreateXMLAppManifest(g_sTargetDir._pwz, g_sTemplateFile._pwz, &UniqueManifestList, &RawFiles))) goto exit; } break;
case CmdSubscription:
if((g_sAppManifestFile._cc <= 1) || (g_sSubscriptionManifestDir._cc <= 1) || (g_sAppManifestURL._cc <= 1)) { hr = E_INVALIDARG; goto exit; }
if(g_sPollingInterval._cc <= 1) { g_sPollingInterval.Assign(DEFAULT_POLLING_INTERVAL); }
hr = CreateSubscriptionManifest(g_sAppManifestFile._pwz, g_sSubscriptionManifestDir._pwz, g_sAppManifestURL._pwz, g_sPollingInterval._pwz); break;
default : hr = E_FAIL; goto exit; } exit:
// Clean up hash table
for (int i = 0; i < HASHTABLE_SIZE; i++) { pos = AssemblyFileList[i].GetHeadPosition(); while (pos) { pwzBuf = AssemblyFileList[i].GetNext(pos); SAFEDELETEARRAY(pwzBuf); }
AssemblyFileList[i].RemoveAll(); }
//clean up Rawfilelist
pos = RawFiles.GetHeadPosition(); while (pos) { pwzBuf = RawFiles.GetNext(pos); SAFEDELETEARRAY(pwzBuf); } RawFiles.RemoveAll(); // clean up ManifestList
pos = ManifestList.GetHeadPosition(); while (pos) { pManifestNode = ManifestList.GetNext(pos); SAFEDELETE(pManifestNode); } ManifestList.RemoveAll();
// clean up UniqueManifestList
pos = UniqueManifestList.GetHeadPosition(); while (pos) { pManifestNode = UniqueManifestList.GetNext(pos); SAFEDELETE(pManifestNode); } UniqueManifestList.RemoveAll();
if (bCoInitialized) CoUninitialize();
if (FAILED(hr)) { fprintf(stderr, "\nFailed with code 0x%x \n", hr); UsageCommand(CmdMode);
} return hr; }
|